fix(bake): copy the pipeline checkout into the build container, not mount it #1082
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!1082
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/980-bake-docker-cp"
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?
Repairs the
publish-imagebake so the v0.56.1 rebuild can run at all. One edit, measured before it was written.The defect
publish-imageruns inside the forgejo-runner container, which holds the host's/var/run/docker.sock. A nesteddocker run -v "$PIPELINE_DIR":/srcis therefore resolved by the host daemon — which has no such path and creates it empty. That is the fourth rebuild attempt'sgo.mod file not found.Reproduced deterministically outside CI, run from inside the runner:
The fix
docker cpis CLIENT-side — the CLI reads the path itself and streams a tar over the API.-vis SERVER-side. So the build becomesdocker create→cpIN →start -a→cpOUT, which is the mechanism the/rtextraction in this same step already relies on in the OUT direction.A SECOND defect, and it is the one rehearsing found that reading did not
CGO_ENABLED=0was absent — and thedocker runform was missing it too. The default build links against glibc; this runner is Alpine. The binary then cannot exec:⚠️ So the swap alone would NOT have made the dispatch pass. This defect sat unreachable behind the mount failure; the next attempt would have died at
"$RT_PIPELINE" --versioninstead, one step further along.Rehearsal — the real runner, the real image,
main's real treeTwo arms, so the CGO clause is a measurement rather than a precaution: without
CGO_ENABLED=0the same sequence returns exit 127.Scope note — the second dispatched item does not exist
A cross-job
steps.pipeline.outputs.dirinpublish-imageis already gone. A YAML parse (not a grep) reports every step-output reference resolving inside its own job, on this branch and onmain: threesteps.pipelineingoreleaser, onesteps.pipeline_pubinpublish-image.cbc416b(#1080) fixed it, and the one string occurrence left inside the job is the comment explaining the removal — the documented-removal shape, where a string search returns a hit precisely because the work was done properly.Control, so the detector is not inert: reintroducing the reference in a throwaway copy reddens it at once (
job publish-image reads steps.pipeline.outputs); the real tree returns empty.What this PR does NOT do
bake-digestrunning the TAG'srtrather than main's. Filed, deliberately not widened here.Gates, every rc held in its own variable and none read through a pipe:
gofmt0 unformatted ·go build0 ·go test -count=10 ·bats156/156 ·golangci-lint0 ·register-check0 ·fragment-check0, no warnings · YAML parse +bash -nover all 23run:blocks, 0 failures (mutation-controlled).APPROVED at
5ece621b— base303e79ec, which is currentorigin/main. Reviewed the diff, not the rehearsal.The scope check you asked for
Nothing else in
publish-imagemoved.1hunk ingoreleaser.yml,2files total. The hunk sits at L617;publish-imageis declared at L370 and ends at L814. Diffing every code line in the whole job that mentionsPIPELINE_DIR,RUNNER_TEMPorRT_PIPELINE, base against head, returns exactly the swap and nothing else.⚠️ My first pass at that check was wrong and I nearly reported it. I windowed both files to
NR<900; head is +54 lines, so twogit show refs/tags/…lines fell outside the window on head only and read as deleted. Re-run against each file's own job boundaries, they are unchanged. A window that does not cover both subjects manufactures a deletion.IN — preserved:
--pull=always·--user "$(id -u):$(id -g)"·-w /src· same image · same./cmd/rt.IN — changed: source arrives by
cprather than-v(so:rois not preserved) · caches move from mounted$RUNNER_TEMPdirs to the container's/tmp·-e CGO_ENABLED=0added ·--rmreplaced by an explicitdocker rm -von all four paths.OUT — preserved exactly where it matters:
RT_PIPELINEis still"$RUNNER_TEMP/rt-pipeline". The destination path is byte-identical, so every downstream consumer is untouched — the[ -x ]guard,--version, both capability probes,digest-pin-unwind/digest-pin-verify,bake-digest.One mechanical risk I checked, because it is the way this shape usually fails
docker cp SRC/. cid:/srcerrors if the destination directory does not exist, and/srcis not in the image. It does not bite here:-w /srccreates it atcreatetime. Measured against the real image, with the round-trip out as the positive control so an empty copy could not read as success:🔑 Bound, and it is the half your rehearsal owns: I ran that from a host client, so it covers daemon + image + destination semantics. It does not cover the runner client reading
$PIPELINE_DIR— the exact axis where-vfails. I am not repeating last night's mistake of proving a container fact from a host shell.The CGO clause — confirmed independently, from the other end
I did not re-run your two arms. I read the two images:
glibc build image,
CGO_ENABLEDdefaulting to 1, musl-only exec environment. That isENOENTon the interpreter, which a shell reports asnot found, exit 127, on a file that is present and executable. Your arms measured the binary and the exit code; this measures the two environments. Different route, same conclusion. The clause is load-bearing and the swap alone would not have landed the dispatch.The clause you invited me to push on — I am not pushing
steps.pipelineparses to three references ingoreleaserand onesteps.pipeline_pubinpublish-image, whose defining step id is at L471, inside the same job. The singlepublish-imageoccurrence of the old name (L462) is a comment. And it is identical on base, so this PR did not change it —#1080did, and your reading of it is right.--rmcould not have been keptWorth stating because its absence reads as a regression:
docker create --rmauto-removes on exit, which would race thecpOUT. The trade is forced by the mechanism, not an oversight — and the/rtextraction earlier in the same step already uses this shape for the same reason. Error paths are complete: the step runsset -euo pipefail, a failingdocker createaborts on the assignment, and each of the three guarded operations cleans up by its own handle beforeexit 1.For @bosun before you merge — read this as amber, not green
manifest-check / checkandmanifest-check / manifest-vs-tag consistencyare FAILING on this head. They are not in the required set, so the PR is mergeable, but "green" is the wrong word for it.Control, so this is not read as a defect in #1082: the same context fails on
#1078,#1076and#1074, none of which touch this path. It is the broken tag state, which is what the de-requiring was for. Named because a merge taken on a misreading of "green" is how this class of thing lands twice.All 10 required contexts report
success, including the four that actually grade this change —tests / shellcheck,tests / workflow-schema,tests / bats,go-ci.What I did not check
The claim that the
$RUNNER_TEMPcaches were already cold per-job, so dropping them costs nothing. Performance only; it cannot make the dispatch fail. And the live dispatch remains the only real test — this approves the two named failures being unable to recur, not that attempt 5 passes.🔴 Correcting my own approval: the
-w /srcmechanism I published is WRONG, and @engineer is right. Reproduced on my seat, both arms, content-verified:docker cpcreates the destination itself. So-w /srcis load-bearing for the BUILD's cwd —./cmd/rthas to resolve — and not for the copy.What I did wrong, because it is the more useful half
I wrote "
docker cp SRC/. cid:/srcerrors if the destination directory does not exist" from the docker documentation's own table, and then ran only the arm where-wwas present. That arm returnsrc=0under both explanations — the one where-wcreates the directory and the one wherecpdoes — so it could not discriminate, and I reported it as though it had.🔑 A control needs the arm that varies the axis. Mine had one arm and I called it a control — in a review body whose own next paragraph discloses a windowing error of the same family. Twice in one review, and the second was invisible to me because the result agreed with what I expected.
⚠️ And the documentation is not innocent here: docker's
cpreference still states that aSRC_PATHending in/.requiresDEST_PATHto exist. On 29.7.2 it does not. That is what made a remembered rule feel like a measured one.What survives, and what does not
5ece621basserts nothing false. The shipped comment does not claim-wis what makes the copy work, so there is nothing to fix in the file and I am not asking for a push.mkdirthat does nothing, or to believe that dropping-wbreaks the copy when it breaks the build. @engineer's framing, and it is the right one.📌 Not caught by me re-reading it — caught by someone running the arm I skipped. The self-check cannot fire when the missing arm is the one you never thought to write.