Skip to content

Commit 19c2d27

Browse files
authored
ci(release): block a release tag whose versions do not match the tag (#605)
Adds scripts/release/check-versions.sh and runs it as a gating verify-versions job in all three *-release workflows (android, macos, windows); each build job now needs: verify-versions, so a vX.Y.Z tag whose baked-in versions disagree with the tag is blocked before any artifact is built. Checks all seven surfaces: VERSION, the three service crates, apps/android VERSION_NAME, apps/ios MARKETING_VERSION, apps/desktop-flutter pubspec. Invoked via bash (no exec-bit dependency). No-op on non-tag refs so the manual re-ship (workflow_dispatch) paths keep working. This is the permanent guard against the 0.1.x-era version-drift mistake; verified passing against the current 0.2.0 tree and failing on a wrong tag. Signed-off-by: badbread <badbread@users.noreply.github.com> Co-authored-by: badbread <badbread@users.noreply.github.com>
1 parent b35c0f8 commit 19c2d27

4 files changed

Lines changed: 98 additions & 0 deletions

File tree

.github/workflows/android-release.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,20 @@ permissions:
4646
contents: write # to create/update the GitHub Release and upload the APK
4747

4848
jobs:
49+
# Guard: a vX.Y.Z tag whose baked-in versions disagree with the tag must never
50+
# ship. Runs on every release workflow; the build job below `needs:` it, so a
51+
# mismatch blocks the release before anything is built. No-op on non-tag refs.
52+
verify-versions:
53+
name: verify versions match the tag
54+
runs-on: ubuntu-latest
55+
steps:
56+
- uses: actions/checkout@v4
57+
- name: All version surfaces must equal the release tag
58+
run: bash scripts/release/check-versions.sh
59+
4960
build-and-sign:
5061
name: build + sign release APK
62+
needs: verify-versions
5163
# Signing a release APK needs the keystore secrets (see the header). Until
5264
# they're configured, gate the job off via the ANDROID_RELEASE_ENABLED repo
5365
# variable so a v* tag doesn't fail — it skips cleanly. Set the variable to

.github/workflows/macos-release.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,19 @@ permissions:
2424
contents: write # attach the app zip to the GitHub Release (tag builds)
2525

2626
jobs:
27+
# Guard: block the release if any version surface disagrees with the tag.
28+
# No-op on non-tag refs (workflow_dispatch). See scripts/release/check-versions.sh.
29+
verify-versions:
30+
name: verify versions match the tag
31+
runs-on: ubuntu-latest
32+
steps:
33+
- uses: actions/checkout@v4
34+
- name: All version surfaces must equal the release tag
35+
run: bash scripts/release/check-versions.sh
36+
2737
build:
2838
name: build macOS app
39+
needs: verify-versions
2940
runs-on: macos-latest
3041
defaults:
3142
run:

.github/workflows/windows-release-flutter.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,19 @@ permissions:
2929
contents: write # attach the zip to the GitHub Release on tag builds
3030

3131
jobs:
32+
# Guard: block the release if any version surface disagrees with the tag.
33+
# No-op on non-tag refs (workflow_dispatch). See scripts/release/check-versions.sh.
34+
verify-versions:
35+
name: verify versions match the tag
36+
runs-on: ubuntu-latest
37+
steps:
38+
- uses: actions/checkout@v4
39+
- name: All version surfaces must equal the release tag
40+
run: bash scripts/release/check-versions.sh
41+
3242
build:
3343
name: build Windows (Flutter)
44+
needs: verify-versions
3445
runs-on: windows-latest
3546
defaults:
3647
run:

scripts/release/check-versions.sh

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#!/usr/bin/env bash
2+
#
3+
# Release version guard.
4+
#
5+
# Verifies that EVERY version surface in the repo matches the release tag, so a
6+
# `vX.Y.Z` tag can never ship artifacts whose baked-in version disagrees with the
7+
# tag. This is the guard against the 0.1.x-era "the app versions did not match the
8+
# tag" class of mistake. The three *-release.yml workflows run this as a gating
9+
# job and their build jobs `needs:` it, so a mismatch blocks the release before a
10+
# single artifact is built.
11+
#
12+
# Usage:
13+
# scripts/release/check-versions.sh v0.2.0 # explicit tag
14+
# scripts/release/check-versions.sh # reads $GITHUB_REF_NAME (CI)
15+
#
16+
# On a ref that is not a vX.Y.Z tag (e.g. a workflow_dispatch run from a branch)
17+
# it is a no-op success, so the manual re-ship paths keep working.
18+
set -euo pipefail
19+
20+
tag="${1:-${GITHUB_REF_NAME:-}}"
21+
want="${tag#v}"
22+
23+
if [[ ! "$want" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
24+
echo "ref '${tag:-<none>}' is not a vX.Y.Z release tag; nothing to check."
25+
exit 0
26+
fi
27+
28+
root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
29+
fail=0
30+
31+
check() { # label actual expected
32+
if [[ "$2" == "$3" ]]; then
33+
printf 'ok %-30s %s\n' "$1" "$2"
34+
else
35+
printf 'FAIL %-30s got %s, expected %s\n' "$1" "${2:-<empty>}" "$3"
36+
fail=1
37+
fi
38+
}
39+
40+
check "VERSION" \
41+
"$(tr -d ' \t\r\n' < "$root/VERSION")" "$want"
42+
43+
for c in api common recorder; do
44+
check "services/$c Cargo.toml" \
45+
"$(grep -m1 '^version' "$root/services/$c/Cargo.toml" | sed -E 's/.*"([^"]+)".*/\1/')" "$want"
46+
done
47+
48+
check "android VERSION_NAME" \
49+
"$(grep -m1 '^VERSION_NAME=' "$root/apps/android/version.properties" | cut -d= -f2 | tr -d ' \r')" "$want"
50+
51+
check "ios MARKETING_VERSION" \
52+
"$(grep -m1 'MARKETING_VERSION' "$root/apps/ios/project.yml" | sed -E 's/.*MARKETING_VERSION:[[:space:]]*"?([0-9]+\.[0-9]+\.[0-9]+)"?.*/\1/')" "$want"
53+
54+
check "flutter pubspec" \
55+
"$(grep -m1 '^version:' "$root/apps/desktop-flutter/pubspec.yaml" | sed -E 's/^version:[[:space:]]*([0-9]+\.[0-9]+\.[0-9]+).*/\1/')" "$want"
56+
57+
echo
58+
if [[ "$fail" -ne 0 ]]; then
59+
echo "Release version guard FAILED for tag $tag."
60+
echo "Bump every surface listed above to $want in the SAME commit you tag,"
61+
echo "then re-tag. See apps/android/version.properties for the per-surface steps."
62+
exit 1
63+
fi
64+
echo "Release version guard passed: all surfaces at $want."

0 commit comments

Comments
 (0)