Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 30 additions & 8 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 }}

Expand All @@ -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'
Expand All @@ -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.
Expand Down
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Loading