f7c34091b1
Mirrors the pi-devbox v0.75.5b fix (2026-05-23) onto the four-variant pipeline here. The with-pi, omos, and omos-with-pi variants install upstream npm packages whose *_VERSION build-args defaulted to 'latest'. When the build-arg string is byte-identical across builds, the layer hash is identical and the registry buildcache silently reuses the layer from whatever upstream version was current when the cache was first populated — same mechanism that shipped pi-devbox v0.74.0..v0.75.5 with identical image bytes. Currently masked here because OPENCODE_VERSION is a hard-coded ARG that bumps every release; parent-chain cache invalidation flushes the downstream pi/omos layers. Masking would fail on any vN.N.Nb opencode- version-unchanged release that only bumps pi or omos. Filed last night as parked followup; fixing preventatively now that #5 (AWS SSO inside tor-ms22 container) cleared. CHANGES .gitea/workflows/docker-publish-split.yml — new resolve-versions job running 'npm view @earendil-works/pi-coding-agent version' and 'npm view oh-my-opencode-slim version', exposing concrete strings as job outputs. All six affected jobs (smoke-omos, smoke-with-pi, smoke-omos-with-pi, build-variant-omos, build-variant-with-pi, build-variant-omos-with-pi) now consume them as PI_VERSION / OMOS_VERSION build-args. smoke-base / build-variant-base unaffected. scripts/smoke-test.sh — new run_expect helper asserting an expected substring in command output. The pi check uses EXPECTED_PI_VERSION; the omos check uses EXPECTED_OMOS_VERSION against npm ls -g. Both env vars are wired from resolve-versions outputs in the smoke jobs. Catches this regression class on the next release, not four releases later. Dockerfile.variant — comment blocks above OPENCODE_VERSION (source- pinned, not subject to the bug), PI_VERSION (CI-resolved), and OMOS_VERSION (CI-resolved) explaining the cache-hit footgun. AGENTS.md — new convention bullet under 'Critical conventions' naming the resolve-versions job + EXPECTED_*_VERSION wiring as the contract to keep in lockstep when modifying variant build-args. .gitea/README.md — Step 1 expanded to cover the parallel resolve- versions job alongside base-decide; pipeline diagram updated. CHANGELOG.md — Unreleased entry describing the fix, masking mechanism, and audit footprint. No image-content change expected on the next release vs what 'latest' would have resolved to anyway. Purely makes the cache invalidate correctly going forward.
133 lines
6.5 KiB
Docker
133 lines
6.5 KiB
Docker
# opencode-devbox — variant image
|
|
#
|
|
# FROMs a base-<hash> image produced by Dockerfile.base and adds only
|
|
# the variant-specific tools (opencode, pi, oh-my-opencode-slim, Go).
|
|
#
|
|
# The four published variants are produced from THIS Dockerfile by
|
|
# varying build args:
|
|
#
|
|
# variant INSTALL_OPENCODE INSTALL_OMOS INSTALL_PI
|
|
# ───────────────── ──────────────── ──────────── ──────────
|
|
# base true false false
|
|
# omos true true false
|
|
# with-pi true false true
|
|
# omos-with-pi true true true
|
|
#
|
|
# Pass `--build-arg BASE_IMAGE=<repo>:base-<hash>` to select the base.
|
|
# The CI workflow computes the base hash from Dockerfile.base + rootfs/
|
|
# + entrypoint*.sh and feeds it in.
|
|
#
|
|
# IMPORTANT: the base image sets NPM_CONFIG_PREFIX to
|
|
# /home/developer/.pi/npm-global so runtime `pi install npm:...` and
|
|
# `npm install -g` by the developer user lands on the named volume.
|
|
# At BUILD time we want the baked binaries on /usr so they survive the
|
|
# volume mount. Each `npm install -g` below therefore prefixes the
|
|
# command with `NPM_CONFIG_PREFIX=/usr`.
|
|
|
|
ARG BASE_IMAGE
|
|
FROM ${BASE_IMAGE}
|
|
|
|
ARG TARGETARCH
|
|
ARG USER_NAME=developer
|
|
|
|
# ── Install opencode via npm ─────────────────────────────────────────
|
|
# OPENCODE_VERSION is intentionally pinned in this Dockerfile (not
|
|
# 'latest'). It drives the release tag and gets bumped via a source
|
|
# edit, so the cache-hit class of bug that bit pi-devbox v0.74.0..
|
|
# v0.75.5 cannot apply here.
|
|
ARG INSTALL_OPENCODE=true
|
|
ARG OPENCODE_VERSION=1.15.10
|
|
RUN if [ "${INSTALL_OPENCODE}" = "true" ]; then \
|
|
NPM_CONFIG_PREFIX=/usr npm install -g opencode-ai@${OPENCODE_VERSION} && \
|
|
opencode --version ; \
|
|
fi
|
|
|
|
# ── Optional: pi coding-agent ────────────────────────────────────────
|
|
# pi-toolkit and pi-extensions are cloned into /opt/. entrypoint-user.sh
|
|
# runs each repo's install.sh on container start so symlinks land under
|
|
# ~/.pi/agent/ on the named volume.
|
|
# PI_VERSION should be passed explicitly by CI as a concrete version
|
|
# (resolved from `npm view @earendil-works/pi-coding-agent version`,
|
|
# see .gitea/workflows/docker-publish-split.yml § resolve-versions).
|
|
# The default `latest` is for local dev convenience only — it has a
|
|
# known cache-hit footgun when used in registry-cached CI builds: the
|
|
# resulting build-arg string is byte-identical across builds, the
|
|
# layer-hash is identical, and the registry buildcache silently reuses
|
|
# the layer from whatever pi version was current when the cache was
|
|
# first populated. Currently masked here because OPENCODE_VERSION (a
|
|
# parent layer) bumps every release; will manifest the moment a
|
|
# vN.N.Nb opencode-version-unchanged release ships. See pi-devbox
|
|
# v0.75.5b 2026-05-23 for the discovery + canonical fix.
|
|
ARG INSTALL_PI=false
|
|
ARG PI_VERSION=latest
|
|
ARG PI_TOOLKIT_REF=main
|
|
ARG PI_EXTENSIONS_REF=main
|
|
RUN if [ "${INSTALL_PI}" = "true" ]; then \
|
|
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)" ; \
|
|
fi
|
|
|
|
# ── Optional: Go ─────────────────────────────────────────────────────
|
|
ARG INSTALL_GO=false
|
|
ARG GO_VERSION=latest
|
|
RUN if [ "${INSTALL_GO}" = "true" ]; then \
|
|
GOARCH=$(case "${TARGETARCH}" in amd64) echo "amd64" ;; arm64) echo "arm64" ;; *) echo "amd64" ;; esac) && \
|
|
V="${GO_VERSION}" && \
|
|
if [ "$V" = "latest" ]; then \
|
|
V=$(curl -fsSL --retry 5 --retry-delay 5 --retry-all-errors "https://go.dev/dl/?mode=json" | \
|
|
awk -F'"' '/"version":/ { sub(/^go/,"",$4); print $4; exit }'); \
|
|
fi && \
|
|
[ -n "$V" ] && \
|
|
echo "Installing Go ${V}" && \
|
|
curl -fsSL --retry 5 --retry-delay 5 --retry-all-errors "https://go.dev/dl/go${V}.linux-${GOARCH}.tar.gz" | tar -C /usr/local -xz && \
|
|
ln -s /usr/local/go/bin/go /usr/local/bin/go && \
|
|
ln -s /usr/local/go/bin/gofmt /usr/local/bin/gofmt; \
|
|
fi
|
|
|
|
# ── Optional: oh-my-opencode-slim (multi-agent orchestration) ────────
|
|
# Installs Bun runtime and the oh-my-opencode-slim npm package.
|
|
# OMOS_VERSION shares the same cache-hit footgun as PI_VERSION when
|
|
# left at the `latest` default in registry-cached CI builds. CI
|
|
# resolves it via `npm view oh-my-opencode-slim version` and passes
|
|
# the concrete value as a build-arg. See PI_VERSION block above.
|
|
ARG INSTALL_OMOS=false
|
|
ARG OMOS_VERSION=latest
|
|
RUN if [ "${INSTALL_OMOS}" = "true" ]; then \
|
|
ARCH=$(uname -m) && \
|
|
if [ "$ARCH" = "x86_64" ]; then \
|
|
BUN_ARCH="x64-baseline"; \
|
|
elif [ "$ARCH" = "aarch64" ]; then \
|
|
BUN_ARCH="aarch64"; \
|
|
fi && \
|
|
curl -fsSL --retry 5 --retry-delay 5 --retry-all-errors "https://github.com/oven-sh/bun/releases/latest/download/bun-linux-${BUN_ARCH}.zip" -o /tmp/bun.zip && \
|
|
unzip -o /tmp/bun.zip -d /tmp/bun && \
|
|
mv /tmp/bun/bun-linux-${BUN_ARCH}/bun /usr/local/bin/bun && \
|
|
chmod +x /usr/local/bin/bun && \
|
|
ln -sf bun /usr/local/bin/bunx && \
|
|
rm -rf /tmp/bun /tmp/bun.zip && \
|
|
bun --version && \
|
|
test -L /usr/local/bin/bunx && \
|
|
NPM_CONFIG_PREFIX=/usr npm install -g oh-my-opencode-slim@${OMOS_VERSION}; \
|
|
fi
|
|
|
|
# WORKDIR / ENTRYPOINT / CMD inherited from base.
|