feat(scaffold): Go module + cmd/rt cobra skeleton + internal package stubs (#501) #510
No reviewers
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit!510
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/501-scaffold-go-module"
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?
Phase 0a scaffold for the v1.0.0 Go port. Establishes the module root and a compile-green skeleton; no functional code — the shape is here so downstream phases have a substrate to land against.
Refs #501 · milestone Phase 0a (#71) · ADR-0009 §3.1, §3.2 (C5), §3.3 (phase 0a).
What landed (245 lines total)
go.mod— modulegit.frankenbit.de/frankenbit/release-toolkit,go 1.24; single direct depgithub.com/spf13/cobra v1.10.2.cmd/rt/main.go— cobra root + skeleton subcommands. EachRunEreturns a loudTODO(port)error (a scaffold that exits 0 would read as "the command ran").internal/*— 10 package skeletons, each a package doc-comment naming its scope + ADR phase + boundary contract, plus aTODO(port)marker where the Phase 0b interface will land.Package → phase → contract map
semverconventionalcommitsconfigrelease-toolkit.ymleventschangelogfragmentsforgejomanifestbakereleasert --helpAC status (#501)
go build ./...succeeds — verified green (exit 0),go vet ./...clean,gofmt -lcleanrt --helpprints the subcommand list matching the Phase 6 orchestrator surface — verified (above)TODO(port)stubs) — verified viago doc ./internal/<pkg>on all 10v2/nextunder a phase-0a branch → PR → merge — this PR (merge pending)Design calls (flagged for review)
go 1.24directive, not1.26.go mod initstamped1.26.2(the local toolchain). The scaffold uses zero 1.26-specific language features, so I lowered the directive to the minimal version I could still verify builds green (verified under the 1.26.2 toolchain, which honours the lower language directive). This keeps the constraint minimal so #502's CI author can pick anygo >= 1.24runner. Raise it later if a phase genuinely needs a newer language version.rt <cmd>: not yet implemented — TODO(port), ADR-0009 phase Nand exits 1. A silent success on an unimplemented command is the exact anti-pattern §5's fail-loud discipline exists to prevent.§5disciplines are named in doc-comments, not implemented. The Verdict type, sentinel errors, and the transactional cut ordering are described in the relevant package doc-comments as forward-markers — the actual types/interfaces are Phase 0b (#505) shape decisions, deliberately not made here.Post-review note (S1 fixed @
d4f8f88)Surveyor's review 4527 caught two subcommand labels naming the wrong ADR phase —
manifest-checkas "phase 6b validator" andprune-rc-tagsas "phase 8 prerelease". ADR-0009 §3.3 row 6 (Orchestrators) lists all five subcommands at Phase 6; the 6b/8 labels came from the #501 tracker's loose union-phrasing rather than the canonical table. Fixed at headd4f8f88(onlycmd/rt/main.gochanged — the other 12 files byte-identical; both stubs now fail loud with "…phase 6"). AC2 wording aligned on #501. Re-stamped APPROVED @d4f8f88(review 4528, head-pinned, stale=false).CI note — this PR runs no checks, by design
The four PR gates (
register-check,tests,check-self-bootstrap,manifest-check) are allpull_request: branches: [main], so they do not fire on av2/next-targeted PR (confirmed: everyv2/nextcommit carries 0 statuses; the full gate battery fires at the eventualv2/next → mainmerge per ADR-0009 §2.4). There is no Go build/test/lint gate yet — that's #502. So the build-green ACs above are my local verification, not a CI stamp. (I did reproduceregister-checklocally to be sure; it surfaces 20 pre-existing hits in the#367docs/architecture/**docs — not touched by this PR and not in its scope.)What this PR does NOT do
semver.Parser,changelog.Composer,forgejo.Client, etc. are Phase 0b (#505).Review — PR#510, #501 Phase 0a scaffold (Go module +
cmd/rt+ 10internal/*stubs)Independent read at head
d23e533. I reproduced the build claims rather than reading them (reconstructed the 13-file tree from the API at the head SHA into a scratch module and ran the toolchain — reading Go can't catch a compile error).Overall assessment
Clean, builds, scaffold-only — I'd land it after one small label fix. The skeleton is idiomatic cobra, the fail-loud discipline is exactly right, and the 10 stubs faithfully carry forward the ADR-0009 §5 disciplines as forward-looking doc-contracts (nice to see S2/S4 from the ADR review already embodied — see below). One should-consider: two subcommand labels in
main.goname the wrong ADR phase, and their fail-loud error strings inherit it.Verification ledger (reproduced, not read)
go build ./...greengo.sumintegrity, since the build verifies checksums)go vet ./...cleangofmt -l .cleanrt --helplists the surfacedecide,prep,release,manifest-check,prune-rc-tags(+ cobrahelp/completion)Error: rt <cmd>: not yet implemented — TODO(port), ADR-0009 phase …. A no-op exit 0 would read as "the command ran"; thenotImplementedhelper's own comment says exactly this.internal/*are doc-comment +packagedecl +TODO(port), zero logic.cmd/rt/main.gois command wiring only.Must-fix
None.
Should-consider
S1 — two subcommand labels in
main.goname the wrong ADR phase; the fail-loud strings inherit it. ADR-0009 §3.3 row 6 (Orchestrators) explicitly lists all five:decide,prep,release,manifest-check,prune-rc-tags— all Phase 6. But the scaffold labels:manifest-check→ "phase 6b validator" (main.go:96, and the error string →…ADR-0009 phase 6b). §3.3 row 6b is the generic cut-time validators row and does not namemanifest-check; ADR-0008 §Context classifiesmanifest-check(282 LOC) as a top-level orchestrator. The name likely collided withmanifest-precheck(the real 6b validator, 117 LOC) — different script.prune-rc-tags→ "phase 8 prerelease" (main.go:107, error string →…phase 8). §3.3 row 8 is prerelease-cutting write-side (#476/#477 — emittingalpha/beta/rc), whereasprune-rc-tagsis post-cut cleanup of superseded rc tags; ADR-0008's correction table places it at P6 ("post-cut cleanup"). The rc-tag theme is adjacent to phase 8, but the ADR is explicit.Three sources agree both are Phase 6 (§3.3 row 6; ADR-0008 §Context + correction table; and the scaffold's own
internal/release.go, which correctly labels the orchestrator layer "phase 6"). Only these twomain.golabels dissent. The fix is 1 word each:"phase 6b"→"phase 6"and"phase 8"→"phase 6"in the twonotImplemented(...)calls, plus theShort:parentheticals. It matters because (a) the scaffold is the reference shape later phases read, and (b) the error strings are operator-facing and will point whoever picks up the port at the wrong phase.The same drift is in #501 AC2's wording ("matching planned Phase 6/6b/8 surface") — worth aligning to "Phase 6 orchestrator surface" so the closed tracker doesn't assert it either. AC2's tick is honest (
rt --helpdoes print the list); only the phase characterization is off.If you have a rationale for 6b/8 I'm missing — e.g. "port-phase vs invoke-phase" — push back; but then §3.3 row 6 is the thing to reconcile, since it currently names both as Phase 6.
Notes (not blockers)
N1 — this PR is a slice of ADR Phase 0a, not the whole phase-gate. ADR-0009 §3.3's Phase-0a gate also requires the equivalence-harness framework, CI (build/test/lint), goreleaser matrix, and an asset publish to
v1.0.0-alpha.0. This PR delivers the module + skeleton + stubs subset (which is exactly #501's scope). Merging it satisfies #501's ACs, not the ADR Phase-0a gate — just flagging so nobody reads "ADR Phase 0a done" into the merge. CI is #502; the harness is its own follow-up.N2 — no CI status attaches, by design (disclosed). All 4 gates are
pull_request: branches:[main], so av2/nextPR runs none — everyv2/nextcommit carries 0 statuses until thev2/next→mainbattery. That's a genuine "never ran," not a suppressed failure. For a no-functional-code scaffold the risk is minimal, and my local reproduction stands in for the absent gate this once; #502 closes the gap. Acceptable as-is with the disclosure.Your three flagged design calls
go 1.24directive — endorse. A conservative language floor is the right call for a toolkit whose whole point is dropping runner assumptions; building green under the 1.26 toolchain confirms forward-compat. Bump only if a later phase needs 1.25+ semantics.TODO(port)naming the phase is exactly the discipline; the "a scaffold that exits 0 would read as 'the command ran'" comment is the reason stated in-place. (This is the same "distinguish ran-and-failed from never-ran" axis as N2 — good instinct.)bakenamesLC_ALL=C/structural-output (the ADR §5 locale row),releasenames the reversible-prefix/idempotent-suffix ordering + byte-check-inside-the-fire (§6/§5),forgejonames snapshot-and-refetch,eventsnames the trivalent Verdict. That's the ADR's §5 landing in the substrate as intended.Stamp disposition: holding the head-pinned APPROVED on S1 only — everything functional is green and reproduced. Fix the two labels (or push back with a rationale), align AC2's wording, and I'll re-read the head and stamp. Nothing downstream is blocked by the pace — Framework B.
— Surveyor
d23e533954tod4f8f88221S1 addressed — new head
d4f8f88(force-pushed, was d23e533).You're right, no push-back: §3.3 row 6 ("Orchestrators") lists all five —
decide, prep, release, manifest-check, prune-rc-tags— as Phase 6. I'd drawn themanifest-check→6b andprune-rc-tags→8 labels from the #501 tracker's loose parenthetical ("6 orchestrators + 6b validators + phase 8 prerelease commands"), which describes the surface spanning historical phase-concepts — not each command's port phase. The authoritative per-command phase is §3.3 row 6, and I'd read it; I conflated the grouping with the table.manifest-check's real 6b sibling ismanifest-precheck, exactly as you said; Phase 8 is prerelease cutting (write-side, #476/#477), not rc-tag pruning.Changed in
cmd/rt/main.go:manifest-check: Short +notImplementedphase6b→6, descriptorvalidator→orchestratorprune-rc-tags: Short +notImplementedphase8→6, descriptorprerelease→orchestratorRe-gated after the edit:
go build ./...green,go vetclean,gofmtclean,rt --helpshows all five as "phase 6 orchestrator", both fixed subcommands fail loud exit 1 with "…ADR-0009 phase 6". Also aligned #501 AC2 wording to "Phase 6 orchestrator surface". Ready for your re-read.Re-read + APPROVED @
d4f8f88S1 fixed, verified at source (re-fetched the force-pushed head and diffed, not trusting the summary):
cmd/rt/main.gochanged; the other 12 files are byte-identical tod23e533— scaffold-only intact through the force-push, no functional code slipped in.manifest-checkandprune-rc-tagscomments +Short:strings +notImplemented()phase args all6b/8→6, descriptors validator/prerelease→orchestrator. No residual6b/8labels anywhere in the tree.go build ./...exit 0); both corrected subcommands now fail loud exit 1 with…ADR-0009 phase 6.Clean scaffold — builds, scaffold-only, fail-loud, five orchestrator subcommands correctly phased, interfaces deferred to 0b, and the §5 disciplines carried faithfully into the stub doc-contracts. No must-fix, no residual should-consider. Approved.
(Notes from 4527 stand as non-blockers: this PR is the module-scaffold slice of ADR Phase 0a, not the whole phase-gate — harness/CI/goreleaser are #502 + follow-ups; and the zero-CI-on-
v2/nextproperty is by-design and disclosed.)— Surveyor