ci: one pinned-mcpp bootstrap, not six drifting copies#287
Merged
Conversation
Sunrisepeak
force-pushed
the
ci/pin-all-mcpp-bootstraps
branch
2 times, most recently
from
July 26, 2026 11:20
ac6358d to
a41b3b3
Compare
The 0.0.109 release died in `build + upload (linux/x86_64)` with the symptom
0.0.109 was released to fix:
error: index requires mcpp >= 0.0.108 but this is mcpp 0.0.105 [E0006]
error: xlings install_packages failed (exit 1) for 'mcpplibs.cmdline@0.0.1'
A bare `xlings install mcpp -y` resolves "newest in whatever index copy this
runner happens to have", not the pin in .xlings.json. When that lands below the
index floor, the floor check makes EVERY descriptor read return nothing, so
every dependency falls back to its legacy derived address — and the error names
neither the version nor the floor as the cause.
#286 pinned two composite actions. It missed that release.yml carries four
inline bootstraps of its own, cross-build-test.yml two more, and each had
drifted: the Windows one used `find ~/.xlings -name mcpp.exe | head -1`, which
returns whichever version the directory walk reaches first.
So: one implementation. .github/tools/install_pinned_mcpp.sh reads the pin,
installs it, locates the binary inside that version's own directory (the layout
underneath differs per platform — `<ver>/mcpp` on Linux, `<ver>/bin/mcpp.exe` on
Windows — so only the version directory is treated as the contract), asserts the
parsed version matches exactly, and prints just the path. Six call sites use it,
including the two from #286, so there is no seventh copy to drift.
Two bugs found while consolidating, both of which #286 had shipped:
* Under `set -eo pipefail` a `find ~/.xlings ... 2>/dev/null` over a tree with
one unreadable directory exits non-zero — the redirect hides the message, not
the status. That killed the script before it could report anything. Every
find is now `|| true` with an explicit `return 0`, since a miss is a normal
outcome the caller handles. #286's copies had the same landmine; it only
stayed quiet because the loop returned early before reaching the fallback.
* An exact version comparison instead of a substring match, which would let a
pin of 0.0.10 be satisfied by a 0.0.109 binary.
The Windows release leg also never returns to the workspace after `cd "$WORK"`,
so it reads .xlings.json through a REPO_DIR captured beforehand rather than
GITHUB_WORKSPACE, which git-bash sees as a backslash path.
Left alone deliberately: ci-aarch64-fresh-install's bare install is the point of
that workflow (it verifies what a user's fresh install resolves), and
ci-linux-e2e's hermetic bootstrap is green — reshaping a passing job for
stylistic consistency after six CI rounds is not a good trade.
No source change; 0.0.109 is unreleased, so the version stays.
Sunrisepeak
force-pushed
the
ci/pin-all-mcpp-bootstraps
branch
from
July 26, 2026 11:26
a41b3b3 to
520001e
Compare
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.
ci: one pinned-mcpp bootstrap, not six drifting copies
The 0.0.109 release died in
build + upload (linux/x86_64)with the symptom0.0.109 was released to fix:
A bare
xlings install mcpp -yresolves "newest in whatever index copy thisrunner happens to have", not the pin in .xlings.json. When that lands below the
index floor, the floor check makes EVERY descriptor read return nothing, so
every dependency falls back to its legacy derived address — and the error names
neither the version nor the floor as the cause.
#286 pinned two composite actions. It missed that release.yml carries four
inline bootstraps of its own, cross-build-test.yml two more, and each had
drifted: the Windows one used
find ~/.xlings -name mcpp.exe | head -1, whichreturns whichever version the directory walk reaches first.
So: one implementation. .github/tools/install_pinned_mcpp.sh reads the pin,
installs it, locates the binary inside that version's own directory (the layout
underneath differs per platform —
<ver>/mcppon Linux,<ver>/bin/mcpp.exeonWindows — so only the version directory is treated as the contract), asserts the
parsed version matches exactly, and prints just the path. Six call sites use it,
including the two from #286, so there is no seventh copy to drift.
Two bugs found while consolidating, both of which #286 had shipped:
Under
set -eo pipefailafind ~/.xlings ... 2>/dev/nullover a tree withone unreadable directory exits non-zero — the redirect hides the message, not
the status. That killed the script before it could report anything. Every
find is now
|| truewith an explicitreturn 0, since a miss is a normaloutcome the caller handles. fix: a bare dependency's wire address takes BOTH halves from its descriptor (0.0.109) #286's copies had the same landmine; it only
stayed quiet because the loop returned early before reaching the fallback.
An exact version comparison instead of a substring match, which would let a
pin of 0.0.10 be satisfied by a 0.0.109 binary.
The Windows release leg also never returns to the workspace after
cd "$WORK",so it reads .xlings.json through a REPO_DIR captured beforehand rather than
GITHUB_WORKSPACE, which git-bash sees as a backslash path.
Left alone deliberately: ci-aarch64-fresh-install's bare install is the point of
that workflow (it verifies what a user's fresh install resolves), and
ci-linux-e2e's hermetic bootstrap is green — reshaping a passing job for
stylistic consistency after six CI rounds is not a good trade.
No source change; 0.0.109 is unreleased, so the version stays.
Note on validation scope: PR CI exercises the two composite actions and
cross-build-test.yml. The fourrelease.ymlcall sites only run on tag/dispatch, so they are validated by re-running the release after this merges — which is the blocked step this PR exists to unblock.