docs(single-stack): fetch-rt.sh is the BOOTSTRAP and cannot be ported — record the retirement`s terminal state #778
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#778
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?
Motivation
This tracker exists to stop the bash retirement from reading as unfinished forever.
scripts/fetch-rt.sh— 171 lines — fetches the releasedrtbinary, checksum-verifiesit, installs it
0755and puts its directory on$GITHUB_PATH. It is the single source oftruth for fetch-and-verify, shared by the composite bootstrap
action.ymlandreusable-release.yml's 2c-hybrid FETCH path (#582).🔴 It cannot be ported to Go, by construction
This is not a difficulty estimate or a scheduling preference. No amount of effort moves it,
and any plan that lists it as remaining work is describing an impossibility. The retirement's
terminal state is one file, and this is the file.
⚠️ Nor should its security-critical half move ANYWHERE
The checksum verify is deliberately outside the cache hit/miss branch, so a cache hit cannot
skip it:
A restored binary is UNTRUSTED input — it arrives from a key-addressed store this script does
not control, and a mis-keyed or poisoned entry would otherwise be executed by every downstream
gate with no tell.
checksums.txtis 81 bytes against a 9,519,266-byte asset (0.00085%), sore-fetching it every run buys the whole safety property for nothing.
And it verifies at the binary's FINAL PATH, not the downloaded file, so what is checked is
exactly what later steps execute, on both paths.
🔑 A guard that runs before the thing it guards is available cannot itself depend on that
thing. That is the same reason the file is irreducible.
📌 It also already moved once, in the correct direction: it was extracted from
action.yml'sinline body per the extract-to-script-for-coverage preference, so the verify lives in one
greppable, testable place rather than two copies that can silently diverge. Pushing it back
into the workflow would undo a deliberate fix, which answers the "or Forgejo workflows?" half
of the scoping question.
Scope
No code change. This is a documentation and bookkeeping tracker:
docs/adr/0009-go-substrate-for-v1.md(or its successor) that the single-stack goalterminates at one bootstrap script, with the reason above
only, permanent
✅ What WOULD change this, stated so the decision is checkable rather than assumed
Only a change to how
rtis delivered — a distro package, a container image withrtpreinstalled, or a runner image baking it in (cf.
alcatraz-infra#528, which did exactly thisfor
bats/shellcheck/graphviz). Then the bootstrap moves into the image and this file goesaway as a side effect. That is an infrastructure decision, not a porting task, and it is not
proposed here.
Acceptance criteria
Related
#582— the 2c-hybrid bootstrap FETCH path that shares this script#606— the install-dir caching, and why VERIFY sits outside the branch#705— retire the last bash (forgejo-api.sh); the last unit that CAN be portedalcatraz-infra#528— baking tools into runner images; the shape that would make this mootAnchor
2026-08-20 09:23. Operator scoping of the remainder; the bootstrap-circularity finding came from
reading the file's own header rather than from its line count. Census measured recursively
against
origin/main: 5 files, 1,789 lines, of whichforgejo-api.shis 1,177.ACs ticked — each re-derived from
origin/mainat tick time, not assumed from the merge⚠️ AC2 first read as NOT MET and that was my instrument, not the docs. A grep for
zero[- ]bashreturned 2 hits, which I nearly reported as unfinished work on a closed tracker.Reading them:
Both occurrences are the AC being SATISFIED. The needle matched the phrase and was blind to
its negation — the same polarity gap that has cost this crew four separate measurements this
week. A count is not a reading.
⚠️ Amended by an operator ruling — the terminal state is
fetch-rt.shALONEThis tracker recorded the terminal state as "one bootstrap file", meaning one
.shfile.The operator has ruled that workflow-embedded bash is in scope too (
rt#792), so:The reason this tracker gave is untouched and still correct:
fetch-rt.shfetches the Gobinary, so porting it needs
rtalready installed. What changes is that "one bootstrap file"must not be quoted as "the retirement is done" — it is a statement about
.shfiles, and thearc now has a second number.
⚠️ And one open question this ruling creates, flagged rather than answered: three of the
workflow blocks are bootstrap-shaped too —
checkout release-toolkit(36 lines),install deps(21),
verify rt on PATH(32). A step that fetches and verifies the binary cannot be written inthe binary. They may be permanent for the same reason this file is. That needs deciding, not
assuming.