refactor(prepublish): run GoReleaser through release-cli - #17
Merged
Conversation
PP-05 moves out of go-pre-publish.yml and into goprof: `stage --profile go` now runs `goreleaser release --clean --skip=publish` and then performs the existing validation and projection. The workflow keeps PP-04's managed-tool path proof and becomes a thin shell. GoReleaser shells out to go, syft, and cosign, so the workflow invokes the CLI under `mise exec` and passes the pinned binary as RELEASE_GORELEASER_PATH. Both GoReleaser streams are routed to the CLI's stderr so the --json envelope stays the only stdout content. Adds the guided tutorial and the trust-boundary explanation the plan requires, and records that --dist must be a basename because GoReleaser writes its distribution directory relative to the working directory.
`runStage` never inspected the settings resolver error, so a malformed boolean such as RELEASE_JSON=yes was silently ignored. That was harmless while stage only validated; now that it builds, the command would have run GoReleaser and could exit 0 despite the documented exit-2 contract. Also give the injected GoReleaser seam the same not-configured guard every other collaborator has, so a missing default cannot panic and collide with the reserved usage exit code, and collapse the ad-hoc dist basename rule into goprof.RootName, which now rejects `..` and both path separators.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
PR 10 of the eleven-PR
release-cliprogram (.journal/002/PLAN.md), on top of PR 9 (8a5e0a7). This is the last behavioral slice: inventory item PP-05, thegoreleaser release --clean --skip=publishshell line, moves out of.github/workflows/go-pre-publish.ymland intointernal/profile/goprof. All four reusable workflows are now thin shells. PR 11 is documentation only.Scope
internal/profile/goprof/goreleaser.go(new) —RunGoReleaser(ctx, GoReleaserOptions{Path, Dist, Environ, Stdout, Stderr})invoking exactlyrelease --clean --skip=publishthroughexec.CommandContext: explicit argv slice, deferredexec.LookPath, bounded 4 KiB stderr tail,WaitDelay, no environment or token in any error. No port, no adapter package, noexecx— the plan forbids all three.goreleaser releasehas no--distflag, soDistis the package'sRootNamedomain type, validated rather than forwarded.internal/cli/stage.go—stage --profile gobuilds, then validates, then writes theoci-build-inputs.jsonprojection.Options.RunGoReleaseris an injected function seam defaulted inwithDefaults;RELEASE_GORELEASER_PATHis environment-only, likeRELEASE_COSIGN_PATH. Both GoReleaser streams are routed to the CLI's stderr, so the--jsonenvelope remains the only stdout content.--distmust be a basename because GoReleaser writes relative to the working directory..github/workflows/go-pre-publish.yml— PP-04's managed-tool-path proof stays as its own step; the staging step resolvesmise which goreleaser, refuses a non-executable path, and runs the CLI undermise execbecause GoReleaser shells out togo,syft, andcosign. No input, output, permission, timeout, or action pin changed; both uploads byte-identical.examples/go-release/README.md, plus the two pages the plan requires:docs/tutorials/release-a-go-project.mdanddocs/explanation/release-trust-boundaries.md.Invariant 17 stays intact
Four independent boundaries, all verified: the argv is a fixed Go slice with no interpolation and no shell;
.goreleaser.yamlkeepsrelease.disable: truein both this repository and the example; the producer job holdscontents: readwith no write and noGITHUB_TOKEN; andRELEASE_GORELEASER_PATHselects the binary, never the flags.--skiphas no environment binding in GoReleaser 2.17.1.Verification
mise exec -- moon run root:checkgreen;mise exec -- goreleaser checkvalidates the config.mise execwith a temporary local tag: it cleaned dist, printedskipping announce and publish, validated git state, reportedrelease is disabled, and reached module proxying, where it stopped becausegomod.proxy: truecannot resolve an unpublished local tag. A complete build therefore remains a tag-time event, which is exactly the plan's Layer 3.RELEASE_JSON=yesexits 2 before any build;--distvaluesa\b,a/b,.,..,/abs/dist, anddist/each exit 2 before any build; a build that succeeds and then fails validation exits 1 with one envelope.Review
Two rounds, plus a conformance audit. Nothing blocking survived, and three real defects were fixed that the slice would otherwise have shipped:
runStagenever inspected the settings resolver error, so a malformedRELEASE_*boolean was silently ignored. Harmless whilestageonly validated; after this change it would have built and could exit 0 against the documented exit-2 contract. Now checked first.options.RunGoReleaserhad no not-configured guard, so deleting the default made the binary panic, write no envelope, and exit 2 — colliding with the reserved usage code. It now matches every other injected collaborator, and a test drives the real default throughNewRootCommand.ParseRootNamequietly narrowed it to/only, so--dist 'a\b'went from a pre-build exit 2 to a post-build exit 1, and would have inverted on Windows.ParseRootNamenow rejects..and both separators, matchingParseBinaryNamein the same file.Also fixed: GoReleaser colorizes even into a pipe, so the retained error tail carried raw ANSI into the
--jsonenvelope. The escapes are now stripped from the tail only; the live stream keeps its color for humans reading the workflow log.Journal follow-ups recorded, not acted on here
cosign,melange,apko,goprof). Conformance recommends rescinding theexecxprohibition; that needs an architecture amendment, so it is deliberately out of scope.Options.RunGoReleaseris, in substance, a function-shaped outbound seam rather than merely a test hook. The port budget claim should be read as "no interface and no adapter package", which is what the plan forbade.