8b69b3625b
The previous clone helper for these two repos (git_clone_retry) used
`git clone --branch <ref>`, which only accepts branch names or tags,
NOT commit SHAs. Run 374 (the workflow_dispatch retry of v1.0.0)
failed at smoke because the workflow's resolve-versions step had been
extended to resolve PI_TOOLKIT_REF and PI_EXTENSIONS_REF to commit
SHAs (commit b55b44e), and `git clone --branch <40-char-SHA>` fails
with 'Remote branch not found'.
Switching all four clones to git_fetch_ref (`git fetch + checkout
FETCH_HEAD`) makes the build accept both branch names AND SHAs
uniformly. Both Gitea and GitHub allow fetching arbitrary commits by
default (uploadpack.allowReachableSHA1InWant).
The unused git_clone_retry helper is removed; comment explaining the
choice and the historical context is in its place.
Image was published successfully on run 373; this only affects the
v1.0.0-rerun path (description fix). Image bytes unchanged because the
SHAs being passed match what run 373 cloned by branch name.
110 lines
5.8 KiB
Docker
110 lines
5.8 KiB
Docker
# pi-devbox — variant image
|
|
#
|
|
# FROMs a base-<hash> image produced by Dockerfile.base and adds only
|
|
# the variant-specific tools — currently just the pi install. Kept as a
|
|
# separate file (rather than collapsed into Dockerfile.base) so future
|
|
# variants (e.g. studio, studio-tex) can FROM the variant or extend
|
|
# this Dockerfile with additional build args without rebuilding the
|
|
# base on every pi version bump.
|
|
#
|
|
# Pass `--build-arg BASE_IMAGE=<repo>:base-<hash>` to select the base.
|
|
# CI 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
|
|
|
|
# ── pi coding-agent + companions ─────────────────────────────────────
|
|
# 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`).
|
|
# The default `latest` is for local dev convenience only — it has a
|
|
# known cache-hit footgun 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. CI MUST pass a resolved concrete version. See pi-devbox
|
|
# v0.75.5b 2026-05-23 for the discovery + canonical fix.
|
|
ARG PI_VERSION=latest
|
|
ARG PI_TOOLKIT_REF=main
|
|
ARG PI_EXTENSIONS_REF=main
|
|
# pi-fork (fork tool) + pi-observational-memory (recall tool) live on GitHub
|
|
# under elpapi42. CI resolves these to commit SHAs to defeat the same
|
|
# cache-hit footgun that affects PI_VERSION.
|
|
ARG PI_FORK_REPO=https://github.com/elpapi42/pi-fork.git
|
|
ARG PI_FORK_REF=master
|
|
ARG PI_OBSMEM_REPO=https://github.com/elpapi42/pi-observational-memory.git
|
|
ARG PI_OBSMEM_REF=master
|
|
|
|
RUN set -e && \
|
|
# git_fetch_ref: clone-equivalent helper that accepts EITHER a branch name
|
|
# OR a commit SHA as $ref. Uses `git fetch <ref> + checkout FETCH_HEAD`
|
|
# which (a) works with both name and SHA forms uniformly, and (b) defeats
|
|
# the registry-buildcache footgun when CI passes a resolved SHA. The
|
|
# earlier helper `git_clone_retry` (using `git clone --branch`) only
|
|
# worked with branch names — a SHA-resolved build-arg made `git clone
|
|
# --branch <40-char-SHA>` fail with "Remote branch not found". Surfaced
|
|
# in pi-devbox v1.0.0-rerun (run 374) 2026-06-10 and fixed by switching
|
|
# all four clones to git_fetch_ref. Both Gitea and GitHub allow fetching
|
|
# arbitrary commits by default (uploadpack.allowReachableSHA1InWant).
|
|
git_fetch_ref() { \
|
|
url="$1"; ref="$2"; dest="$3"; \
|
|
rm -rf "$dest"; mkdir -p "$dest"; \
|
|
git -C "$dest" init -q && git -C "$dest" remote add origin "$url" && \
|
|
for i in 1 2 3 4 5; do \
|
|
if git -C "$dest" fetch --depth 1 origin "$ref" && git -C "$dest" checkout -q FETCH_HEAD; then return 0; fi; \
|
|
echo "git fetch $url@$ref 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_fetch_ref "https://gitea.jordbo.se/joakimp/pi-toolkit.git" "${PI_TOOLKIT_REF}" /opt/pi-toolkit && \
|
|
git_fetch_ref "https://gitea.jordbo.se/joakimp/pi-extensions.git" "${PI_EXTENSIONS_REF}" /opt/pi-extensions && \
|
|
git_fetch_ref "${PI_FORK_REPO}" "${PI_FORK_REF}" /opt/pi-fork && \
|
|
git_fetch_ref "${PI_OBSMEM_REPO}" "${PI_OBSMEM_REF}" /opt/pi-observational-memory && \
|
|
(cd /opt/pi-fork && npm install --omit=dev --no-audit --no-fund) && \
|
|
(cd /opt/pi-observational-memory && npm install --omit=dev --no-audit --no-fund) && \
|
|
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)" && \
|
|
echo "pi-fork at $(cd /opt/pi-fork && git rev-parse --short HEAD)" && \
|
|
echo "pi-observational-memory at $(cd /opt/pi-observational-memory && git rev-parse --short HEAD)"
|
|
|
|
# ── Optional: Go toolchain ───────────────────────────────────────────
|
|
# Off by default; opt in for users who run Go tools inside the devbox.
|
|
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
|
|
|
|
# WORKDIR / ENTRYPOINT / CMD inherited from base.
|