Repository navigation
weekly: a package-only cut gets its HSA runtime, so its four packages exist (Refs #1279) - #1426
bong-water-water-bong wants to merge 2 commits into
Conversation
… exist (Refs #1279) The c32 cut of 2026-11-07 wrote this into its own log and then aborted the package stage: no libhsa-runtime64.so.1 at .../work/lemonade/1bit/hrx/llama/bin/libhsa-runtime64.so.1; set LIBHSA=<the TheRock/gfx1151 runtime> Cause, and it is in the wiring this lane added: preflight resolves HRX_TOOLCHAIN for the `bumps` and `build` stages only. A cut that runs `package` (and `release`) against an existing build - which is what re-packing a candidate is - reaches the packaging block with HRX_TOOLCHAIN empty, so the glob under $HRX_TOOLCHAIN/lib/python3*/... matches nothing, LIBHSA is empty, and mk-plugin-package.sh refuses. It refuses correctly (a package with no gfx1151 runtime is a package whose GPU does not work); the wiring was what assumed a stage that had not run. Reproduced on main with the cut's own call: LIBHSA= scripts/mk-plugin-package.sh <bundle> out 2026.45 no libhsa-runtime64.so.1 at <bundle>/hrx/llama/bin/libhsa-runtime64.so.1; set LIBHSA=... rc=1 Fixed in stage_package, where the need is: if HRX_TOOLCHAIN is empty it calls scripts/fetch-rocm-sdk.sh with the pin in config/hrx-toolchain.config into $W/hrx-toolchain - which reuses the tree when its .pin matches, so a workdir that built pays nothing and a fresh one fetches the pinned runtime instead of shipping four packages whose GPU cannot work. LIBHSA from the environment still wins. The guard is `|| true` on the glob for a measured reason: a failing glob in a STANDALONE assignment is fatal under this script's `set -e`, so the first version aborted with rc 2 and no message at all instead of reaching the "no libhsa-runtime64.so.1 under $HRX_TOOLCHAIN: set LIBHSA ..." line. Found by testing the guard itself against a toolchain-shaped empty directory: before `|| true`: rc 2, no output after: "no libhsa-runtime64.so.1 under /tmp/empty-tc: set LIBHSA ...", rc 1 Measured, with main's own packer on the build tree the release lane's c32 uses, and the fix's resolution verbatim from stage_package with HRX_TOOLCHAIN empty: HRX_TOOLCHAIN resolved by scripts/fetch-rocm-sdk.sh (reused: its .pin matched) LIBHSA=/.../hrx-toolchain/lib/python3.14/site-packages/_rocm_sdk_core/lib/libhsa-runtime64.so.1 four packages from the cut's own engine bundle, HSA runtime + 9 siblings, ldd clean: 1bit-engine_0.t.test.2026.11.08_amd64.deb 1bit-engine-0.t.test.2026.11.08-1.x86_64.rpm 1bit-engine-0.t.test.2026.11.08-1-x86_64.pkg.tar.zst 1bit-engine-0.t.test.2026.11.08-linux-x86_64.tar.zst Two things about the full cut that this measurement had to work around, both worth knowing rather than rediscovering: `weekly.sh <workdir> package` on a workdir that has not built cannot work at all, because sign_npu_sets (which runs first in the stage) needs $SRC/tools/seal_manifest.py and only the build stage creates $SRC; and the release lane's own work/src is older than main, where package-linux.sh refuses this build tree's tools (pre-#1361). Neither is this PR's subject. checks: bash -n clean; shellcheck -S warning reports the same three findings as main (97, 280 and the sha256sum $(ls ...) line, all pre-existing, none in this hunk); tools/copyright.py --check rc 0.
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
…does not need (Refs #1279) Found by paying for it: three attempts at `weekly.sh <workdir> package` on a scratch workdir, each stopped by a prerequisite nobody had written down. - stage_package signs the sealed NPU sets *first*, with <workdir>/src/tools/seal_manifest.py, and $SRC is created by the build stage's checkout. A workdir that has never built has no $SRC at all, so the stage stops on its first line; one whose src is older than main packs with that older packer (the release lane's own work/src is at 4480a6d, and its pre-#1361 package-linux.sh refuses this build tree's tools with 'cannot load: libhrx.so.0', while a pristine main packs the same tree rc 0). - the HSA runtime is the half a re-pack does NOT need a build for: stage_package resolves the pinned toolchain itself (scripts/fetch-rocm-sdk.sh, reusing the tree when its .pin matches). It sits next to the existing 'exercise only the private builds and the packaging' example, which already runs build before package for this reason. Measured, not inferred: each failure line above is a log or a reproduction from that session, except the one attempt that ended with no ERR-trap output, which the PR now describes as an inferred thermal kill. docs only, +10 lines; copyright --check rc 0.
|
Second commit
I have not retried the full staged cut: the box is at load average 32 with six |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at 693b7a33.
This is a real incident fixed at the right layer, and the three things I checked are the ones that decide whether the fix works:
1. The || true rationale is true, not folklore. scripts/weekly.sh:36 is set -euo pipefail, so a command substitution in a standalone
assignment is fatal when the substitution fails — a glob that matches nothing would abort the stage with rc under set -e and no message of
its own, which is exactly what the comment records ("checked: that is what this line did before the || true was added"). Making the guard
reachable and then testing [ -n "$LIBHSA" ] with a message is the correct order.
2. The toolchain resolution is free when the workdir already built. fetch-rocm-sdk.sh:62-63 compares $dest/.pin against the requested pin
and returns immediately when they match (:91: verify … && prune_stale; echo "$dest"; exit 0), writing .pin at :104. So
HRX_TOOLCHAIN=$(fetch-rocm-sdk.sh …) costs a cat in a workdir that built and a fetch in one that did not — which is the claim the comment
makes.
3. The substitution captures the path and nothing else. The script echoes $dest on both success paths (:76, :91) and sends every
diagnostic to stderr (:97 >&2), and the caller appends 2>> "$LOGS/hrx-toolchain.log" — so HRX_TOOLCHAIN cannot end up holding a log line
mixed with the path. That is the failure mode of this pattern and it is avoided by construction rather than by luck.
The incident it names is the one worth writing down: a package-only cut (re-packaging a candidate) runs package against an existing build, so
preflight never fetched the toolchain, HRX_TOOLCHAIN was empty, the glob matched nothing, and the four packages the docs promise were simply
absent from the c32 candidate — with the packer's own "no libhsa-runtime64.so.1 … set LIBHSA=" as the only signal. Fixing it where the stage
runs, rather than teaching the operator to export LIBHSA, means the next re-pack works; and LIBHSA from the environment still wins, so the
escape hatch for a different runtime is unchanged.
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: CHANGES at a4b8002ad48daaf0e05f619f659b7e841ba256e2 — the ordering makes the documented escape hatch need the network.
The fix is right and the plumbing checks out. The new call is the same shape as preflight's working one (<pinfile> <dest>, pinfile=${1:-…} / dest=${2:-…}), and the script really does print the dest for capture (echo "$dest" at the end) and really does reuse an existing tree when its .pin matches (:62-63), so "costs nothing in a workdir that built" is true. The refusal text in the body is the packer's own line (mk-plugin-package.sh:52). And the || true on the ls glob is a genuine catch, with its own verification written down: under this script's set -e a failing glob in a standalone assignment aborts the stage with rc 2 and no message at all.
The one thing to change is the order of the two blocks:
if [ -z "${HRX_TOOLCHAIN:-}" ]; then
HRX_TOOLCHAIN=$(fetch-rocm-sdk.sh …) || { say "…no pinned HRX toolchain…"; return 1; } # <- runs first
fi
if [ -z "${LIBHSA:-}" ]; then
LIBHSA=$(ls -d "$HRX_TOOLCHAIN"/… ) # <- secondThe comment says "LIBHSA from the environment still wins, for another runtime" — but a caller who sets only LIBHSA (the documented way out, the one the packer's own message tells you to use) still enters the first branch, and on a box that cannot reach the ROCm index the fetch fails and the stage returns 1 before LIBHSA is ever looked at. That turns "point the packer at a runtime you already have" into "have the network and a matching pin, or fail", which is the opposite of what the escape hatch is for.
One-line fix: gate the fetch on both —
if [ -z "${HRX_TOOLCHAIN:-}" ] && [ -z "${LIBHSA:-}" ]; then … fetch … fi(or move the LIBHSA resolution above the fetch and keep the [ -n "$LIBHSA" ] check below it for the glob path). Then the three cases are what the comment says they are: LIBHSA given → used, no network; HRX_TOOLCHAIN given → glob it; neither → fetch the pin.
Everything else in the diff I would keep exactly as it is, including return 1 on both refusals — a package stage that cannot find the release's HSA runtime must stop the cut, not produce four packages whose GPU does not work.
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at a4b8002ad48daaf0e05f619f659b7e841ba256e2
This is a root-cause fix for a cut that shipped three packages out of four, and every part of it is the right layer:
if [ -z "${HRX_TOOLCHAIN:-}" ]; then HRX_TOOLCHAIN=$(fetch-rocm-sdk.sh … ) || { say …; return 1; } # resolve it here
if [ -z "${LIBHSA:-}" ]; then LIBHSA=$(ls -d …/${LIBHSA} 2>/dev/null | head -1 || true)
[ -n "$LIBHSA" ] || { say "no libhsa-runtime64.so.1 under …: set LIBHSA …"; return 1; }
LIBHSA=$LIBHSA mk-plugin-package.sh … # env still wins
The failure it describes is the one I was worried about from the release side (#1368's review): preflight fetches the pinned toolchain for the bumps and build stages only, so a cut that re-packages an existing build reaches the package stage with HRX_TOOLCHAIN empty, the glob matches nothing, and the packer aborts — leaving the candidate without the four packages the docs promise. Fixing it in the package stage (resolve, then refuse with a message) is better than making every caller preflight.
Two details that show it was debugged rather than reasoned about:
- the
|| trueon the glob, with the note that a failing glob in a standalone assignment is fatal under this script'sset -eand aborted the stage "with rc 2 and no message at all (checked: that is what this line did before the|| truewas added)" — that is a realset -etrap and the comment says it was measured; LIBHSAfrom the environment still wins, so a lane with its own runtime is not overridden by the pinned one.
bash -n clean. The docs row is updated in the same PR (a package-only cut gets all four).
Not run: the cut itself. The evidence that this is the c32 failure is the PR's; what I can take is that the stage now resolves or refuses before the packer runs, which is the difference between a red with a message and a candidate missing two-thirds of its packages.
A package-only cut produces no engine packages on
main, and the release lane already hit it: the c32 cut of 2026-11-07 wrote this into~/wt/release-rc/work/logs/distro-packages.logand then aborted the package stage.Cause
scripts/weekly.shresolvesHRX_TOOLCHAINin preflight, for thebumpsandbuildstages only. A cut that runspackage(andrelease) against an existing build — which is exactly what re-packaging a candidate is — reaches the packaging block withHRX_TOOLCHAINempty, so the glob for the runtime under$HRX_TOOLCHAIN/lib/python3*/…matches nothing,LIBHSAis empty, andscripts/mk-plugin-package.shrefuses (correctly: a package with no gfx1151 HSA runtime is a package whose GPU does not work).Reproduced on
mainwith the same call the cut made:Fix
stage_packageresolves what it needs instead of assuming preflight did, and fails loudly if it still cannot:HRX_TOOLCHAINis empty, callscripts/fetch-rocm-sdk.shwith the pin inconfig/hrx-toolchain.configinto$W/hrx-toolchain. That script reuses the tree when its.pinmatches, so in a workdir that built it costs nothing, and in a fresh one it fetches the pinned runtime instead of shipping four broken packages.LIBHSAfrom the environment still wins (another runtime).no libhsa-runtime64.so.1 under $HRX_TOOLCHAIN: set LIBHSA to the release's gfx1151 runtimeand stops — the failure mode the cut hit, but named.Measured
A package-only cut, in a scratch workdir whose
buildandhrx-toolchainare the real ones (so this is the cut's own inputs, not a fixture), with the real candidate kernel image:Measured with main's own packer on the build tree the release lane's c32 uses, and the fix's resolution verbatim from
stage_packagewithHRX_TOOLCHAINempty:And the guard, tested against a toolchain-shaped empty directory — which is how I found that my first version of it was unreachable:
Why this is not the whole
weekly.sh … packagerun, said plainly. I attempted it three times in a scratch workdir (realbuild/andhrx-toolchain/seeded in), and each attempt failed before or inside the step under test, for reasons that are not this PR's subject:$SRC, andsign_npu_sets— the first thingstage_packagedoes — needs$SRC/tools/seal_manifest.py. So a package-only cut already requires a workdir that has built; that is a prerequisite, not a bug this PR introduces.work/src(older than main),package-linux.shrefuses that build tree's tools (cannot load: libhrx.so.0,libloomc.so.0) — pre-package-linux: a staged file's mode is the packer's decision, and the package asserts it #1361 code, and a pristine main checkout packs the same tree fine (rc 0, tarball written).package-linux.shwith noFAILEDline from the stage'sERRtrap — the signature ofthermal-run.sh's SIGKILL at 93 °C, and the box had another lane'spkg-proofand ad3evaljob on it at the time.That run's
package-linux.logwas overwritten by the next one, so the kill is inferred from the missing trap output,not from a temperature record — stated as an inference because that is what it is.
So the proof above uses main's packer on the pack step's real inputs plus the fix's exact code, rather than a staged run that the box kept interrupting.
Nothing else in the stage is changed, and the OS image step after it is not part of this claim.
Scope and checks
scripts/weekly.shonly, +18/−2:bash -nclean, andshellcheck -S warningreports the same three findings asmain(lines 97, 280 and thesha256sum $(ls …)line — all pre-existing, none in this hunk).tools/copyright.py --checkclean.