From 86feb919221acaba6ae981bf29c09c534979ca61 Mon Sep 17 00:00:00 2001 From: Bryant Liu Date: Sat, 13 Jun 2026 23:49:45 +0800 Subject: [PATCH 1/4] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20(release-python):=20Ex?= =?UTF-8?q?tract=20tag=20=E2=86=92=20PEP=20440=20conversion=20into=20a=20r?= =?UTF-8?q?eusable=20script?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the sed-based agent-assembly tag → PEP 440 version conversion out of the release-python.yml `resolve` job's inline bash and into a single sourceable script `.github/scripts/tag-to-pep440.sh` exposing `tag_to_pep440 `. This makes the conversion the unit-under-test for the AAASM-2863 follow-up test harness rather than a copy of the regex. Refs AAASM-2863. --- .github/scripts/tag-to-pep440.sh | 44 ++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100755 .github/scripts/tag-to-pep440.sh diff --git a/.github/scripts/tag-to-pep440.sh b/.github/scripts/tag-to-pep440.sh new file mode 100755 index 00000000..07b74f85 --- /dev/null +++ b/.github/scripts/tag-to-pep440.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# +# Convert an agent-assembly release tag to a PEP 440 version string. +# +# Examples: +# v0.0.1 -> 0.0.1 +# v0.0.1-alpha.8 -> 0.0.1a8 +# v0.0.1-beta.2 -> 0.0.1b2 +# v0.0.1-rc.3 -> 0.0.1rc3 +# +# Usage (CLI): +# .github/scripts/tag-to-pep440.sh v0.0.1-alpha.8 +# +# Usage (library — preferred from CI/workflows): +# source .github/scripts/tag-to-pep440.sh +# pypi_version="$(tag_to_pep440 "v0.0.1-alpha.8")" +# +# This is the single source of truth for the conversion. The +# release-python.yml `resolve` job sources this file so the test +# harness exercises the exact code path the workflow runs. +# +# Owner: python-sdk release pipeline (AAASM-2857, hardened in AAASM-2863). + +# Conversion function. Reads the tag from $1 and prints the PEP 440 form +# to stdout. Returns non-zero only if the input is empty (sed itself is +# a pure transformation; unknown pre-release shapes are passed through +# unchanged so callers can layer their own validation). +tag_to_pep440() { + local tag="${1-}" + if [[ -z "$tag" ]]; then + echo "tag_to_pep440: missing tag argument" >&2 + return 1 + fi + local stripped="${tag#v}" + printf '%s\n' "$stripped" | sed -E 's/-alpha\.([0-9]+)/a\1/; s/-beta\.([0-9]+)/b\1/; s/-rc\.([0-9]+)/rc\1/' +} + +# When executed directly (not sourced), behave as a CLI: take the tag +# as $1 and print the converted version. When sourced, define the +# function only and let the caller drive it. +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + set -euo pipefail + tag_to_pep440 "${1-}" +fi From 26b75e14c2ad7d3ad9f3dc7c503f0618e2cf2acd Mon Sep 17 00:00:00 2001 From: Bryant Liu Date: Sat, 13 Jun 2026 23:50:42 +0800 Subject: [PATCH 2/4] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20(release-python):=20So?= =?UTF-8?q?urce=20tag=20=E2=86=92=20PEP=20440=20helper=20from=20resolve=20?= =?UTF-8?q?job?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the inline sed in the `resolve` job's repository_dispatch branch with a `source` + call into the new `.github/scripts/tag-to-pep440.sh` helper. Adds the matching `actions/checkout@v6` step so the working tree is on disk for the source call (the job previously did not check out). Conversion semantics are unchanged — the helper holds the same sed expression byte-for-byte. The win is that the AAASM-2863 unit tests now exercise the exact code path the workflow runs. Refs AAASM-2863. --- .github/workflows/release-python.yml | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release-python.yml b/.github/workflows/release-python.yml index a7ecaf9e..db164e42 100644 --- a/.github/workflows/release-python.yml +++ b/.github/workflows/release-python.yml @@ -52,6 +52,11 @@ jobs: pypi_version: ${{ steps.r.outputs.pypi_version }} dry_run: ${{ steps.r.outputs.dry_run }} steps: + # Need the working tree on disk so the resolve step can source the + # tag → PEP 440 conversion script (.github/scripts/tag-to-pep440.sh). + # That script is the single source of truth for the conversion, + # shared with the AAASM-2863 unit tests. + - uses: actions/checkout@v6 - id: r env: EVENT_NAME: ${{ github.event_name }} @@ -79,9 +84,12 @@ jobs: # Convert agent-assembly tag (e.g. v0.0.1-alpha.8) to PEP 440 form # (0.0.1a8). Mirrors the sync-version-from-dispatch composite action # so the repository_dispatch path produces identical wheel + version - # state to today. - stripped="${DISPATCH_PAYLOAD_TAG#v}" - pypi_version=$(echo "$stripped" | sed -E 's/-alpha\.([0-9]+)/a\1/; s/-beta\.([0-9]+)/b\1/; s/-rc\.([0-9]+)/rc\1/') + # state to today. The conversion lives in a sourceable script so + # the AAASM-2863 unit tests exercise the same code path this + # workflow runs (instead of a copy of the regex). + # shellcheck source=.github/scripts/tag-to-pep440.sh + source "${GITHUB_WORKSPACE}/.github/scripts/tag-to-pep440.sh" + pypi_version="$(tag_to_pep440 "$DISPATCH_PAYLOAD_TAG")" # repository_dispatch is always a real publish — it is fired by # agent-assembly after a real upstream release. dry_run="false" From ceb9cf2b490fcd83db562ab95841a1774f72583c Mon Sep 17 00:00:00 2001 From: Bryant Liu Date: Sat, 13 Jun 2026 23:51:28 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E2=9C=85=20(release-python):=20Add=20test?= =?UTF-8?q?=20for=20tag=20=E2=86=92=20PEP=20440=20conversion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cover the six AAASM-2863 fixture categories — stable, alpha (single + double digit), beta, rc, and multi-digit base version with a large pre-release counter — by sourcing the same helper the workflow runs. Adds extra coverage for the v-prefix-only case, unknown pre-release types passing through, multi-digit beta/rc counters, and the empty-input fail-fast guard the workflow depends on to avoid emitting an empty pypi_version. Runnable locally with `bash .github/scripts/test_tag_to_pep440.sh`; CI wiring follows in a separate commit. Refs AAASM-2863. --- .github/scripts/test_tag_to_pep440.sh | 110 ++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100755 .github/scripts/test_tag_to_pep440.sh diff --git a/.github/scripts/test_tag_to_pep440.sh b/.github/scripts/test_tag_to_pep440.sh new file mode 100755 index 00000000..beb073fb --- /dev/null +++ b/.github/scripts/test_tag_to_pep440.sh @@ -0,0 +1,110 @@ +#!/usr/bin/env bash +# +# Unit tests for `.github/scripts/tag-to-pep440.sh`. +# +# Exercises the conversion function that release-python.yml's `resolve` +# job sources to turn an agent-assembly release tag into a PEP 440 +# version string. Because the workflow sources the same file, these +# tests cover the actual code path CI runs, not a copy of the regex. +# +# Run locally: +# bash .github/scripts/test_tag_to_pep440.sh +# +# Run from CI: see .github/workflows/release-python-conversion-test.yml. +# +# Exits 0 when every fixture passes, 1 otherwise. Prints a per-fixture +# OK/FAIL line plus a final pass/fail/total summary. +# +# Refs AAASM-2863. + +set -uo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +# shellcheck source=.github/scripts/tag-to-pep440.sh +source "${SCRIPT_DIR}/tag-to-pep440.sh" + +pass=0 +fail=0 +total=0 + +# assert_eq