v2.0.0: remove pi, relocate npm-global prefix, bump opencode 1.17.2->1.17.4
Validate / base-change-warning (push) Successful in 14s
Validate / docs-check (push) Successful in 13s
Publish Docker Image / resolve-versions (push) Successful in 8s
Publish Docker Image / base-decide (push) Successful in 13s
Validate / validate-omos (push) Successful in 12m42s
Validate / validate-base (push) Successful in 13m39s
Publish Docker Image / build-base (push) Successful in 44m17s
Publish Docker Image / smoke-base (push) Successful in 3m46s
Publish Docker Image / smoke-omos (push) Successful in 5m54s
Publish Docker Image / build-variant-base (push) Successful in 18m11s
Publish Docker Image / build-variant-omos (push) Successful in 19m34s
Publish Docker Image / promote-base-latest (push) Successful in 9s
Publish Docker Image / update-description (push) Successful in 15s

PR-5 (per docs/CLEANUP-v2.0.0.md). Major release with two breaking changes:

1. pi fully removed (deprecated in v1.17.2). Gone: INSTALL_PI + all PI_*
   build args; with-pi/omos-with-pi/pi-only variants; base-pi-only publish
   job; all ~/.pi entrypoint wiring; the 3 pi smoke/validate/build-variant
   CI jobs. Only base + omos variants remain (4 tags/release).

2. NPM_CONFIG_PREFIX relocated ~/.pi/npm-global -> ~/.config/opencode/npm-global
   (persistent in both compose files). entrypoint-user.sh gains a one-time
   migration shim that copies old global npm packages forward.

Also: opencode 1.17.2->1.17.4; DOCKER_HUB.md gains {{OPENCODE_VERSION}}
placeholder filled by CI at publish time (mirrors pi-devbox); full docs
drift sweep across README/AGENTS/.gitea-README/.env.example/manual-host-publish;
DOCKER_HUB.md regenerated + --check passes; both workflows YAML-valid;
all shell scripts pass bash -n.
This commit is contained in:
pi
2026-06-13 16:59:40 +02:00
parent c8217814c8
commit 72298ae77e
17 changed files with 334 additions and 1210 deletions
+16 -138
View File
@@ -8,7 +8,7 @@
# - Generated opencode.json has the expected shape
# - MCP wrapper works (when mempalace is installed)
#
# Usage: ./scripts/smoke-test.sh <image> [--variant base|omos|with-pi|omos-with-pi|pi-only]
# Usage: ./scripts/smoke-test.sh <image> [--variant base|omos]
#
# Exit codes:
# 0 all checks passed
@@ -23,7 +23,7 @@ if [ "${2:-}" = "--variant" ]; then
fi
if [ -z "$IMAGE" ]; then
echo "usage: $0 <image> [--variant base|omos|with-pi|omos-with-pi|pi-only]" >&2
echo "usage: $0 <image> [--variant base|omos]" >&2
exit 2
fi
@@ -32,16 +32,10 @@ pass() { echo " ✓ $1"; }
fail() { echo "$1" >&2; FAILED=$((FAILED + 1)); }
warn() { echo "$1" >&2; }
# Registration assertions (fork/recall installed by the BASE image's
# entrypoint-user.sh via `pi install /opt/<pkg>`) depend on the base, not the
# variant layer built here. validate.yml builds variants FROM the published
# base-latest, which can lag the entrypoint in the current commit (the base
# only rebuilds on a release tag), so a stale base-latest would red the
# push-to-main run with a false negative. These checks are therefore warn-only
# by default; the release pipeline (docker-publish-split.yml) builds the base
# fresh in the same run and sets STRICT_REGISTRATION=1 to enforce them hard.
# The build-time /opt + node_modules checks below stay hard in every path —
# those are produced by the variant layer and must always be correct.
# Registration assertions for fork/recall were removed in v2.0.0 along with
# pi. STRICT_REGISTRATION is retained as an inert env var for backward
# compatibility with any external caller that still sets it; it has no
# effect now that no pi packages are deployed.
STRICT_REGISTRATION="${STRICT_REGISTRATION:-0}"
run() {
@@ -85,9 +79,6 @@ docker run --rm --entrypoint="" "$IMAGE" sh -c '
if command -v opencode >/dev/null 2>&1; then
printf " %-15s %s\n" "opencode" "$(opencode --version 2>&1 | head -1)"
fi
if command -v pi >/dev/null 2>&1; then
printf " %-15s %s\n" "pi" "$(pi --version 2>&1 | head -1)"
fi
printf " %-15s %s\n" "node" "$(node --version)"
printf " %-15s %s\n" "npm" "$(npm --version)"
printf " %-15s %s\n" "nvim" "$(nvim --version | head -1)"
@@ -117,7 +108,7 @@ docker run --rm --entrypoint="" "$IMAGE" sh -c '
echo
echo "-- Core binaries --"
# opencode is gated on INSTALL_OPENCODE=true (default). When absent, the
# image is a pi-only build (or a pure base no harness at all).
# image is a pure base with no harness at all.
if docker run --rm --entrypoint="" "$IMAGE" sh -c "command -v opencode" >/dev/null 2>&1; then
run "opencode" "opencode --version"
else
@@ -171,116 +162,15 @@ elif docker run --rm --entrypoint="" "$IMAGE" sh -c "command -v mempalace" >/dev
echo " - mempalace-toolkit not installed (INSTALL_MEMPALACE_TOOLKIT=false)"
fi
# pi: present when built with INSTALL_PI=true. Verifies pi itself plus
# the runtime-deployed pi-toolkit + pi-extensions + mempalace bridge
# symlinks under ~/.pi/agent/. Note: extension symlinks are created by
# entrypoint-user.sh on first start, so we test by running the entry
# point chain (not just `docker run --entrypoint=""`).
if docker run --rm --entrypoint="" "$IMAGE" sh -c "command -v pi" >/dev/null 2>&1; then
if [ -n "${EXPECTED_PI_VERSION:-}" ]; then
run_expect "pi version matches build-arg" "pi --version" "$EXPECTED_PI_VERSION"
else
run "pi" "pi --version"
fi
run "pi-toolkit clone" "test -d /opt/pi-toolkit && git -C /opt/pi-toolkit rev-parse --short HEAD"
run "pi-extensions clone" "test -d /opt/pi-extensions && git -C /opt/pi-extensions rev-parse --short HEAD"
# pi-fork (fork tool) + pi-observational-memory (recall tool): cloned to
# /opt with node_modules baked at build time (a local-path `pi install` does
# NOT npm-install, so deps MUST already be present for the extension to load).
run "pi-fork clone + node_modules" \
"test -f /opt/pi-fork/package.json && test -d /opt/pi-fork/node_modules && echo ok"
run "pi-observational-memory clone + node_modules" \
"test -f /opt/pi-observational-memory/package.json && test -d /opt/pi-observational-memory/node_modules && echo ok"
# Run the full entrypoint as developer to verify install.sh deployment.
# Spin up a long-running container so we can `docker exec` into it from
# the host — the `run` helper above invokes commands INSIDE the image
# and has no docker CLI to nest with.
CID=$(docker run -d --rm "$IMAGE" tail -f /dev/null)
trap 'docker rm -f "$CID" >/dev/null 2>&1 || true' EXIT
# Wait for entrypoint-user.sh to finish deploying pi-toolkit + extensions.
# The deploy order is: pi-toolkit (writes keybindings.json) -> pi-extensions
# (symlinks its *.ts) -> settings.json -> mempalace.ts bridge (LAST). Gating
# only on keybindings.json races: it lands when pi-toolkit finishes, before
# pi-extensions has symlinked its *.ts, so the "*.ts >= 4" check below could
# sample mid-deploy under parallel build load (observed v1.16.2 run 370:
# smoke-with-pi saw <4 .ts while omos-with-pi/pi-only saw 8). Wait for the
# LAST-deployed artifact (the mempalace.ts bridge symlink) AND a settled
# extension count so the deploy is fully complete before any assertion runs.
# Up to 45s — pi-bearing variants have more setup work under load.
for _ in $(seq 1 45); do
if docker exec "$CID" sh -c \
'test -L $HOME/.pi/agent/keybindings.json && \
test -L $HOME/.pi/agent/extensions/mempalace.ts && \
[ "$(ls -1 $HOME/.pi/agent/extensions/*.ts 2>/dev/null | wc -l)" -ge 4 ]' \
2>/dev/null; then
break
fi
sleep 1
done
exec_test() {
local label="$1"; shift
local out
if out=$(docker exec -u developer "$CID" sh -c "$*" 2>&1); then
pass "$label ($(echo "$out" | head -1))"
else
fail "$label: $out"
fi
}
# Like exec_test but warn-only unless STRICT_REGISTRATION=1 (see note at top).
exec_test_reg() {
local label="$1"; shift
local out
if out=$(docker exec -u developer "$CID" sh -c "$*" 2>&1); then
pass "$label ($(echo "$out" | head -1))"
elif [ "$STRICT_REGISTRATION" = "1" ]; then
fail "$label: $out"
else
warn "$label (warn-only — stale base-latest? set STRICT_REGISTRATION=1 to enforce): $out"
fi
}
exec_test "~/.pi/agent/keybindings.json (pi-toolkit)" \
'test -L $HOME/.pi/agent/keybindings.json && echo ok'
exec_test "~/.pi/agent/extensions/*.ts ≥ 4 (pi-extensions)" \
'count=$(ls -1 $HOME/.pi/agent/extensions/*.ts 2>/dev/null | wc -l); [ $count -ge 4 ] && echo "$count extensions"'
exec_test "~/.pi/agent/extensions/mempalace.ts (bridge)" \
'test -L $HOME/.pi/agent/extensions/mempalace.ts && echo ok'
exec_test "~/.pi/agent/settings.json (template bootstrap)" \
'test -f $HOME/.pi/agent/settings.json && echo ok'
# pi-fork + pi-observational-memory are registered by entrypoint-user.sh via
# `pi install /opt/<pkg>` (records a relative path into settings.json
# packages). That runs slightly after the keybindings marker, so wait for it.
for _ in $(seq 1 15); do
if docker exec "$CID" grep -q pi-observational-memory \
/home/developer/.pi/agent/settings.json 2>/dev/null; then
break
fi
sleep 1
done
exec_test_reg "pi-fork registered in settings.json (fork tool)" \
'grep -q pi-fork $HOME/.pi/agent/settings.json && echo ok'
exec_test_reg "pi-observational-memory registered in settings.json (recall tool)" \
'grep -q pi-observational-memory $HOME/.pi/agent/settings.json && echo ok'
docker rm -f "$CID" >/dev/null 2>&1 || true
trap - EXIT
else
echo " - pi not installed (INSTALL_PI=false)"
fi
# bun: only in the omos and omos-with-pi variants
if [ "$VARIANT" = "omos" ] || [ "$VARIANT" = "omos-with-pi" ]; then
# bun: only in the omos variant
if [ "$VARIANT" = "omos" ]; then
run "bun (omos)" "bun --version"
run "bunx symlink (omos)" "test -L /usr/local/bin/bunx && readlink /usr/local/bin/bunx"
# oh-my-opencode-slim is npm-installed globally (not a bun install);
# verify it shows up in the global module list. We must explicitly point
# npm at the system prefix (/usr) here: the image's NPM_CONFIG_PREFIX env
# is set to /home/developer/.pi/npm-global so user-installed packages
# is set to /home/developer/.config/opencode/npm-global so user-installed
# packages
# land on the persistent volume — which means a default `npm ls -g`
# queries the user prefix and would miss the baked binaries even though
# they're correctly on PATH at /usr/bin.
@@ -387,17 +277,10 @@ SIZE_BYTES=$(docker image inspect --format='{{.Size}}' "$IMAGE")
SIZE_MB=$((SIZE_BYTES / 1024 / 1024))
echo " Uncompressed size: ${SIZE_MB} MB"
# Thresholds (uncompressed): base 2500 MB, omos 3300 MB, with-pi adds ~150 MB.
# Thresholds (uncompressed): base 2600 MB, omos 3300 MB.
# omos bumped 3000→3200 on v1.14.31c — mempalace-toolkit bake-in pushed the
# baseline; bumped 3200→3300 on v1.15.0 — opencode 1.15.0 came in at
# 3206 MB, leaving zero headroom for routine apt-get upgrade drift.
# omos-with-pi bumped 3400→3500 on v1.15.0 alongside the omos bump.
# omos-with-pi bumped 3500→3700 on v1.15.4b — omos+pi compounded as both
# upstream packages grew (opencode 1.15.0→1.15.4, pi 0.74.0→0.75.3) and
# the variant landed just over 3500 in v1.15.4's smoke.
# with-pi 2700→2900 and omos-with-pi 3700→3900: baking pi-fork +
# pi-observational-memory node_modules into /opt (fork pulls its
# @earendil-works peer deps, ~150 MB) adds to both pi-bearing variants.
# base 2500→2600 on v1.15.13c — base crept to 2506 MB (LAN-access script +
# updated entrypoint + routine apt-get upgrade drift), tripping the
# deliberately zero-headroom 2500 ceiling and skipping promote-base-latest.
@@ -406,17 +289,12 @@ echo " Uncompressed size: ${SIZE_MB} MB"
# v1.16.2: all thresholds bumped +150 MB preemptively ahead of the combined
# opencode 1.15.13->1.16.2 (minor) + pi 0.78.1->0.79.0 (minor) bump. Both
# base (2506/2600) and omos (3206/3300) were sitting on ~94 MB headroom and
# a minor opencode bump has tripped them before (v1.15.0 omos, v1.15.4
# omos-with-pi). Restoring ~250 MB headroom avoids a partial-publish +
# letter-suffix recovery cycle. CI's smoke size print + resolved-versions
# table records the actual landed sizes; tighten later if they come in low.
# a minor opencode bump has tripped them before (v1.15.0 omos). Restoring
# ~250 MB headroom avoids a partial-publish + letter-suffix recovery cycle.
# CI's smoke size print + resolved-versions table records the actual landed
# sizes; tighten later if they come in low.
THRESHOLD=2750
[ "$VARIANT" = "omos" ] && THRESHOLD=3450
[ "$VARIANT" = "with-pi" ] && THRESHOLD=3050
[ "$VARIANT" = "omos-with-pi" ] && THRESHOLD=4050
# pi-only = with-pi minus opencode (its platform binary is ~145 MB), so it
# lands a bit under base. Threshold 2750 leaves the same headroom pattern.
[ "$VARIANT" = "pi-only" ] && THRESHOLD=2850
if [ "$SIZE_MB" -gt "$THRESHOLD" ]; then
fail "image size ${SIZE_MB} MB exceeds threshold ${THRESHOLD} MB for variant=$VARIANT"
else