refactor: re-brand the opencode-devbox with-pi variant (single source of truth)

pi-devbox no longer installs pi itself. The Dockerfile is now a thin
FROM joakimp/opencode-devbox:latest-with-pi (overridable via BASE_IMAGE),
inheriting pi + pi-toolkit + pi-extensions + pi-fork (fork) +
pi-observational-memory (recall) + the LAN-access helper + all base tooling
from the single source of truth. Eliminates the install-logic duplication
that drifted against opencode-devbox/Dockerfile.variant (decision #3).

Consequences (documented in CHANGELOG/AGENTS):
- The image now ALSO contains opencode (with-pi has INSTALL_OPENCODE=true).
  A leaner pi-only image would need a dedicated pi-only variant upstream.
- Publish ordering: release opencode-devbox first so latest-with-pi carries
  the target pi version, THEN tag this repo. The smoke test asserts
  pi --version matches the tag (EXPECTED_PI_VERSION) and fails loudly if the
  base is stale — turning the version coupling into an enforced ordering guard.

CI: drop PI_VERSION build-arg (Dockerfile installs nothing); keep tag->version
resolution to feed the smoke base-freshness guard. Smoke adds fork/recall
clone + node_modules + settings.json registration checks; size threshold
2200 -> 2900 MB (now tracks with-pi). Docs updated across README, AGENTS,
DOCKER_HUB, .env.example, docker-compose.
This commit is contained in:
pi
2026-06-03 15:51:41 +02:00
parent 1587a84579
commit c139be326f
9 changed files with 160 additions and 120 deletions
+24 -56
View File
@@ -1,62 +1,30 @@
# pi-devbox — pi coding-agent container
#
# Builds on top of the opencode-devbox base image, which provides:
# Debian trixie, Node.js, AWS CLI, mempalace + MCP server, gitea-mcp,
# dev tools (neovim, tmux, bat, eza, fzf, zoxide, ripgrep, uv, rustup,
# git-crypt, gitleaks),
# user setup (developer/gosu), entrypoints, chromadb prewarm.
# As of 2026-06-03 this image is a thin re-brand of the opencode-devbox
# "with-pi" variant, which is the SINGLE SOURCE OF TRUTH for the pi install
# and its companion repos (pi-toolkit, pi-extensions, pi-fork,
# pi-observational-memory). Previously pi-devbox/Dockerfile duplicated that
# install logic, which drifted from opencode-devbox/Dockerfile.variant; this
# refactor eliminates the duplication.
#
# This image adds only pi itself and its companion repos.
# Everything is inherited from the with-pi image:
# pi + pi-toolkit + pi-extensions + pi-fork (fork) + pi-observational-memory
# (recall), the mempalace bridge, the LAN-access helper, entrypoints, and
# all base dev tooling.
#
# Build args:
# BASE_IMAGE — base image to build from (default: base-latest)
# PI_VERSION — pi npm version: "latest" or a pinned version e.g. "0.74.0"
# PI_TOOLKIT_REF — git ref for pi-toolkit (default: main)
# PI_EXTENSIONS_REF — git ref for pi-extensions (default: main)
ARG BASE_IMAGE=joakimp/opencode-devbox:base-latest
# NOTES / consequences of FROM-ing with-pi:
# - This image now ALSO contains opencode (with-pi has INSTALL_OPENCODE=true).
# If a leaner pi-only image is wanted later, add a dedicated pi-only variant
# to opencode-devbox and FROM that instead.
# - PUBLISH ORDERING: rebuild opencode-devbox (so `latest-with-pi` carries the
# target pi version) BEFORE tagging this repo. The smoke test asserts
# `pi --version` matches this repo's tag and fails loudly if the base is
# stale — turning the version coupling into an enforced ordering check.
#
# Override BASE_IMAGE to pin a specific with-pi build (e.g. a version tag or a
# digest) instead of tracking latest-with-pi.
ARG BASE_IMAGE=joakimp/opencode-devbox:latest-with-pi
FROM ${BASE_IMAGE}
# PI_VERSION should be passed explicitly by CI as a concrete version
# (e.g. PI_VERSION=0.75.5, derived from the git tag). The default `latest`
# is for local dev convenience only — it has a known cache-hit footgun
# when used in registry-cached CI builds. See .gitea/workflows/docker-
# publish.yml § "Resolve PI_VERSION from tag" and AGENTS.md gotcha for
# the full story (silent same-bytes-across-releases regression discovered
# 2026-05-23 affecting all builds v0.74.0..v0.75.5).
ARG PI_VERSION=0.78.0
ARG PI_TOOLKIT_REF=main
ARG PI_EXTENSIONS_REF=main
# Install pi and clone companion repos.
# NPM_CONFIG_PREFIX is overridden to /usr so the baked binary lands at the
# system prefix — same pattern as opencode-devbox's variant Dockerfile.
# At runtime, NPM_CONFIG_PREFIX is reset to /home/developer/.pi/npm-global
# (inherited from base ENV) so user-installed packages land on the named
# volume and survive container recreate.
#
# git clone is wrapped in a retry loop because gitea.jordbo.se occasionally
# returns transient HTTP 500s on the first request after idle.
RUN set -e && \
git_clone_retry() { \
url="$1"; ref="$2"; dest="$3"; \
for i in 1 2 3 4 5; do \
if git clone --depth 1 --branch "$ref" "$url" "$dest"; then return 0; fi; \
rm -rf "$dest"; \
echo "git clone $url failed (attempt $i/5), retrying in $((i*5))s..."; \
sleep $((i*5)); \
done; \
return 1; \
} && \
if [ "${PI_VERSION}" = "latest" ]; then \
NPM_CONFIG_PREFIX=/usr npm install -g @earendil-works/pi-coding-agent ; \
else \
NPM_CONFIG_PREFIX=/usr npm install -g @earendil-works/pi-coding-agent@${PI_VERSION} ; \
fi && \
pi --version && \
git_clone_retry https://gitea.jordbo.se/joakimp/pi-toolkit.git "${PI_TOOLKIT_REF}" /opt/pi-toolkit && \
git_clone_retry https://gitea.jordbo.se/joakimp/pi-extensions.git "${PI_EXTENSIONS_REF}" /opt/pi-extensions && \
echo "pi-toolkit at $(cd /opt/pi-toolkit && git rev-parse --short HEAD)" && \
echo "pi-extensions at $(cd /opt/pi-extensions && git rev-parse --short HEAD)"
# WORKDIR / ENTRYPOINT / CMD inherited from base.
# WORKDIR / ENTRYPOINT / CMD and all tooling inherited from the base.
# No additional layers — the value here is the single-source-of-truth refactor.