diff --git a/.gitea/workflows/docker-publish.yml b/.gitea/workflows/docker-publish.yml index 75ef08c..968a267 100644 --- a/.gitea/workflows/docker-publish.yml +++ b/.gitea/workflows/docker-publish.yml @@ -47,6 +47,7 @@ env: jobs: # ── Phase 1: decide whether base needs rebuilding ────────────────── base-decide: + needs: [resolve-versions] runs-on: ubuntu-latest container: image: catthehacker/ubuntu:act-latest @@ -75,6 +76,10 @@ jobs: ! -name '._*' \ -print0 2>/dev/null | sort -z | xargs -0 cat 2>/dev/null cat entrypoint.sh entrypoint-user.sh + # mempalace-toolkit is cloned in Dockerfile.base at a ref CI + # resolves to a SHA; fold it in so base_tag changes when the + # toolkit moves (otherwise a toolkit-only fix never lands). + echo "${{ needs.resolve-versions.outputs.mempalace_toolkit_ref }}" } | sha256sum | cut -c1-12 ) BASE_TAG="base-${HASH}" @@ -117,6 +122,7 @@ jobs: toolkit_ref: ${{ steps.resolve.outputs.toolkit_ref }} extensions_ref: ${{ steps.resolve.outputs.extensions_ref }} studio_ref: ${{ steps.resolve.outputs.studio_ref }} + mempalace_toolkit_ref: ${{ steps.resolve.outputs.mempalace_toolkit_ref }} steps: - name: Resolve pi version + companion refs id: resolve @@ -151,6 +157,16 @@ jobs: [ -n "$EXTENSIONS_REF" ] || EXTENSIONS_REF=main echo "toolkit_ref=${TOOLKIT_REF}" >> "$GITHUB_OUTPUT" echo "extensions_ref=${EXTENSIONS_REF}" >> "$GITHUB_OUTPUT" + # Resolve mempalace-toolkit main HEAD to a SHA. UNLIKE the others, + # mempalace-toolkit is cloned in Dockerfile.base, so this SHA is + # ALSO folded into the base-decide hash to force a base rebuild + # when the toolkit moves (without it, a toolkit-only fix silently + # fails to land unless Dockerfile.base itself changes). + MEMPALACE_TOOLKIT_REF=$(curl -sf -H "Authorization: token ${GITEA_BUILD_TOKEN:-${GITHUB_TOKEN:-}}" \ + "https://gitea.jordbo.se/api/v1/repos/joakimp/mempalace-toolkit/commits?limit=1&sha=main" \ + | jq -r '.[0].sha // "main"' 2>/dev/null || echo "main") + [ -n "$MEMPALACE_TOOLKIT_REF" ] || MEMPALACE_TOOLKIT_REF=main + echo "mempalace_toolkit_ref=${MEMPALACE_TOOLKIT_REF}" >> "$GITHUB_OUTPUT" # Resolve pi-studio (omaclaren/pi-studio) main HEAD to a SHA for # the :latest-studio variant — same cache-busting rationale. STUDIO_REF=$(curl -sf -H "Accept: application/vnd.github.sha" \ @@ -161,10 +177,11 @@ jobs: echo "Resolved PI_FORK_REF=${FORK_REF}, PI_OBSMEM_REF=${OBSMEM_REF}" echo "Resolved PI_TOOLKIT_REF=${TOOLKIT_REF}, PI_EXTENSIONS_REF=${EXTENSIONS_REF}" echo "Resolved PI_STUDIO_REF=${STUDIO_REF}" + echo "Resolved MEMPALACE_TOOLKIT_REF=${MEMPALACE_TOOLKIT_REF}" # ── Phase 2: build & push base (multi-arch), only when needed ────── build-base: - needs: [base-decide] + needs: [base-decide, resolve-versions] if: needs.base-decide.outputs.need_build == 'true' runs-on: ubuntu-latest container: @@ -206,6 +223,7 @@ jobs: shell: bash env: BASE_TAG_FULL: ${{ env.IMAGE }}:${{ needs.base-decide.outputs.base_tag }} + MEMPALACE_TOOLKIT_REF: ${{ needs.resolve-versions.outputs.mempalace_toolkit_ref }} run: | set -euo pipefail # 3-attempt retry around `docker buildx build --push` for transient @@ -219,6 +237,7 @@ jobs: if docker buildx build \ --platform linux/amd64,linux/arm64 \ --file Dockerfile.base \ + --build-arg MEMPALACE_TOOLKIT_REF="${MEMPALACE_TOOLKIT_REF}" \ --push \ --tag "${BASE_TAG_FULL}" \ .; then diff --git a/CHANGELOG.md b/CHANGELOG.md index 2738ed1..b66d9b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,34 @@ Pre-v1.0.0 tags followed the pi npm version (`v{pi_version}[letter]`). --- +## Unreleased + +### Changed + +- **`mempalace-toolkit` is now CI-resolved to a commit SHA**, closing a + silent-staleness footgun. It is the only companion cloned in + `Dockerfile.base` (all others are cloned in `Dockerfile.variant`), so it + was never run through the `resolve-versions` → build-arg plumbing. Its + ref stayed a literal `main`, and because the base only rebuilds when the + hash of `Dockerfile.base + rootfs/* + entrypoints` changes, a + toolkit-only fix would *not* land in the image unless `Dockerfile.base` + itself happened to change (as it did, incidentally, in v1.1.1). + + Now `resolve-versions` resolves `mempalace-toolkit` `main` HEAD to a SHA + (new `mempalace_toolkit_ref` output), `base-decide` folds that SHA into + the base-tag hash (so a moved toolkit forces a base rebuild), and + `build-base` passes it as `--build-arg MEMPALACE_TOOLKIT_REF`. The base + clone switched from `git clone --branch` to a SHA-capable + `git fetch + checkout FETCH_HEAD` (the `--branch <40-char-SHA>` + footgun previously fixed in `Dockerfile.variant`, run 374). + + Note: `base-decide` now depends on `resolve-versions`, so the base tag + reflects a live gitea API lookup. On an API blip it falls back to `main` + — which hashes differently than a SHA and triggers one *extra* rebuild, + never a *missed* one (fail-toward-rebuild). + +--- + ## v1.1.1 — 2026-06-13 Patch release: pi `0.79.1` → `0.79.3` (auto-resolved at build) plus the diff --git a/Dockerfile.base b/Dockerfile.base index c44ae25..9a00ee1 100644 --- a/Dockerfile.base +++ b/Dockerfile.base @@ -336,9 +336,23 @@ RUN if [ "${INSTALL_MEMPALACE}" = "true" ]; then \ # ── mempalace-toolkit — bash wrappers for session/docs mining ──────── ARG INSTALL_MEMPALACE_TOOLKIT=true ARG MEMPALACE_TOOLKIT_REF=main +# MEMPALACE_TOOLKIT_REF accepts EITHER a branch name OR a commit SHA. CI +# resolves it to a SHA (resolve-versions job) and folds that SHA into the +# base-decide hash so the base rebuilds when the toolkit moves. `git clone +# --branch <40-char-SHA>` fails ("Remote branch not found") — the same +# footgun fixed in Dockerfile.variant (v1.0.0-rerun, run 374) — so use +# `git fetch + checkout FETCH_HEAD`, which works for name and SHA. RUN if [ "${INSTALL_MEMPALACE}" = "true" ] && [ "${INSTALL_MEMPALACE_TOOLKIT}" = "true" ]; then \ - git clone --depth 1 --branch "${MEMPALACE_TOOLKIT_REF}" \ - https://gitea.jordbo.se/joakimp/mempalace-toolkit.git /opt/mempalace-toolkit && \ + rm -rf /opt/mempalace-toolkit && mkdir -p /opt/mempalace-toolkit && \ + git -C /opt/mempalace-toolkit init -q && \ + git -C /opt/mempalace-toolkit remote add origin https://gitea.jordbo.se/joakimp/mempalace-toolkit.git && \ + ok=0; for i in 1 2 3 4 5; do \ + if git -C /opt/mempalace-toolkit fetch --depth 1 origin "${MEMPALACE_TOOLKIT_REF}" && \ + git -C /opt/mempalace-toolkit checkout -q FETCH_HEAD; then ok=1; break; fi; \ + echo "git fetch mempalace-toolkit@${MEMPALACE_TOOLKIT_REF} failed (attempt $i/5), retrying in $((i*5))s..."; \ + sleep $((i*5)); \ + done; \ + [ "$ok" = "1" ] && \ ln -sf /opt/mempalace-toolkit/bin/mempalace-session /usr/local/bin/mempalace-session && \ ln -sf /opt/mempalace-toolkit/bin/mempalace-docs /usr/local/bin/mempalace-docs && \ chmod +x /opt/mempalace-toolkit/bin/mempalace-session /opt/mempalace-toolkit/bin/mempalace-docs && \