From 71d9064642dea661e598851c0799c03db5c00a0b Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Sun, 18 Oct 2026 12:25:45 +0100 Subject: [PATCH] ci: drop install and cache work the CI tasks never use The CI jobs' cost is dominated by setup, not the tasks themselves, and three pieces of that setup buy nothing: The build jobs persisted and restored the whole dist tree as their Turbo cache entry. Moving that entry through the runner cache costs more than the build it would skip, a restored entry was routinely a miss anyway (the PR's own source change is what invalidated it), and every such write evicts pnpm-store entries the other tasks actually restore from. The build jobs now run uncached through Turbo in CI; local `turbo run _build` keeps its cache. `pnpm install` in CI now passes --ignore-scripts: the package's prepare script runs husky and an esbuild bundle of the CLI, and no CI task consumes that bundle (lint, typecheck, test and knip read the sources; the build and publish jobs bundle explicitly). Runners have no use for the git hooks. The audit job installs nothing: pnpm audit reads the lockfile alone. The composite action gains `install` and `cache-turbo` inputs, both defaulting to the previous behaviour, so only the jobs named above change what they do. --- .github/actions/setup-and-run/action.yml | 13 ++++++++++++- .github/workflows/ci.yml | 8 ++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/.github/actions/setup-and-run/action.yml b/.github/actions/setup-and-run/action.yml index b5c66fdb..8ea34986 100644 --- a/.github/actions/setup-and-run/action.yml +++ b/.github/actions/setup-and-run/action.yml @@ -12,6 +12,14 @@ inputs: description: GitHub token for commands that need it. required: false default: "" + install: + description: Whether to install dependencies from the lockfile. False for tasks that read only the lockfile or the sources (pnpm audit needs neither node_modules nor a bundle), skipping the install and its store-cache save. + required: false + default: "true" + cache-turbo: + description: Whether to persist and restore Turbo's task cache directory. False for the build jobs, whose cache entry is the whole dist tree; moving that entry costs more than the build it would skip, and every build-job cache write evicts pnpm-store entries the other tasks depend on. + required: false + default: "true" runs: using: composite @@ -23,11 +31,14 @@ runs: node-version-file: .tool-versions cache: pnpm - - run: pnpm install --frozen-lockfile + # --ignore-scripts skips the package's own prepare script (husky plus an esbuild bundle of the CLI). No CI task consumes that bundle: lint, typecheck, test and knip all read the sources, and the build and publish jobs bundle explicitly before anything runs the result. Husky hooks are meaningless on a runner. + - run: pnpm install --frozen-lockfile --ignore-scripts + if: inputs.install == 'true' shell: bash # Turbo owns the actual cache-or-run decision per task (via each task's declared inputs/outputs in turbo.json) -- this step only needs to persist its local cache directory across runs. Keyed per-task because lint/typecheck/test/audit/knip/build are separate parallel jobs in the same workflow run, all writing to this same path. runner.arch is included alongside runner.os deliberately: build-linux-x64 (ubuntu-latest) and build-linux-arm64 (ubuntu-24.04-arm) both report runner.os as "Linux", and the _build task's turbo.json inputs are pure source content with no architecture marker, so without runner.arch here the two jobs would share one Turbo cache namespace -- confirmed to actually happen (a stale cross-architecture binary served from cache broke the Linux x64 release, caught only because the verify jobs actually execute the installed binary rather than just checking install exit codes). github.run_id makes the primary key unique to this run, so actions/cache always saves a fresh entry at the end -- without it, the primary key would stay identical across every run on the same branch/lockfile, and actions/cache treats a key as immutable: once written, a later run restores it but silently skips re-saving, so nothing computed after the very first run under that key would ever actually persist. restore-keys still falls back by prefix (ignoring run_id) to find the most recent prior entry to seed from. - uses: actions/cache@v5 + if: inputs.cache-turbo == 'true' with: path: .turbo key: turbo-${{ runner.os }}-${{ runner.arch }}-${{ inputs.task }}-${{ github.ref_name }}-${{ hashFiles('pnpm-lock.yaml') }}-${{ github.run_id }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 11ff5315..5e1473bc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -75,10 +75,12 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 + # install: false because pnpm audit reads the lockfile alone; an install here would be pure overhead plus a store-cache entry saved for a job that never runs anything else. - uses: ./.github/actions/setup-and-run with: task: audit command: pnpm audit --audit-level moderate + install: false # Unused-file/export/dependency detection, scoped to a single-package CLI (not exadex's Next.js monorepo shape) — src/cli.ts is the only declared entry; every resolve/* submodule is imported directly by its own consumers now (no facade), and everything else knip flags as unused is either genuinely dead or a same-file-only export that should never have carried the `export` keyword in the first place. knip: @@ -153,6 +155,7 @@ jobs: with: task: build command: pnpm build + cache-turbo: false - run: mv dist/agent-shim-sea dist/agent-shim-macos-arm64 - run: shasum -a 256 dist/agent-shim-macos-arm64 | awk '{print $1}' > dist/agent-shim-macos-arm64.sha256 @@ -183,6 +186,7 @@ jobs: with: task: build command: pnpm build + cache-turbo: false - run: mv dist/agent-shim-sea dist/agent-shim-macos-x64-unverified - run: shasum -a 256 dist/agent-shim-macos-x64-unverified | awk '{print $1}' > dist/agent-shim-macos-x64-unverified.sha256 @@ -209,6 +213,7 @@ jobs: with: task: build command: pnpm build + cache-turbo: false - run: mv dist/agent-shim-sea dist/agent-shim-linux-x64 - run: shasum -a 256 dist/agent-shim-linux-x64 | awk '{print $1}' > dist/agent-shim-linux-x64.sha256 @@ -234,6 +239,7 @@ jobs: with: task: build command: pnpm build + cache-turbo: false - run: mv dist/agent-shim-sea dist/agent-shim-linux-arm64 - run: shasum -a 256 dist/agent-shim-linux-arm64 | awk '{print $1}' > dist/agent-shim-linux-arm64.sha256 @@ -260,6 +266,7 @@ jobs: with: task: build command: pnpm build + cache-turbo: false - name: Package archive shell: pwsh @@ -292,6 +299,7 @@ jobs: with: task: build command: pnpm build + cache-turbo: false - name: Package archive shell: pwsh