Skip to content

ci(actions): vendor runs-on/cache to stop per-job codeload re-download - #1126

Closed
Rasbandit wants to merge 1 commit into
mainfrom
ci/vendor-runs-on-cache
Closed

ci(actions): vendor runs-on/cache to stop per-job codeload re-download#1126
Rasbandit wants to merge 1 commit into
mainfrom
ci/vendor-runs-on-cache

Conversation

@Rasbandit

Copy link
Copy Markdown
Member

Parked from a worktree cleanup — no PR, local-only branch. Draft so it's recoverable; decide later.

Vendors the runs-on/cache action into .github/actions/runs-on-cache so CI jobs stop re-downloading it from codeload, plus the verify.yml wiring.

Audit notes:

  • Absent from main.
  • Large: ~362,900 added lines, almost entirely committed dist/ JavaScript. That's the main reason it was worth preserving rather than deleting — it's tedious to reconstruct — but also the main reason to think before merging.

🤖 Parked by Claude Code

Ephemeral self-hosted runners re-download every action from codeload.github.com
each job. runs-on/cache (a fork of actions/cache with the AWS S3 SDK bundled,
~18MB dist) intermittently timed out downloading (100s x3), making the "Set up
job" phase take ~60s or fail outright — hitting prebuild-mix, unit-tests, lint,
migration-gates, e2e-browser.

Vendor it locally at v5.0.7 (SHA 88d9064) as ./.github/actions/runs-on-cache and
.../restore. A local (./) action is served straight from the checkout, no fetch.
All 13 verify.yml refs repointed; verified every using-job runs actions/checkout
first. Minimal vendor: only the entry points the workflow uses (cache main +
restore); dropped the unused save/ sub-action and dist/save-only. Behavior is
identical (same inputs, same MinIO/S3 backend env). ~13MB.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VK9qUcRtS3tiW9wNhw83y7
@Rasbandit

Copy link
Copy Markdown
Member Author

Closing after measuring the problem this solves. The cost is ~0.6s of critical-path time per CI run — not worth 362,900 committed lines.

Measurement

Parsed the runner logs of a real full run (30228376076), timing every Download action repository 'runs-on/cache@...' against the next log line:

Distinct downloads per run 5 (one per job that uses it, not per call site)
Aggregate wall-clock 1.94s
Mean per download 0.39s
Critical-path cost ~0.61s (the 5 jobs run in parallel, so the slowest one is the real cost)

Per job: migration gates 0.61s, lint 0.48s, unit-tests 0.35s, prebuild-mix 0.30s, e2e-browser 0.19s.

The ~18 uses: call sites in verify.yml are misleading — the runner downloads an action once per job and reuses it across steps, so the fan-out never materialized.

Why that changes the verdict

Vendoring buys back 0.6s per run and costs:

  • 362,900 lines of committed third-party dist/ JavaScript, paid by every clone and checkout forever
  • No Dependabot coverage — security updates become a manual re-vendor
  • An unreviewable diff, permanently

That trade is upside-down.

If the download ever does become a real cost

Fix it at the runner layer, not in the repo — cache or mirror the action tarball on the self-hosted runner VMs (docs/context/runner-vm-setup.md). That fixes every action at once, including actions/checkout (12 downloads/run) and actions/create-github-app-token (10/run), which are both downloaded more often than runs-on/cache is.

Branch ci/vendor-runs-on-cache is left in place — nothing is lost if this needs revisiting.

@Rasbandit Rasbandit closed this Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant