fix(canary): make cross-environment cache proofs environment-invariant - #95
Conversation
The hosted-to-self and self-to-hosted cache steps keyed their payloads
under ${{ runner.temp }}, but a cache entry's version is a hash of the
path input plus the compression tool, so the hosted save
(/home/runner/work/_temp/..., zstd) could never be restored on a fleet
worker (different temp path, gzip-only image). Proven live on the first
laptop acceptance dispatch: run 29371617183 saved version fec98c1e...,
reproduced exactly as sha256('/home/runner/work/_temp/hosted-to-self-
cache|zstd-without-long|1.0'), and the parity job missed with
fail-on-cache-miss.
Use a workspace-relative path in all four cache steps; the worker-image
side (zstd parity) ships separately in melodic-software/ci-runner.
Part of melodic-software/github-iac#88.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D5wqdo4adEZmWgjpY9ZjVx
|
Claude finished @kyle-sexton's task in 1m 56s —— View job Code Review
SummaryThe root cause diagnosis and fix are both correct. The change is minimal and well-scoped. CorrectnessPath fix — correct. All 8 path references updated consistently. The four create/save pairs and four restore/verify pairs across Remaining
One dependency to land togetherThe PR body correctly notes the compression fix ( CLAUDE.md complianceAll VerdictLooks good to merge. The fix is correct, complete for its stated scope, and the companion compression change in ci-runner is the remaining gate. No blocking issues. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0c31091b4e
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
## What Adds `zstd` to the worker image's compatibility layer. ## Why `actions/cache` versions every entry as `sha256(pathInput | compressionMethod | salt)` and selects zstd whenever the binary is present. GitHub-hosted runners ship zstd; this image was gzip-only (verified: `docker run --entrypoint bash ghcr.io/melodic-software/ci-runner@be222b0e -c 'command -v zstd'` → absent). Result: hosted↔self-hosted cache exchange can never hit, which failed the first-ever governed laptop acceptance dispatch ([ci-runner-canary run 29371617183](https://github.com/melodic-software/ci-runner-canary/actions/runs/29371617183)) at the `fail-on-cache-miss` gate. Path-side fix (workspace-relative cache paths in the canary contract) is melodic-software/ci-workflows#95; both are required for the melodic-software/github-iac#88 laptop gate. This is also the first instance of the fleet-image tool-parity class tracked for melodic-software/github-iac#89 (pipx precedent) — the broader parity inventory stays in that issue; this PR ships only what the acceptance gate needs. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01D5wqdo4adEZmWgjpY9ZjVx Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…contract Lockstep repin: #95 made the cross-environment cache proofs environment-invariant and #92 hardened the reusable execution, so the canonical callers pin the merged commit 9eb22ac carrying both. Part of melodic-software/github-iac#88. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01D5wqdo4adEZmWgjpY9ZjVx
…97) Lockstep repin after #95: template callers now pin the merged cache-invariant contract commit `4083c8d82bc4e7a79a9866544101bf8a5261fb50`. The seeded `ci-runner-canary` repo gets the matching repin via bootstrap re-run once this merges. Part of melodic-software/github-iac#88. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01D5wqdo4adEZmWgjpY9ZjVx Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
What
The canary contract's hosted↔self-hosted cache exchange used
${{ runner.temp }}paths. A cache entry's version issha256(pathInput | compressionMethod | salt)(actions/cache dist at the pinned SHA), so the exchange can never hit across environments:runner.tempto/home/runner/work/_temp; the fleet worker resolves differently.ghcr.io/melodic-software/ci-runner@be222b0e).Live proof (first-ever governed dispatch, run 29371617183): the hosted save produced cache version
fec98c1e…, reproduced byte-exactly assha256('/home/runner/work/_temp/hosted-to-self-cache|zstd-without-long|1.0'); the self-hosted restore missed withfail-on-cache-miss.Fix
Workspace-relative path (
.canary-cache/…) in all four cache steps + payload create/verify steps — identical version component in every environment. The compression half of the fix (zstd in the worker image) ships separately in melodic-software/ci-runner; both are required before the laptop gate can pass.Contract tests green (
node --test local-runner-canary.test.cjs), actionlint clean.Part of melodic-software/github-iac#88.
🤖 Generated with Claude Code
https://claude.ai/code/session_01D5wqdo4adEZmWgjpY9ZjVx