fix(ci): unblock the release — npm 11 esbuild bloat + two self-inflicted assertions
Lint / hadolint (push) Successful in 8s
Lint / skill-floor (push) Successful in 9s
Lint / doc-drift (push) Successful in 10s
Lint / actionlint (push) Successful in 19s
Publish Docker Image / lint-gate (push) Successful in 15s
Publish Docker Image / resolve-versions (push) Successful in 10s
Publish Docker Image / base-decide (push) Successful in 14s
Publish Docker Image / build-base (push) Has been skipped
Publish Docker Image / smoke (push) Successful in 5m4s
Publish Docker Image / smoke-studio (push) Successful in 13m17s
Publish Docker Image / build-variant (push) Successful in 33m49s
Publish Docker Image / update-description (push) Successful in 6s
Publish Docker Image / promote-base-latest (push) Successful in 14s
Publish Docker Image / build-variant-studio (push) Successful in 30m58s
Lint / hadolint (push) Successful in 8s
Lint / skill-floor (push) Successful in 9s
Lint / doc-drift (push) Successful in 10s
Lint / actionlint (push) Successful in 19s
Publish Docker Image / lint-gate (push) Successful in 15s
Publish Docker Image / resolve-versions (push) Successful in 10s
Publish Docker Image / base-decide (push) Successful in 14s
Publish Docker Image / build-base (push) Has been skipped
Publish Docker Image / smoke (push) Successful in 5m4s
Publish Docker Image / smoke-studio (push) Successful in 13m17s
Publish Docker Image / build-variant (push) Successful in 33m49s
Publish Docker Image / update-description (push) Successful in 6s
Publish Docker Image / promote-base-latest (push) Successful in 14s
Publish Docker Image / build-variant-studio (push) Successful in 30m58s
v1.9.0 was tagged but never published: smoke failed 90-passed/3-failed and
build-variant needs smoke, so nothing reached the registry. All three are fixed.
1. Size, 431 MB over threshold. Node 24 brings npm 11, which installs EVERY
@esbuild/<platform> optional binary instead of the matching one: 26 dirs,
284 MB per pi-coding-agent copy. Measured on pi-fork: npm 10.9.8 -> 165 MB
(exactly what v1.8.14 shipped), npm 11.19.0 -> 449 MB. npm 11 ignores the
os/cpu constraints AND --os/--cpu AND an npmrc carrying them, all measured,
so Dockerfile.variant prunes explicitly, keeping linux-$(node -p
process.arch) so one line is right on both arches. Pruned in the SAME layer
as each install, or the bytes survive in the earlier layer. Three sites:
global pi, pi-fork, pi-studio. Verified esbuild still transforms TS after.
2. om's node_modules assertion tested an npm artefact. om has zero runtime deps;
its node_modules held ONE file (.package-lock.json) and 20 empty scope dirs.
npm 11 stopped creating it. Now asserts the entry point pi actually loads,
read from package.json -> pi.extensions.
3. The skill-source annotation added in v1.9.0 ("baked (package copy)") broke
the assertion matching "baked$". Pattern now allows an optional suffix; which
copy shipped stays authoritatively asserted against the manifest + tree hash.
Also: a failed size check now prints the largest layers, largest directories and
an @esbuild sentinel, so this class attributes itself next time instead of
costing a CI dig plus a local npm bisect.
Threshold stays 3800 MB: it caught a real regression and raising it would have
thrown the signal away. No Dockerfile.base/rootfs change, so base-0fb1256c7f99
is reused and build-base is skipped.
This commit is contained in:
+45
-3
@@ -315,8 +315,24 @@ run "pi-toolkit clone" "test -d /opt/pi-toolkit && git -C /opt/pi-toolkit rev
|
||||
run "pi-extensions clone" "test -d /opt/pi-extensions && git -C /opt/pi-extensions rev-parse --short HEAD"
|
||||
run "pi-fork clone + node_modules" \
|
||||
"test -f /opt/pi-fork/package.json && test -d /opt/pi-fork/node_modules"
|
||||
run "pi-observational-memory clone + node_modules" \
|
||||
"test -f /opt/pi-observational-memory/package.json && test -d /opt/pi-observational-memory/node_modules"
|
||||
# om is checked differently from pi-fork ON PURPOSE. It declares ZERO runtime
|
||||
# dependencies: 8 devDependencies (omitted by --omit=dev) and 4 peerDependencies,
|
||||
# which pi itself provides. npm 10 still materialised a node_modules for it, but
|
||||
# that directory held exactly ONE file (.package-lock.json, 4 KB) and no nested
|
||||
# package.json at all — 20 empty scope dirs. npm 11 stopped creating it, so the
|
||||
# old `test -d node_modules` assertion went red on v1.9.0 while nothing about om
|
||||
# had changed or broken. It was asserting an npm artefact, not a property of the
|
||||
# shipped software. What actually has to hold is that the entry point pi loads
|
||||
# exists, so assert THAT, straight out of the manifest pi reads
|
||||
# (package.json -> pi.extensions), rather than a hardcoded path that could drift.
|
||||
run "pi-observational-memory clone + declared pi entry point" \
|
||||
"test -f /opt/pi-observational-memory/package.json && \
|
||||
node -e 'const p=require(\"/opt/pi-observational-memory/package.json\"),f=require(\"fs\"),h=require(\"path\"); \
|
||||
const l=(p.pi&&p.pi.extensions)||[]; \
|
||||
if(!l.length){console.error(\"package.json declares no pi.extensions\");process.exit(1)} \
|
||||
for(const e of l){const t=h.resolve(\"/opt/pi-observational-memory\",e); \
|
||||
if(!f.existsSync(t)){console.error(\"declared entry missing: \"+t);process.exit(1)}} \
|
||||
console.log(\"entries ok: \"+l.join(\",\"))'"
|
||||
# ...and that the clone carries the AUTH FIX, not merely that it exists. om's
|
||||
# pre-flight hasUsableAuth() check silently disabled `recall` for ~8 weeks once
|
||||
# pi moved to request-time SigV4 signing and stopped exposing a static Bedrock
|
||||
@@ -697,9 +713,17 @@ exec_test "pi-devbox-version reports skill sources (all baked, no skillset here)
|
||||
'out=$(pi-devbox-version)
|
||||
echo "$out" | grep -q "skills:" || { echo "no skills section" >&2; exit 1; }
|
||||
for s in mempalace pi-extensions pi-devbox-environment credential-incident-response; do
|
||||
echo "$out" | grep -qE "^ $s +baked$" \
|
||||
echo "$out" | grep -qE "^ $s +baked( \([^)]*\))?$" \
|
||||
|| { echo "$s not reported as baked" >&2; exit 1; }
|
||||
done; echo ok'
|
||||
# The optional " (...)" above is what pi-extensions now appends to say WHICH copy
|
||||
# shipped — "baked (package copy)", or a loud FALLBACK/MIXED annotation. Without
|
||||
# allowing it, adding that annotation turned this assertion red on v1.9.0 even
|
||||
# though the state it reported was the correct one. The suffix is deliberately
|
||||
# matched loosely rather than pinned to "(package copy)", because WHICH copy
|
||||
# shipped is already asserted authoritatively above, against the manifest field
|
||||
# and its measured tree hash, and duplicating that here in a regex would just
|
||||
# create a second place to update whenever the wording changes.
|
||||
# The boot banner must NOT carry the section: entrypoint-user.sh prints the
|
||||
# version FIRST, before the baked links exist and long before the skillset
|
||||
# deploy + reconcile run last, so anything it said about skill sources would be
|
||||
@@ -882,6 +906,24 @@ elif [ "$SIZE_MB" -le "$SIZE_THRESHOLD_MB" ]; then
|
||||
printf " ✅ size: %d MB (threshold %d MB)\n" "$SIZE_MB" "$SIZE_THRESHOLD_MB"; PASS=$((PASS+1))
|
||||
else
|
||||
printf " ❌ size: %d MB exceeds threshold %d MB\n" "$SIZE_MB" "$SIZE_THRESHOLD_MB"; FAIL=$((FAIL+1))
|
||||
# A bare "too big" verdict cost a full CI-log dig plus a local npm bisect to
|
||||
# attribute the v1.9.0 overshoot (+431 MB, which turned out to be npm 11
|
||||
# installing 26 @esbuild platform binaries per pi-coding-agent copy). The
|
||||
# container already knows where its bytes are, so make it say so: the biggest
|
||||
# layers, and the biggest directories under the paths that historically grow.
|
||||
# Same principle as the run() helper above — a red assertion should carry its
|
||||
# own diagnostic rather than send the next reader spelunking.
|
||||
echo " ── largest layers (docker history) ──"
|
||||
docker history --format '{{.Size}}\t{{.CreatedBy}}' "$IMAGE" 2>/dev/null \
|
||||
| grep -vE '^0B' | head -12 | sed 's/^/ /' | cut -c1-160
|
||||
echo " ── largest directories in the image ──"
|
||||
docker run --rm --entrypoint sh "$IMAGE" -c \
|
||||
'du -sm /usr/lib/node_modules/* /opt/* /usr/local/share/ms-playwright 2>/dev/null | sort -rn | head -12' \
|
||||
2>/dev/null | sed 's/^/ /' || echo " (could not inspect directories)"
|
||||
echo " ── @esbuild platform dirs (npm 11 regression sentinel) ──"
|
||||
docker run --rm --entrypoint sh "$IMAGE" -c \
|
||||
'find /usr/lib/node_modules /opt -type d -regex ".*/@esbuild/[^/]+" -printf "%f\n" 2>/dev/null | sort | uniq -c | sort -rn | head' \
|
||||
2>/dev/null | sed 's/^/ /' || true
|
||||
fi
|
||||
|
||||
# ── Summary ───────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user