Problem
Consumers SHA-pin the hyperi-ci reusable-workflow caller (Renovate
helpers:pinGitHubActionDigests), e.g.
uses: hyperi-io/hyperi-ci/.github/workflows/python-ci.yml@<sha> # v2.6.1.
That is correct supply-chain hygiene, but it means every hyperi-ci release
needs a bump PR in every consumer repo to be picked up — N repos × 1 PR per
release. During active hyperi-ci development that is real churn.
Decision
Adopt a moving major tag @vMAJOR for the first-party hyperi-ci caller
(mirrors actions/checkout@v4). Consumers reference @v2; the release flow
advances v2 to each new release commit; one tag-move rolls every consumer
forward. Minor/patch flow automatically; only a major bump is a deliberate
per-consumer edit.
Chosen over: a per-repo hyperi-ci pin-ci CLI (per-repo fan-out = mini-Renovate,
the bespoke machinery #31 warned against), bare @main (no version gate at all),
and status-quo Renovate SHA-pinning (most PR churn).
Keep Renovate SHA-pinning for third-party actions — that is where pinning
earns its keep. Only the first-party hyperi-ci caller moves to @vMAJOR.
Why it is safe (and what it does not change)
Implementation checklist
Current state (for whoever picks this up)
- Stable release: v2.6.1 (on PyPI). No bare-major tag (
v2) exists yet.
init scaffolds @main (src/hyperi_ci/init.py _WORKFLOW_REF = "main").
- Renovate currently SHA-pins the caller in consumers (see pylib history:
chore(deps): Pin hyperi-io/hyperi-ci action to ...).
- Reusable resolver already exists:
scripts/update-versions.py
(_select_pinned_release, _pinned_spec_for) — version->SHA with cooldown,
if a SHA is ever needed.
References
Problem
Consumers SHA-pin the hyperi-ci reusable-workflow caller (Renovate
helpers:pinGitHubActionDigests), e.g.uses: hyperi-io/hyperi-ci/.github/workflows/python-ci.yml@<sha> # v2.6.1.That is correct supply-chain hygiene, but it means every hyperi-ci release
needs a bump PR in every consumer repo to be picked up — N repos × 1 PR per
release. During active hyperi-ci development that is real churn.
Decision
Adopt a moving major tag
@vMAJORfor the first-party hyperi-ci caller(mirrors
actions/checkout@v4). Consumers reference@v2; the release flowadvances
v2to each new release commit; one tag-move rolls every consumerforward. Minor/patch flow automatically; only a major bump is a deliberate
per-consumer edit.
Chosen over: a per-repo
hyperi-ci pin-ciCLI (per-repo fan-out = mini-Renovate,the bespoke machinery #31 warned against), bare
@main(no version gate at all),and status-quo Renovate SHA-pinning (most PR churn).
Keep Renovate SHA-pinning for third-party actions — that is where pinning
earns its keep. Only the first-party hyperi-ci caller moves to
@vMAJOR.Why it is safe (and what it does not change)
interface gate (
scripts/check-workflow-interfaces.py, in hyperi-ci's Qualityjob) prevents a breaking-
mainchange from reaching a consumer. A per-releaseSHA on the caller adds little tamper-resistance for first-party.
@main(we didnot build the freezer).
@v2only version-gates the top-level workflow;composite/sibling edits already flow live via
@mainand stay gate-protected.So
@v2purely removes update churn — it does not change the floating-internalsmodel.
Implementation checklist
scripts/advance-major-tag.py— derivevNfrom the release version(VERSION file / arg / latest tag), move
vNto the release commit, push(force). Pure logic (major extraction + tag name) unit-tested; git ops covered
with a tmp repo. No bash — Python, like
scripts/update-versions.py..github/workflows/ci.ymlRelease job(after
npx semantic-release). Not in the shared_release-tail.yml—only hyperi-ci is consumed as a reusable workflow. Needs
contents: write(already present) + a token allowed to move tags.
init: scaffold@vNinstead of@main. DeriveNfrom__version__major (
_WORKFLOW_REF = f"v{__version__.split('.')[0]}") so it auto-tracks.Update
_render_workflowtest.hyperi-io/renovate-config, governed from hyperi-ci):add a
packageRulethat excludeshyperi-io/hyperi-cireusable-workflowrefs from digest-pinning (keep them on the moving tag, allow major-tag bumps).
Third-party digest-pinning unchanged.
v2tag at the current release (no bare-major tagexists yet) so consumers can switch immediately.
@<sha>/@main->@v2(pylib, rustlib, dfe-*).docs/dependencies/WORKFLOW-PINNING.md(add the@vMAJORfirst-partycaller policy),
docs/dependencies/DEPS-PINNING.md(first-party caller is theone exception to SHA-pinning), and the
initnotes in README/ARCHITECTURE.Current state (for whoever picks this up)
v2) exists yet.initscaffolds@main(src/hyperi_ci/init.py_WORKFLOW_REF = "main").chore(deps): Pin hyperi-io/hyperi-ci action to ...).scripts/update-versions.py(
_select_pinned_release,_pinned_spec_for) — version->SHA with cooldown,if a SHA is ever needed.
References
docs/dependencies/WORKFLOW-PINNING.md(issue Reusable workflows pin siblings at @main, defeating consumer SHA-pinning (breaking-main changes cause startup failures) #31, gate-only)docs/dependencies/DEPS-PINNING.md