Promote Main to Release Branches #61
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Promote Main to Release Branches | |
| permissions: | |
| contents: write | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| target: | |
| description: "Promote target" | |
| required: true | |
| default: "both" | |
| type: choice | |
| options: | |
| - both | |
| - web | |
| - admin | |
| force_redeploy: | |
| description: "When up to date, skip divergence and print manual redeploy guidance" | |
| required: true | |
| default: false | |
| type: boolean | |
| jobs: | |
| generate_tag: | |
| name: Generate HeadVer Tag | |
| uses: ./.github/workflows/headver-tagging.yml | |
| with: {} | |
| create_release: | |
| name: Create GitHub Release | |
| runs-on: ubuntu-latest | |
| needs: generate_tag | |
| steps: | |
| - uses: actions/checkout@v3 | |
| with: | |
| fetch-depth: 0 | |
| - name: Create Release | |
| uses: ncipollo/release-action@v1 | |
| with: | |
| tag: "v${{ needs.generate_tag.outputs.version }}" | |
| release_name: "Release v${{ needs.generate_tag.outputs.version }}" | |
| body: "Automated release created for build v${{ needs.generate_tag.outputs.version }}" | |
| token: ${{ secrets.GITHUB_TOKEN }} | |
| promote_release_branch: | |
| name: Promote main -> release branch(es) | |
| runs-on: ubuntu-latest | |
| needs: create_release | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Promote main branch to selected release branch(es) | |
| run: | | |
| set -euo pipefail | |
| git fetch origin main | |
| MAIN_SHA=$(git rev-parse origin/main) | |
| TARGET="${{ github.event.inputs.target }}" | |
| FORCE_REDEPLOY="${{ github.event.inputs.force_redeploy }}" | |
| case "$TARGET" in | |
| web) | |
| RELEASE_BRANCHES="release-web" | |
| ;; | |
| admin) | |
| RELEASE_BRANCHES="release-admin" | |
| ;; | |
| both) | |
| RELEASE_BRANCHES="release-web release-admin" | |
| ;; | |
| *) | |
| echo "Unsupported target: $TARGET" >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| { | |
| echo "## Release Promotion" | |
| echo "- Selected target: $TARGET" | |
| echo "- Promoted main SHA: $MAIN_SHA" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| for BRANCH in $RELEASE_BRANCHES; do | |
| git fetch origin "$BRANCH" || true | |
| if git show-ref --verify --quiet "refs/remotes/origin/$BRANCH"; then | |
| RELEASE_SHA=$(git rev-parse "origin/$BRANCH") | |
| else | |
| RELEASE_SHA="" | |
| fi | |
| if [ -z "$RELEASE_SHA" ]; then | |
| git push origin origin/main:"refs/heads/$BRANCH" | |
| { | |
| echo "- $BRANCH: created from main" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| continue | |
| fi | |
| if [ "$MAIN_SHA" = "$RELEASE_SHA" ]; then | |
| if [ "$FORCE_REDEPLOY" = "true" ]; then | |
| { | |
| echo "- $BRANCH: already up to date" | |
| echo " - force_redeploy=true requested" | |
| echo " - skipped empty commit to keep release branch ancestry clean" | |
| echo " - trigger redeploy manually in Vercel if needed" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| continue | |
| fi | |
| { | |
| echo "- $BRANCH: already up to date" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| continue | |
| fi | |
| if ! git merge-base --is-ancestor "origin/$BRANCH" origin/main; then | |
| { | |
| echo "- $BRANCH: non-ancestor detected, forcing reset to main" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| fi | |
| git push --force-with-lease origin origin/main:"refs/heads/$BRANCH" | |
| { | |
| echo "- $BRANCH: updated" | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| done | |
| { | |
| echo "- Note: Vercel production deploy is triggered by corresponding release branch update" | |
| } >> "$GITHUB_STEP_SUMMARY" |