1+ name : Release Gate
2+
3+ on :
4+ pull_request :
5+ types : [closed]
6+ branches : [main]
7+
8+ jobs :
9+ release-gate :
10+ name : Tag and update release branches
11+ runs-on : ubuntu-latest
12+ # Only run when a release/ branch is merged (not just closed)
13+ if : |
14+ github.event.pull_request.merged == true &&
15+ startsWith(github.event.pull_request.head.ref, 'release/v')
16+
17+ permissions :
18+ contents : write
19+
20+ steps :
21+ - uses : actions/create-github-app-token@v1
22+ id : app-token
23+ with :
24+ app-id : ${{ secrets.APP_ID }}
25+ private-key : ${{ secrets.APP_PRIVATE_KEY }}
26+
27+ - uses : actions/checkout@v4
28+ with :
29+ # Full history required for version comparison against existing tags
30+ # and for the fast-forward push to stable/beta.
31+ fetch-depth : 0
32+ token : ${{ steps.app-token.outputs.token }}
33+
34+ - name : Extract and validate version
35+ id : version
36+ run : |
37+ BRANCH="${{ github.event.pull_request.head.ref }}"
38+ NEW_VERSION="${BRANCH#release/}"
39+ echo "new=${NEW_VERSION}" >> $GITHUB_OUTPUT
40+
41+ # Determine if this is an RC
42+ if echo "$NEW_VERSION" | grep -qE '\-rc[0-9]+$'; then
43+ echo "is_rc=true" >> $GITHUB_OUTPUT
44+ else
45+ echo "is_rc=false" >> $GITHUB_OUTPUT
46+ fi
47+
48+ - name : Validate version is strictly increasing
49+ run : |
50+ NEW_VERSION="${{ steps.version.outputs.new }}"
51+
52+ # Get the latest tag; if none exist yet, skip the comparison
53+ LATEST_TAG=$(git tag --list 'v*' --sort=-version:refname | head -n1)
54+ if [ -z "$LATEST_TAG" ]; then
55+ echo "No existing tags found — skipping version comparison"
56+ exit 0
57+ fi
58+
59+ LATEST_VERSION="${LATEST_TAG#v}"
60+
61+ python3 - <<EOF
62+ import sys
63+ from packaging.version import Version
64+
65+ def normalize(v):
66+ # Convert vX.Y.Z-rcQ → X.Y.ZrcQ (PEP 440)
67+ return v.replace("-rc", "rc")
68+
69+ new = Version(normalize("$NEW_VERSION"))
70+ latest = Version(normalize("$LATEST_VERSION"))
71+
72+ print(f"Latest tag : {latest}")
73+ print(f"New version: {new}")
74+
75+ if new <= latest:
76+ print(f"\n❌ {new} is not strictly greater than current {latest}")
77+ sys.exit(1)
78+
79+ print(f"\n✅ Version order is valid")
80+ EOF
81+
82+ - name : Configure git
83+ run : |
84+ git config user.name "commit-boost-release-bot[bot]"
85+ git config user.email "commit-boost-release-bot[bot]@users.noreply.github.com"
86+
87+ - name : Create and push tag
88+ run : |
89+ VERSION="${{ steps.version.outputs.new }}"
90+ git tag "$VERSION" HEAD
91+ git push origin "$VERSION"
92+ # Branch fast-forwarding happens in release.yml after all artifacts
93+ # are successfully built. stable/beta are never touched if the build fails.
0 commit comments