Skip to content

ci(release): let the floating-tag job run on a dispatch, and say what it covers - #31

Merged
vyncint merged 1 commit into
mainfrom
fix/float-tag-dispatchable
Aug 26, 2026
Merged

ci(release): let the floating-tag job run on a dispatch, and say what it covers#31
vyncint merged 1 commit into
mainfrom
fix/float-tag-dispatchable

Conversation

@vyncint

@vyncint vyncint commented Aug 26, 2026

Copy link
Copy Markdown
Owner

Closes #30.

The ruleset half (already applied)

protect-release-tags covered refs/tags/v* — both kinds of tag, which want opposite treatment:

tag what it is immutable?
v2.0.0 names a published, immutable set of crates yes
v2 a pointer whose contract is to move no

Protecting the pointer against being moved is why float-major-tag had never once worked. 2.0.0 was its first run — on a creation, the case only a major bump produces — and it was rejected outright:

remote: error: GH013: Repository rule violations found for refs/tags/v2.
remote: - Cannot create ref due to creations being restricted.

Narrowed to refs/tags/v*.*.*. Every existing release tag (v1.0.0 … v2.0.0) keeps creation/update/deletion/non-fast-forward protection; v1 and v2 fall outside, so the job needs no bypass. Rules, enforcement and the admin bypass are byte-identical — only the condition changed.

I chose this over adding the Actions bot to the bypass actors, which would have handed the workflow the ability to delete or rewrite a release tag — a strictly larger permission than the problem needs.

The workflow half (this PR)

float-major-tag was gated on push && ref_type == 'tag', so the resume path RELEASING documents — "part-way through the eight crates: re-run release.yml by dispatch" — skipped it. A resumed release finished with @vN still on the previous version, which is precisely what the job exists to prevent. That hole is independent of the ruleset and would have outlived it.

It now runs on dispatch too, given the tag it is finishing. A dispatch can be handed anything, so the tag is checked to exist and to look like a release tag before a floating pointer is aimed at it.

Verification

actionlint clean. I will dispatch it against v2.0.0 after merge — it is idempotent (publish skips what is on the registry, and re-pointing v2 at the commit it already names is a no-op), and it is the only way to prove the bot can now move the tag, since I hold the admin bypass myself and my own push proves nothing.

Checklist

  • All commits signed off
  • No AI attribution trailers
  • docs/RELEASING.md updated — the dispatch input, and why the ruleset stops where it does

… it covers

`float-major-tag` could only run on a tag push, so the resume path
RELEASING documents — "part-way through the eight crates: re-run
release.yml by dispatch" — skipped it. A resumed release therefore
finished with `@vN` still pointing at the previous version, which is the
exact failure the job was added to prevent.

It now runs on a dispatch too, given the tag it is finishing. A dispatch
can be handed anything, so the tag is checked to exist and to look like a
release tag before a floating pointer is aimed at it.

The other half is the ruleset. `protect-release-tags` covered
`refs/tags/v*`, which is both kinds of tag, and they want opposite
treatment: `v2.0.0` names a published, immutable set of crates, while
`v2` is a pointer whose entire contract is to move. Protecting the
pointer against being moved is why the job had never once worked —
2.0.0 was its first run, on a creation, and it was rejected outright.

Narrowed to `refs/tags/v*.*.*`. Release tags keep every protection they
had; the floating majors fall outside, so the job needs no bypass. The
alternative — adding the Actions bot to the bypass actors — would have
handed the workflow the ability to delete or rewrite a *release* tag,
which is a strictly larger permission than the problem needs.

RELEASING now documents both, including that 2.0.0's `v2` was pushed by
hand, so the next person does not rediscover it.

Closes #30.

Signed-off-by: Vyncint Ng <115854244+vyncint@users.noreply.github.com>
@vyncint
vyncint merged commit 4727e8f into main Aug 26, 2026
8 checks passed
@vyncint
vyncint deleted the fix/float-tag-dispatchable branch August 26, 2026 12:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

float-major-tag has never worked: the tag ruleset blocks the bot from the tags it exists to move

1 participant