feat(ci): advance v1 automatically once the gate is green on main
Nothing moved v1 when main advanced, so a merged change was inert until someone remembered to retag by hand — it happened on 2026-09-22 (PR #25 merged, v1 stayed on the previous release) and was only caught because a person asked whether the tag had moved. Option 1 from gitdan-actions#27 (automate it) over option 2 (fail loud while it lags): a `release-tag` job, gated with `needs: selftest` so a broken build never reaches it, force-moves v1 to the pushed commit using the run's built-in GITHUB_TOKEN. If that token turns out not to have write access, the push fails and the job goes red in the Actions UI — a loud failure either way, not the silent one this replaces. Whether the token actually has write access here is unverified short of a real merge; that merge is the next step for this branch. README's Versioning section documented the old manual step as a deliberate decision "never something a merge does by itself" — that claim is now false, so it's rewritten to describe the automated job and keeps the manual command as the recovery path for when the job can't push. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UkSjXXtU6JYcN2vPntWhfb
This commit is contained in:
@@ -101,3 +101,33 @@ jobs:
|
||||
# file.
|
||||
- name: Selftests
|
||||
run: bash scripts/selftest.sh
|
||||
|
||||
release-tag:
|
||||
name: move v1 to main
|
||||
# `needs:` is what makes this "after the gate is green" rather than
|
||||
# merely "after a push": a failed selftest skips this job outright, so
|
||||
# v1 can never advance onto a broken build. The `if:` restricts it to an
|
||||
# actual push to main -- a pull_request run targeting main shares this
|
||||
# workflow but has no ref worth tagging.
|
||||
needs: selftest
|
||||
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' }}
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 2
|
||||
# Requests write access from the run's built-in token (see README's
|
||||
# Versioning section for what's actually verified about it). Without
|
||||
# this the checkout below still succeeds -- it's the push that would be
|
||||
# rejected, which is a red job, not a silent no-op.
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# Lightweight tag, matching what v1 already is (`git cat-file -t v1`
|
||||
# reports `commit`, not `tag`) -- no identity needed to move it, only
|
||||
# to push it.
|
||||
- name: Force v1 to this commit
|
||||
run: |
|
||||
git tag -f v1 "${{ github.sha }}"
|
||||
git push --force origin v1
|
||||
|
||||
@@ -634,13 +634,20 @@ entry, another permission — is a `v2`, not a `v1` move. Everything else moves
|
||||
`v1`: correctness fixes, new optional inputs, and anything internal to
|
||||
`scripts/`.
|
||||
|
||||
**Moving the tag is a release step, and it is the operator's.** Merging to
|
||||
`main` ships nothing to anybody. `v1` is a lightweight tag and does not follow
|
||||
a branch, so until it is re-pointed every consumer keeps fetching the commit it
|
||||
already named, whatever `main` now says. The gap is deliberate: re-pointing
|
||||
`v1` changes what another repository's CI executes on its next run, so it is a
|
||||
decision taken once, knowingly, after the merge — never something a merge does
|
||||
by itself.
|
||||
**Moving the tag is automatic, gated on the same build that gates a PR.** A
|
||||
`release-tag` job in `.gitea/workflows/ci.yaml` runs on every push to `main`,
|
||||
`needs: selftest`, and force-moves `v1` to that commit once selftest
|
||||
succeeds — a broken build never reaches it, so `v1` can't advance onto one.
|
||||
It pushes with the run's built-in `GITHUB_TOKEN`; if that token turns out not
|
||||
to have write access, the push step fails and the job goes red in the Actions
|
||||
UI. That's a loud failure, not the silent one this replaced: `v1` stays put,
|
||||
and nobody has to notice on their own that it lagged.
|
||||
|
||||
This used to be a manual step, treated as a deliberate release decision taken
|
||||
once, knowingly, after the merge — in practice it was still forgotten
|
||||
(gitdan-actions#27): PR #25 merged to `main` and `v1` stayed on the previous
|
||||
release until someone asked whether it had moved. The manual form below is
|
||||
now the recovery path, for when the automated job can't push:
|
||||
|
||||
```bash
|
||||
git fetch origin
|
||||
@@ -651,9 +658,8 @@ git ls-remote --tags origin v1 # must equal git rev-parse origin/main
|
||||
|
||||
**Downstream** are emowheel, which pins `cargo-cache@v1` and
|
||||
`cargo-cache-publish@v1` across its CI workflow, and zemyna, migrating to the
|
||||
same pin. Both pick a move up on their next run with no change on their side,
|
||||
which is the whole point of the moving pointer and also the reason the move is
|
||||
not automatic.
|
||||
same pin. Both pick a move up automatically on their next run with no change
|
||||
on their side, which is the whole point of the moving pointer.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user