From 9b42a5e31134d95465c2b63f5081bd4f63bb9249 Mon Sep 17 00:00:00 2001 From: rabbitblood Date: Sun, 26 Apr 2026 01:30:36 -0700 Subject: [PATCH] test(ci): runtime + a2a-sdk pin compatibility gate (controlplane#253) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes Molecule-AI/molecule-controlplane#253. Prevents recurrence of the 5-hour staging outage from 2026-04-24: molecule-ai-workspace-runtime 0.1.13 declared `a2a-sdk<1.0` in its metadata but actually imported `a2a.server.routes` (1.0+ only). pip resolved successfully; every tenant workspace crashed at import. The canary tenant ultimately caught it but only after 5 hours of degraded staging. PR #249 fixed the version pin manually; nothing automated catches the same class of bug for the next release. This workflow: - Installs molecule-ai-workspace-runtime fresh from PyPI in a Python 3.11 venv (mirrors EC2 user-data install pattern) - Layers in workspace/requirements.txt (the runtime image's actual dep set, including the a2a-sdk[http-server]>=1.0,<2.0 pin) - Runs `from molecule_runtime.main import main_sync` — same import the runtime entrypoint does - Fails CI if pip resolution silently produced a combo that the runtime can't actually import Triggers: - PR + push to main/staging touching workspace/requirements.txt or this workflow (catches local pin changes) - Daily 13:00 UTC schedule (catches upstream PyPI publishes that break the pin combo without any change in our repo) - workflow_dispatch (manual) Concurrency cancels in-progress runs on the same ref. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/runtime-pin-compat.yml | 59 ++++++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 .github/workflows/runtime-pin-compat.yml diff --git a/.github/workflows/runtime-pin-compat.yml b/.github/workflows/runtime-pin-compat.yml new file mode 100644 index 00000000..042620e8 --- /dev/null +++ b/.github/workflows/runtime-pin-compat.yml @@ -0,0 +1,59 @@ +name: Runtime Pin Compatibility + +# CI gate that prevents the 5-hour staging outage from 2026-04-24 from +# recurring (controlplane#253). The original failure mode: +# 1. molecule-ai-workspace-runtime 0.1.13 declared `a2a-sdk<1.0` in its +# requires_dist metadata (incorrect — it actually imports +# a2a.server.routes which only exists in a2a-sdk 1.0+) +# 2. `pip install molecule-ai-workspace-runtime` resolved cleanly +# 3. `from molecule_runtime.main import main_sync` raised ImportError +# 4. Every tenant workspace crashed; the canary tenant caught it but +# only after 5 hours of degraded staging +# +# This workflow installs the runtime in a fresh Python venv from PyPI +# and tries the same import the EC2 user-data does. If pip resolution +# silently produces a broken combo, this gate fails before the tenant +# image gets published. + +on: + push: + branches: [main, staging] + paths: + - 'workspace/requirements.txt' + - '.github/workflows/runtime-pin-compat.yml' + pull_request: + branches: [main, staging] + paths: + - 'workspace/requirements.txt' + - '.github/workflows/runtime-pin-compat.yml' + # Daily catch for upstream PyPI publishes that break the pin combo + # without any change in our repo (e.g. someone re-yanks an a2a-sdk + # release or molecule-ai-workspace-runtime publishes a bad bump). + schedule: + - cron: '0 13 * * *' # 06:00 PT + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + default-install: + name: Default install + import smoke + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: Install runtime + workspace requirements + run: | + python -m venv /tmp/venv + /tmp/venv/bin/pip install --upgrade pip + /tmp/venv/bin/pip install molecule-ai-workspace-runtime + /tmp/venv/bin/pip install -r workspace/requirements.txt + /tmp/venv/bin/pip show molecule-ai-workspace-runtime a2a-sdk \ + | grep -E '^(Name|Version):' + - name: Smoke import — fail if metadata declares deps that don't satisfy real imports + run: | + /tmp/venv/bin/python -c "from molecule_runtime.main import main_sync; print('runtime imports OK')"