FFFF CI: macOS libkrun cache key omits the patch files, so patched builds are served stale · Issue #902 · gominimal/minimal · GitHub
[go: up one dir, main page]

Skip to content

CI: macOS libkrun cache key omits the patch files, so patched builds are served stale #902

Closed

Description

@norrietaylor

Summary

The macOS libkrun cache key hashes the build script but not the patches it applies, so changing a patch's contents does not invalidate the cache. CI then serves a dylib built from the previous patches, and the lane goes green having tested code the PR does not ship.

.github/actions/setup-libkrun-macos/action.yml:28:

script_hash="$(shasum -a 256 scripts/build-libkrun-macos.sh | cut -d' ' -f1)"
...
echo "prefix=$HOME/.cache/minimal-ci/libkrun/$commit-${script_hash:0:12}"

The surrounding comment asserts "The prefix embeds BOTH build inputs (pinned commit + build-script hash)". That was true until gominimal/minimal#884 added a patch-application step, which introduces a third build input the key does not cover.

Observed, not hypothetical

All three commits on #884 share script hash 516adfacdef8:

Commit Patches carried macOS build
7258ee5d credit floor (later refuted) cache miss — logged applying 0001-vsock-don-t-shrink-rx-packets-to-the-last-bytes-of-peer-credit.patch
5aa0de54 credit floor cache hit
5dc8cf01 IRQ fix + fill-loop (what the PR ships) cache hit — same stale dylib

The unit job bakes that dylib into mac-testbed, which the self-hosted e2e job consumes. So the macOS unit and e2e lanes on the current head ran against a libkrun built from a patch the PR deliberately deleted.

Severity

Bounded, but it destroys the signal where it matters most. The poisoned entry is PR-branch-scoped; main's script hash differs, so post-merge main and release rebuild correctly. The shipped artifact is not wrong — but any macOS result on a PR that changes patch contents without touching the build script is meaningless, and reads as green.

This is the CI lane that exists specifically to exercise libkrun on HVF, and patches to libkrun are exactly what it now cannot see.

Note the paths filter is fine — vendor/libkrun/** does trigger ci-macos.yml. Only the cache key is wrong, so the lane runs and reports on stale inputs rather than skipping.

Suggested fix

Fold the patch contents into the key:

build_hash="$( { shasum -a 256 scripts/build-libkrun-macos.sh; \
    find vendor/libkrun/patches -name '*.patch' -type f -print0 | sort -z | xargs -0 -r shasum -a 256; \
  } | shasum -a 256 | cut -d' ' -f1)"

This cannot be fixed from scripts/. On a cache hit the action never invokes the build script at all, so no script-side change can invalidate a stale entry — it has to be the key itself, inside CODEOWNER-gated .github/.

Immediate workaround for #884

Drop that branch's libkrun cache entry on the mini (or make any byte change to scripts/build-libkrun-macos.sh) and re-run the macOS lane, to get an honest signal before merging.

Activity

  1. added
    kind:bugSomething is not working. Applied by the inbox-route classifier.
    priority:should-haveShould be done. Applied by the inbox-route classifier or a human.
    on Jul 22, 2026
  2. gominimal-aw-bot commented on Jul 22, 2026

    @gominimal-aw-bot
    Contributor

    Routing triage — #902

    Kind: bug · Route: patch · Confidence: 0.92
    Target: gominimal/minimal — the composite action named in the issue (.github/actions/setup-libkrun-macos/action.yml) is confirmed present in this repository; the defect is visible at the script_hash= and echo prefix= lines.

    Evidence

    • File confirmed: .github/actions/setup-libkrun-macos/action.yml exists in gominimal/minimal. The Resolve libkrun pin step (action.yml:28) computes script_hash only from scripts/build-libkrun-macos.sh and embeds it as $commit-${script_hash:0:12} in both the prefix output and the actions/cache key:. Patch file contents are absent from the key.
    • Similar issues: No inbox duplicates found (only CI: macOS libkrun cache key omits the patch files, so patched builds are served stale #902 itself matched the libkrun/cache-key search). Targeted search for setup-libkrun-macos and libkrun cache patch in gominimal/minimal returned no prior issue tracking this specific defect. No routing markers (inbox-route:ledger, Routing-Key: inbox-route/) for this bug found in minimal.
    • Distillery (informed by gominimal/minimal#pr-694, gominimal/minimal#pr-703): PR ci(macos): consolidate libkrun on our own pinned source build #694 (ci(macos): consolidate libkrun on our own pinned source build) created the setup-libkrun-macos action and lives in the minimal Distillery project; PR ci: cache discipline, slim CI debug info, and a --locked sweep #703 (ci: cache discipline) confirms cache key work belongs there. No prior Distillery entry for this patch-omission defect.
    • Precedents (informed by routing-outcome entries): Eight eligible routing-outcome entries (all authored by inbox-route-retro, all tagged routing-outcome) were found. All route CI and build-plane bugs to gominimal/minimal; none show a correction away from minimal for this class of issue. No reordering of preference is indicated.
    • Manifest: gominimal/minimal is route: allow; keywords include build, cache, ci (via purpose); sdd: true; default_ref: main.
    • Patch scope: Fix touches one file — both the echo "prefix=..." output line and the actions/cache key: line in action.yml must fold vendor/libkrun/patches/*.patch content into the hash. max_patch_files: 5; 1 file needed. A fix in scripts/build-libkrun-macos.sh is insufficient (the script is not invoked on a cache hit).

    [inbox-route:decision]

    {"schema":"inbox-route/v1","issue":340,"issue_node_id":"I_kwDOSUhdos8AAAABJsl7Jw","dry_run":false,"kind":"bug","route":"patch","confidence":0.92,"targets":[{"repo":"gominimal/minimal","reason":"action.yml confirmed present in gominimal/minimal; bug visible at action.yml:28 where script_hash excludes patch file contents from the cache key"}],"labels":["kind:bug","priority:should-have"],"patch":{"target_ref":"main","brief":"The 'Resolve libkrun pin' step hashes only scripts/build-libkrun-macos.sh into script_hash (action.yml:28) and embeds it in both the prefix output and the actions/cache key:. Since PR #884 added a patch-application step, patch file contents are now a third build input that the key does not cover. Evidence: action.yml confirms commit + script_hash[:12] is the full key; the three-commit table in the issue shows identical script_hash across commits with different patch sets, yielding a cache hit against a deleted patch. The fix folds vendor/libkrun/patches/*.patch contents into a combined digest replacing script_hash in both the echo prefix= line and the actions/cache key: line. Only action.yml needs editing; the build script is not involved (it is not invoked on a cache hit).","files":[".github/actions/setup-libkrun-macos/action.yml"]},"work_issue":{"title":"bug: CI macOS libkrun cache key missing patch file contents","body":"## Summary\n\nThe setup-libkrun-macos composite action caches the built libkrun dylib under a key that hashes only the build script, not the patch files it applies. After PR #884 added a patch-application step, patch file contents became a third build input not covered by the key. CI restores a stale dylib when patches change without a corresponding build-script change, making the macOS lane result meaningless for those PRs.\n\n## Expected behavior\n\nChanging any file under `vendor/libkrun/patches/` invalidates the macOS libkrun cache and triggers a fresh build.\n\n## Actual behavior\n\nThe `Resolve libkrun pin` step (`action.yml:28`) computes `script_hash` from `scripts/build-libkrun-macos.sh` only and uses it as the sole non-commit component of both the `prefix` output and the `actions/cache key:`. A patch change without a build-script change yields an identical hash, so the cache hit restores the previous dylib. The `unit` job bakes that dylib into `mac-testbed`; `e2e` consumes it — both lanes report results against code the PR does not ship.\n\n## Reproduction\n\nObserved on gominimal/minimal#884: all three commits share script hash `516adfacdef8`. The third commit changed the active patch set without touching the build script and received a cache hit, so unit and e2e ran against a dylib built from a patch the PR deliberately deleted.\n\n## Scope notes\n\nFix is isolated to `.github/actions/setup-libkrun-macos/action.yml`. Both the `echo \"prefix=...\"` line and the `actions/cache key:` line must incorporate a hash of `vendor/libkrun/patches/*.patch` content (e.g., sorted `shasum` of all patch files folded into the combined digest). A fix inside `scripts/build-libkrun-macos.sh` is insufficient — the script is not invoked on a cache hit.\n\nLaunch: a maintainer comments `/spec` on the work issue to start the SDD pipeline.\n\n---\n<!-- SDD command vocabulary. Do not edit this footer. -->\n\nThis issue is the tracking issue for this work. A maintainer with write\naccess starts the SDD pipeline by commenting `/spec` on this issue or by\nflipping the `sdd:spec` label.\n\nSteer the pipeline with these comment commands. Each is gated to commenters\nwith write access to the repository.\n\n| Command | Where | Effect |\n|---|---|---|\n| `/spec` | this tracking issue | re-run `sdd-spec` to draft or revise the spec |\n| `/fastpath` | this tracking issue | confirm a single-session change; `sdd-spec` produces a stub spec PR and an execution plan comment in one run (ADR 0012) |\n| `/triage` | this tracking issue, after the spec PR is merged | start `sdd-triage` phase A (architecture) |\n| `/approve` | this tracking issue | full path: confirm the proposed plan so `sdd-triage` creates the Unit and task sub-issues. Fast path: dispatch the execution plan against `sdd-execute-{tier}` |\n| `/dispatch` | this tracking issue (full path only) | arm the cascade across the task tree |\n| `/revise <note>` | a spec, architecture, or implementation PR, or this tracking issue | re-run the owning agent with the note as an added instruction |\n| `/execute` | a task sub-issue | run `sdd-execute` for that task ahead of the schedule |\n\nMerging the spec PR advances to the architecture phase; merging the\narchitecture PR advances to a plan-comment phase, where `sdd-triage` posts\nthe proposed plan as one comment on this tracking issue. When an agent needs\na human decision it applies the `needs-human` label and posts one comment;\nclear the label once you have answered and the agent resumes.\n"},"related":[],"rationale":"The issue names .github/actions/setup-libkrun-macos/action.yml:28 as the defect site. Reading that file confirmed the bug: only scripts/build-libkrun-macos.sh is hashed into script_hash; the cache key is commit + script_hash[:12] — patch file contents are absent. Distillery shows PR #694 (ci(macos): consolidate libkrun on our own pinned source build) created this action in gominimal/minimal, and PR #703 (ci: cache discipline) confirms cache work lives there. No inbox duplicates: only gominimal/minimal#902 itself matched the libkrun-cache-key search. Precedent pass returned 8 eligible routing-outcome entries (all by inbox-route-retro); all route to gominimal/minimal; none show corrections away from minimal for CI-type issues. Confidence 0.92: direct evidence — exact file named in the issue exists in gominimal/minimal with the defect visible, fix touches one file within max_patch_files."}

    Generated by inbox-route for issue #902 · ◷

  3. gominimal-aw-bot commented on Jul 22, 2026

    @gominimal-aw-bot
    Contributor

    [inbox-route:ledger]
    Routed from gominimal/inbox#340 by inbox-route (https://github.com/gominimal/inbox/actions/runs/29893278378)
    Routing-Key: inbox-route/I_kwDOSUhdos8AAAABJsl7Jw
    Route: patch
    Patch-Dispatched: https://github.com/gominimal/inbox/actions/runs/29893278378

  4. transferred this issue fromon Jul 22, 2026
  5. gominimal-aw-bot commented on Jul 22, 2026

    @gominimal-aw-bot
    Contributor

    [inbox-patch:handoff]
    inbox-patch did not produce a verified fix PR for this issue — the agent run finished without creating one (agent result: success).

    Run: https://github.com/gominimal/inbox/actions/runs/29893740351

    Manual retry:

    gh workflow run inbox-patch.yml -R gominimal/inbox -f "target-repo=gominimal/minimal" -f "target-ref=main" -f "issue=902" -f "language=rust" -f "distillery-project=minimal" -f "decision-url=https://github.com/gominimal/inbox/issues/340#issuecomment-5042176936"
    
  6. added
    needs-humanAn agent handed off; a human must act, then clear this label. Set by defer and handoffs.
    on Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind:bugSomething is not working. Applied by the inbox-route classifier.needs-humanAn agent handed off; a human must act, then clear this label. Set by defer and handoffs.priority:should-haveShould be done. Applied by the inbox-route classifier or a human.routed

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      0