The Wizard CI is really slow. It doesn't have to be.
Pulling main, building MCP, and set up work takes as long as the actual wizard runs themselves.
We can greatly improve CI turn around time by just reusing build artifacts and caching them.
Plan: cache + reuse build artifacts in Wizard CI
Root cause
wizard-ci.yml fans out one matrix job per app (~90 apps, max-parallel: 10). Every matrix job independently:
- Clones +
pnpm install + pnpm build:ci the wizard CLI
- Clones +
npm install + npm run build context-mill
- Clones the entire PostHog monorepo,
pnpm install --frozen-lockfile, and builds MCP
That's the same three heavy builds repeated ~90×, gated behind a 10-wide pool. The PostHog monorepo install alone dominates wall-clock and, as noted above, rivals the actual wizard runs. None of it is cached, even though the output is fully determined by each repo's commit SHA.
Approach
Build each dependency once per run, key the result on the dependency's resolved commit SHA, and let every matrix job restore it. Unchanged refs across runs (e.g. weekly scheduled main/master) hit the cache and skip the build entirely.
-
New composite action .github/actions/setup-wizard-deps — single home for the clone/install/build logic (no duplication between the warm-up job and the matrix fallback). For each dep it:
- resolves the ref → commit SHA via
git ls-remote (so main moving busts the cache),
actions/cache/restore keyed on <dep>-<os>-<sha>,
- clones + builds only on a cache miss,
- optionally
actions/cache/save (warm-up job only),
- exports
WIZARD_PATH / CONTEXT_MILL_PATH / MCP_PATH.
-
New setup-deps job (needs: discover) — runs the composite action once with save_cache: true to warm the cache before fan-out, so the 10 parallel jobs don't all cold-build and race.
-
wizard-ci matrix job — replace the three inline "Clone and build" steps with the composite action (save_cache: false); add setup-deps to needs. The action still builds on a miss, so the job self-heals if the cache is cold/evicted — no correctness risk.
Notes / trade-offs
- Matrix
if stays always() && discover succeeded, so a failed setup-deps just means a cold cache + fallback build, not a blocked run.
- Cache keys include
runner.os. The lone swift/ app runs on macos-latest and won't share the Linux warm-up cache — it falls back to building (one app, not worth a second warm-up job; flagged as future work).
- Within a run: ~90 redundant builds → 1. Across runs: unchanged refs skip the build outright.
The Wizard CI is really slow. It doesn't have to be.
Pulling main, building MCP, and set up work takes as long as the actual wizard runs themselves.
We can greatly improve CI turn around time by just reusing build artifacts and caching them.
Plan: cache + reuse build artifacts in Wizard CI
Root cause
wizard-ci.ymlfans out one matrix job per app (~90 apps,max-parallel: 10). Every matrix job independently:pnpm install+pnpm build:cithe wizard CLInpm install+npm run buildcontext-millpnpm install --frozen-lockfile, and builds MCPThat's the same three heavy builds repeated ~90×, gated behind a 10-wide pool. The PostHog monorepo install alone dominates wall-clock and, as noted above, rivals the actual wizard runs. None of it is cached, even though the output is fully determined by each repo's commit SHA.
Approach
Build each dependency once per run, key the result on the dependency's resolved commit SHA, and let every matrix job restore it. Unchanged refs across runs (e.g. weekly scheduled
main/master) hit the cache and skip the build entirely.New composite action
.github/actions/setup-wizard-deps— single home for the clone/install/build logic (no duplication between the warm-up job and the matrix fallback). For each dep it:git ls-remote(somainmoving busts the cache),actions/cache/restorekeyed on<dep>-<os>-<sha>,actions/cache/save(warm-up job only),WIZARD_PATH/CONTEXT_MILL_PATH/MCP_PATH.New
setup-depsjob (needs: discover) — runs the composite action once withsave_cache: trueto warm the cache before fan-out, so the 10 parallel jobs don't all cold-build and race.wizard-cimatrix job — replace the three inline "Clone and build" steps with the composite action (save_cache: false); addsetup-depstoneeds. The action still builds on a miss, so the job self-heals if the cache is cold/evicted — no correctness risk.Notes / trade-offs
ifstaysalways() && discover succeeded, so a failedsetup-depsjust means a cold cache + fallback build, not a blocked run.runner.os. The loneswift/app runs onmacos-latestand won't share the Linux warm-up cache — it falls back to building (one app, not worth a second warm-up job; flagged as future work).