From de2ab5ab33a131f7b8bb5331d409860ecde89887 Mon Sep 17 00:00:00 2001 From: Hongming Wang Date: Mon, 27 Apr 2026 07:46:14 -0700 Subject: [PATCH] feat: forward client_payload.runtime_version + ARG RUNTIME_VERSION MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes the cache trap structurally (instead of pin-bumping every runtime release): 1. publish-image.yml caller now forwards github.event.client_payload.runtime_version (set by cascade) to the molecule-ci reusable workflow as runtime_version input. 2. Reusable workflow forwards it to docker build as a --build-arg. 3. Dockerfile declares ARG RUNTIME_VERSION near the pip install layer so its value becomes part of the cache key. 4. The pip install RUN command does an extra targeted upgrade to the exact version when ARG is set — guarantees the version is what we expect even if requirements.txt resolves to something else. Pairs with molecule-ci PR #12 + molecule-core PR #2181. Together the pipeline is now race- and cache-proof end-to-end. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/publish-image.yml | 13 +++++++++++++ Dockerfile | 19 +++++++++++++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml index 8eea149..69052f1 100644 --- a/.github/workflows/publish-image.yml +++ b/.github/workflows/publish-image.yml @@ -16,6 +16,11 @@ on: branches: [main] pull_request: workflow_dispatch: + inputs: + runtime_version: + description: "Optional explicit runtime version to bake in (forwarded as RUNTIME_VERSION build-arg)" + required: false + type: string permissions: contents: read @@ -25,3 +30,11 @@ jobs: publish: uses: Molecule-AI/molecule-ci/.github/workflows/publish-template-image.yml@main secrets: inherit + with: + # When the cascade fires, client_payload.runtime_version is the + # exact version PyPI just published. Forwarded to the reusable + # workflow as a docker --build-arg so the cache key changes + # per-version and pip install resolves freshly. + # On other events (push/PR/manual without input), this is empty + # and the Dockerfile's default (requirements.txt pin) applies. + runtime_version: ${{ github.event.client_payload.runtime_version || inputs.runtime_version || '' }} diff --git a/Dockerfile b/Dockerfile index 6c96e9c..6f7b0f7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -21,9 +21,24 @@ RUN npm install -g @anthropic-ai/claude-code 2>/dev/null || true RUN useradd -u 1000 -m -s /bin/bash agent WORKDIR /app -# Install Python deps +# RUNTIME_VERSION is forwarded from the reusable publish workflow as +# a docker build-arg. When set (cascade-triggered builds), it's the +# exact runtime version PyPI just published. Including it as an ARG +# changes the cache key for the pip install layer below — without +# this, identical Dockerfile + identical requirements.txt content +# would let docker reuse the cached layer with the previous version +# baked in (the cache trap that bit us 5x on 2026-04-27). +# Empty default = falls back to whatever requirements.txt resolves to. +ARG RUNTIME_VERSION= + +# Install Python deps. The RUNTIME_VERSION ARG is a no-op argument to +# the RUN command itself but its presence as a declared ARG above +# means buildx hashes it into the cache key. COPY requirements.txt . -RUN pip install --no-cache-dir -r requirements.txt +RUN pip install --no-cache-dir -r requirements.txt && \ + if [ -n "${RUNTIME_VERSION}" ]; then \ + pip install --no-cache-dir --upgrade "molecule-ai-workspace-runtime==${RUNTIME_VERSION}"; \ + fi # Copy adapter code COPY adapter.py .