refactor: bake toolkit_ref into _release.yml at build time (eliminate the consumer-side duplication) #148
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit#148
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The substrate-honest gap
Today's consumer
release.ymlspecifies the toolkit ref twice:The "MUST match the @ref above" comment is the smoking gun: the consistency between
uses: @refandtoolkit_ref: refis enforced by convention, not by construction. A consumer who mismatches them (intentionally or by typo) gets a silently-inconsistent workflow run (the reusable file is loaded from one ref, but the toolkit scripts are checked out at another).Why I ruled out the context-var path first
Initial hypothesis: maybe the reusable can self-discover its own ref via a context variable (
github.workflow_ref/github.action_ref/ etc.), eliminating the duplication without any build-time machinery.Empirical probe on 2026-06-27 (branch
i/probe-reusable-context, captured in tracker #1 comment) showed:github.workflow_refinside a reusable points at the CALLER's workflow + ref, NOT the reusable's. For an external consumer's cut, the reusable would seecellblock/release.yml@main— notfrankenbit/release-toolkit/_release.yml@v0.11.0. The toolkit ref isn't in the context vars at all.This matches GitHub Actions documented behavior for reusable workflows;
github.action_refpopulates for step-level actions but not for workflow_call reusables. Substrate-feature gap, not substrate-honest-debt.The proposed fix (operator engagement 2026-06-27)
Bake the ref directly into
_release.ymlat build time. The cut'srelease-prep.shrewrites the marker-anchored value in_release.ymlBEFORE creating the prep commit; the tag for that cut version then points at a commit whose_release.ymlhas the matching ref baked in.Mechanism
_release.ymlgains a hardcodedref:(noinputs.toolkit_reflookup), anchored by a marker comment:release-prep.shgains a step that rewrites the marker-anchored value to match the next-version BEFORE the prep commit:Same edits to
_manifest-check.yml.Consumer's wrapper drops
toolkit_refentirely:Why this is better than the input-based design
uses: @refand toolkit checkoutImplementation surface
.forgejo/workflows/_release.yml+_manifest-check.yml: hardcoded ref + remove thetoolkit_refworkflow_call input declarationscripts/release-prep.sh: new sed step rewrites the marker-anchored ref to$NEXT_VERSIONbefore the prep commitrelease.yml+manifest-check.yml): drop thetoolkit_ref:linedocs/integration.md: quick-start template updatedscripts/check-self-bootstrap.sh: switch from readingtoolkit_ref:inrelease.ymlto reading@<ref>fromuses:line (single source of truth alignment)tests/check-self-bootstrap.bats: update fixture for the new reading pathEstimated scope: ~6 files modified + ~30 bats lines + ~20 lines in release-prep.sh. Roughly one PR cycle.
Composition
release.ymlneeds thetoolkit_ref:line dropped on next upgrade — matches the next version bump anyway, so no extra cycles.uses: @<ref>line as the single source of truth instead of cross-checking againsttoolkit_ref:.What this PR does NOT do
runs_on: per probe (B), the vars-based route has timing quirks; theruns_onworkflow_call input stays for clarity.toolkit_ref: zero pre-refactor adopters need backwards-compat (cellblock will update on next bump anyway).Refs
github.workflow_refempirical resolutionuses: @ref#172quartermaster referenced this issue2026-06-27 14:27:35 +02:00
quartermaster referenced this issue2026-06-27 14:38:13 +02:00
Closing — Phase-1 (build-bake mechanism) shipped earlier; Phase-2 (drop
toolkit_refinput + structural collapse of resolve-ref + detached-bake at re-pin viascripts/repin.sh) shipped via #172/#222 + the post-merge self-bootstrap loop validated via #224. The structural single-source-of-truth invariant the parent tracker described is now in main: every pinnable ref (cut tag, rc tag, main) carries its own baked value + resolve-ref readsBUILD_BAKED_TOOLKIT_REFunconditionally.Sibling follow-ups still open: #209 (dogfood post_bump_hooks for own doc ref-pin updates), #196 (doc ref-pin drift — addressable by #209 or a manual sweep).