From bed550889b6626888bf81c8bf6685d892f9acd14 Mon Sep 17 00:00:00 2001 From: fadeltd Date: Thu, 24 Sep 2026 14:54:20 +0700 Subject: [PATCH] Fix the Release workflow re-run failure; ignore .env The first real release run failed, and the cause is worth recording because the symptom pointed somewhere else. The workflow checked out `github.sha` -- the commit that triggered the run -- rather than the branch tip. Attempt 1 committed the changelog and pushed main successfully, so main advanced. Attempts 2 and 3 then re-ran from that now stale sha, committed on top of it, and were correctly rejected as non-fast-forward. The visible error was "tip of your current branch is behind its remote counterpart", which reads like a race but was really the checkout pinning an old base. Two changes: - Check out `ref: main`. Combined with the changelog logic already being idempotent -- an empty [Unreleased] releases nothing -- a re-run is now a no-op rather than a guaranteed failure. - Guard each push separately, so a partially-completed attempt resumes. The previous version pushed the branch and the tag in one unguarded sequence, so a failure between them left a state where every retry failed on the first push and never reached the tag. That is exactly what happened: main carries the release commit, but v0.2.0 was never tagged and so nothing deployed. Also ignores .env. It is not currently tracked and never has been -- verified against the remote -- but the repository is public now, and an untracked .env sitting in the working tree is the classic accidental commit. --- .github/workflows/release.yml | 38 +++++++++++++++++++++++++++-------- .gitignore | 7 +++++++ CHANGELOG.md | 9 ++++++++- 3 files changed, 45 insertions(+), 9 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9ce0032..f1ca4a4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,6 +33,12 @@ jobs: steps: - uses: actions/checkout@v7 with: + # Check out the BRANCH TIP, not the commit that triggered the run. + # On a re-run the triggering sha is stale, and committing on top of it + # produces a non-fast-forward push that is rejected. Combined with the + # changelog logic being idempotent -- an empty [Unreleased] releases + # nothing -- this makes a re-run safe rather than broken. + ref: main fetch-depth: 0 token: ${{ secrets.RELEASE_TOKEN || secrets.GITHUB_TOKEN }} @@ -49,16 +55,31 @@ jobs: - name: Commit the changelog and tag if: steps.cut.outputs.released == 'true' + env: + TAG: ${{ steps.cut.outputs.tag }} run: | + set -euo pipefail git config user.name "github-actions[bot]" git config user.email "41898282+github-actions[bot]@users.noreply.github.com" - git add CHANGELOG.md package.json - # [skip ci] so this push cannot re-enter this workflow when a PAT is - # in use -- with a PAT, pushes DO trigger workflows. - git commit -m "Release ${{ steps.cut.outputs.tag }} [skip ci]" - git tag -a "${{ steps.cut.outputs.tag }}" -m "${{ steps.cut.outputs.tag }}" - git push origin HEAD:main - git push origin "${{ steps.cut.outputs.tag }}" + + # Each push is guarded, so a partially-completed earlier attempt can + # be resumed rather than blocking every retry. + if git diff --quiet -- CHANGELOG.md package.json; then + echo "::notice::Changelog and version already committed." + else + git add CHANGELOG.md package.json + # [skip ci] so this push cannot re-enter this workflow when a PAT + # is in use -- with a PAT, pushes DO trigger workflows. + git commit -m "Release ${TAG} [skip ci]" + git push origin HEAD:main + fi + + if git ls-remote --exit-code --tags origin "refs/tags/${TAG}" >/dev/null 2>&1; then + echo "::notice::${TAG} already exists on the remote." + else + git tag -a "${TAG}" -m "${TAG}" + git push origin "${TAG}" + fi - name: Create the GitHub release if: steps.cut.outputs.released == 'true' @@ -67,7 +88,8 @@ jobs: run: | gh release create "${{ steps.cut.outputs.tag }}" \ --title "${{ steps.cut.outputs.tag }}" \ - --notes "${{ steps.cut.outputs.notes }}" + --notes "${{ steps.cut.outputs.notes }}" \ + || echo "::notice::Release already exists." # Only needed while no PAT is configured; with one, the tag push above # has already started Deploy. diff --git a/.gitignore b/.gitignore index c50dd73..7306d56 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,10 @@ design/ .wrangler/ *.local .DS_Store + +# Local environment files. Nothing in this project needs them at runtime -- +# the app has no backend and no secrets -- but an untracked .env is exactly the +# kind of thing that gets committed by accident on a public repo. +.env +.env.* +!.env.example diff --git a/CHANGELOG.md b/CHANGELOG.md index 242ac36..d59aecc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,14 @@ this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [Unreleased] -Nothing yet. +### Fixed +- The Release workflow checked out the commit that triggered it rather than the + branch tip, so any re-run built on a stale base and its push was rejected as + a non-fast-forward. It now checks out `main`, and each push is guarded so a + partially-completed attempt resumes instead of blocking every retry. +- `.env` is now ignored. Nothing here needs one — the app has no backend and no + runtime secrets — but an untracked `.env` is exactly what gets committed by + accident on a public repository. ## [0.2.0] — 2026-09-24