fix(ci): one writer to the buildcache ref #11
No reviewers
Labels
No labels
waiting-on-julian
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
jlxq0/jmap-mcp!11
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix-buildcache-race"
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?
Closes jlxq0/m365-mcp#4 for this repository.
The race
Merging a PR and pushing the release tag are two pushes, so two
dockerjobsrun concurrently. Both exported to the same unqualified
:buildcacheref:Observed on
m365-mcpruns 49 and 50, failing within half a second of eachother — after the image had already been pushed successfully.
The fix, and why it is not either option in the issue
The tag build now imports the cache and does not export it.
That works because a tag build is the same commit as the
mainbuild thatpreceded it. Reading the branch: the two paths differ only in
TAGSandPUSH,which are output settings rather than build inputs. So the two caches would be
byte-identical — exporting twice was pure duplication, and the duplication was
the race. One writer removes it by construction rather than by scheduling.
The issue offered two shapes and I took neither:
concurrency:group serialises two builds that produce the same bytes,which is paying a queue to do work twice. Worse, Forgejo job-level
concurrency is unverified here: nothing in the fleet uses it, this instance
is 15.0.2, and an unsupported key is ignored silently — a fix that looks
applied and does nothing, which is the failure mode worth avoiding above all
others tonight.
is the expensive path, and accumulates refs on a registry whose disk is
currently the fleet's bottleneck.
carddav-mcpalready did thisIt guards its export on
refs/heads/mainand has exactly one writer. So this isfour copies converging on the one that was right, not a new invention — the same
shape as the divergence in
oauth_redirect.rs, resolved in favour of the copythat already worked.
Worth correcting one line of the issue: it says all five export to the same ref,
which is true, but only four of them export from both paths.
carddav-mcpneeded no change.
Verification
Not verified by running, and it cannot be yet: the forge runner is out of
disk and every
cargojob fails before reaching a gate. A greendockerjobwould not be evidence either — buildkit does not use that volume.
Correction: the assertion I first wrote was the wrong one
I originally said the check was "exactly one
--export-cachesite remains".That does not distinguish fixed from broken, and
typst-mcpis the proof:before this change it had exactly one export site, guarded by
GITHUB_EVENT_NAME != pull_request— which fires on amainpush and on atag push. One site, two writers. A grep for the count would have reported it
already fixed.
The property is exactly one writer, which is about the guard on the
export, not the number of sites. For three of the four repos those coincide;
for typst they do not.
refs/tags/v*andrefs/heads/mainrefs/tags/v*andrefs/heads/main!= pull_requestrefs/tags/v*and theelserefs/heads/mainAfter this change every one of the four exports only under
refs/heads/main, stated explicitly rather than implied by "not a tag", so atrigger added on another branch later cannot quietly become a second writer.
What is checked
bash -n;--export-cacheis inside arefs/heads/mainguard — read,not counted.
Do not merge on a gate you cannot read. This wants one run after the runner
is back: a merge to
mainand a tag push landing together, both green.🤖 Generated with Claude Code
https://claude.ai/code/session_01SP7njJZ7ZtrMgULuXh8ddq
01f77e76cc26098bace1Merged as
7d886e4b. Merge builds: cargo16532, docker16533, both green.The
Closes jlxq0/m365-mcp#4in the body above did not fire. Cross-repository references do not close issues on Forgejo, and all four pull requests carried the same line, so the issue stayed open with nothing recording that the work was done. It is closed by hand now, and m365-mcp#4 holds the record for all four repositories: merge commits, what was verified, and two instruments that were proposed and withdrawn before anyone used them.Two writer paths this change does not close are tracked in m365-mcp#7. Neither affects this repository: it has no
schedule:trigger, and the second needs two merges inside one build.Evidence for this repository specifically, and it is the sharpest of the four.
16533was the only job across all four merges that retained a log, and it reads:That digest is byte-identical to what
:buildcacheheld before the build. So this repository is the direct demonstration that an unchanged manifest digest does not mean no export happened, which is why the digest test proposed during this work was withdrawn. The log line is the signal; the digest is silent.