From d8e3fbde3a6e6c75eac1374c92e41295c7179b07 Mon Sep 17 00:00:00 2001 From: Bob Date: Sun, 13 Sep 2026 20:29:16 +0000 Subject: [PATCH 1/2] ci(release): publish GitHub releases instead of leaving them as drafts v0.14.0 sat as a draft until it was published by hand. Classify tags with assert-play-track.sh so 0.x.x stable releases are not marked prerelease. Git-Session-Id: 087828bb-1476-551f-9400-d18d7f6cd6f9 --- .github/workflows/build.yml | 44 +++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 99c69765..c822b39c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -492,11 +492,22 @@ jobs: working-directory: dist run: ls -R - # detect if version tag is stable/beta - - uses: nowsprinting/check-version-format-action@v4 - id: version - with: - prefix: 'v' + # Classify the tag with the same rule as Play-track routing + # (scripts/assert-play-track.sh): X.Y.Z → stable, anything else → pre-release. + # Do not use check-version-format-action here: it treats 0.x.x as unstable + # per semver, but aw-android ships 0.x.x as production. + - name: Classify tag + id: tag + run: | + TAG="${{ github.ref_name }}" + TRACK="$(bash scripts/assert-play-track.sh resolve "$TAG")" + if [[ "$TRACK" == production ]]; then + IS_STABLE=true + else + IS_STABLE=false + fi + echo "is_stable=${IS_STABLE}" >> "$GITHUB_OUTPUT" + echo "Classified ${TAG}: track=${TRACK} is_stable=${IS_STABLE}" - name: Set up Python uses: actions/setup-python@v6 @@ -511,16 +522,7 @@ jobs: # get_latest_release.sh excludes the tag being released, so this # resolves to the previous release. STABLE_ONLY makes a stable release # diff against the last stable one rather than the last beta. - # NOTE: check-version-format-action classifies 0.x.x as not stable per - # semver, but aw-android uses 0.x.x for production releases. Use the - # same regex the release-play job uses to detect stability correctly. - TAG="${{ github.ref_name }}" - VERSION="${TAG#v}" - if [[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then - IS_STABLE="true" - else - IS_STABLE="false" - fi + IS_STABLE="${{ steps.tag.outputs.is_stable }}" LAST_RELEASE=$(STABLE_ONLY=${IS_STABLE} \ .changelog-tools/scripts/get_latest_release.sh) if [ -z "$LAST_RELEASE" ]; then @@ -547,8 +549,16 @@ jobs: - name: Release uses: softprops/action-gh-release@v2 with: - draft: true - prerelease: ${{ !(steps.version.outputs.is_stable == 'true') }} # must compare to true, since boolean outputs are actually just strings, and "false" is truthy since it's not empty: https://github.com/actions/runner/issues/1483#issuecomment-994986996 + # Never create drafts. v0.14.0b2's Play Store "full changelog" link + # pointed at a page non-admins could not see, and v0.14.0 sat as a + # draft until it was published by hand (2026-09-13). Empty bodies + # are already fail-closed above. Pre-releases are marked prerelease + # so they do not steal "Latest release". + draft: false + # Compare to the string 'true': GHA boolean outputs are strings, and + # "false" is truthy because it is non-empty. + # https://github.com/actions/runner/issues/1483#issuecomment-994986996 + prerelease: ${{ steps.tag.outputs.is_stable != 'true' }} files: | dist/*.apk dist/*.aab From 33e3bbe9126692f99468ce9807b324bf6ab6cc30 Mon Sep 17 00:00:00 2001 From: Bob Date: Sun, 13 Sep 2026 20:37:21 +0000 Subject: [PATCH 2/2] fix(ci): pass release tag via env instead of interpolating into bash GITHUB_REF_NAME is already set; interpolating github.ref_name into the script lets a crafted tag inject into the release job. Git-Session-Id: f73bd466-b160-5442-a857-61d58fab9408 --- .github/workflows/build.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c822b39c..48164e93 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -499,15 +499,17 @@ jobs: - name: Classify tag id: tag run: | - TAG="${{ github.ref_name }}" - TRACK="$(bash scripts/assert-play-track.sh resolve "$TAG")" + # Use GITHUB_REF_NAME (already an env var) instead of interpolating + # github.ref_name into the script. Tag names can contain shell + # metacharacters; expression expansion happens before Bash parses. + TRACK="$(bash scripts/assert-play-track.sh resolve "$GITHUB_REF_NAME")" if [[ "$TRACK" == production ]]; then IS_STABLE=true else IS_STABLE=false fi echo "is_stable=${IS_STABLE}" >> "$GITHUB_OUTPUT" - echo "Classified ${TAG}: track=${TRACK} is_stable=${IS_STABLE}" + echo "Classified ${GITHUB_REF_NAME}: track=${TRACK} is_stable=${IS_STABLE}" - name: Set up Python uses: actions/setup-python@v6