Skip to content

ci: stop the test cache self-invalidating, and drop duplicate PR runs - #30

Merged
ackness merged 1 commit into
mainfrom
ci/turbo-cache-hashing
Jul 25, 2026
Merged

ci: stop the test cache self-invalidating, and drop duplicate PR runs#30
ackness merged 1 commit into
mainfrom
ci/turbo-cache-hashing

Conversation

@ackness

@ackness ackness commented Jul 25, 2026

Copy link
Copy Markdown
Owner

CI-only change. No version bump, no release — docs/CHANGELOG.md and the version badges are untouched.

The problem

turbo run test never cached. Two consecutive runs with no edits in between:

Cached:    2 cached, 43 total
  Time:    49s

test listed $TURBO_ROOT$/plugins/** as an input, which pulled each plugin's run artefacts into the hash. Diffing two run summaries:

### DIFF in inputs
  ../story-guard/node_modules/.vite/vitest/…/results.json:  94b73c9e → 8823c1d7
  ../char-creator/.turbo/turbo-test.log:                    0d437d09 → 4866ff05
  …41 entries, every plugin package
environmentVariables:        identical
hashOfExternalDependencies:  identical
dependencies:                identical

Those are vitest's result cache and turbo's own task log. Running the suite rewrites them, so the next run hashes differently and all 43 packages miss — running tests was the thing invalidating the test cache.

They are gitignored, but explicit input globs don't consult gitignore the way $TURBO_DEFAULT$ does. That's why git status stayed clean while the hash moved, and why this was invisible.

The fix

Negative globs (!.../node_modules/**) don't work here — inputs resolve per package and these are cross-package paths; verified, still 21/43. So the directory glob is replaced with a whitelist of the source shapes a plugin actually has: markdown, entry .js, package.json, and the eight content directories (hooks lib runtimes schemas server tests tools ui). Artefact directories can no longer match.

Verification

pnpm test ×2, no edits between:   2/43 cached, 49s  →  43/43 cached, 0.3s (FULL TURBO)
edit plugins/narrator/PLUGIN.md:  2/43 cached          ← correctly invalidated
revert it:                        43/43 cached
turbo run lint  ×2:               21/21 FULL TURBO
turbo run build ×2:               4/4   FULL TURBO

Dependency semantics are unchanged — editing any plugin source still invalidates every dependent package's test. The full suite passed on the run that actually executed (43 successful, 0 failed). actionlint and prettier pass.

Also here

  • CI caches .turbo/cache. It ran cold every time, so none of the above would have reached CI otherwise.
  • CI push trigger scoped to main. A *-dev branch with an open PR ran the same commit twice — the PR ref and the branch ref hash to different concurrency groups, so neither cancelled the other. Seen on the v0.0.21 release: runs 30162296595 (push) and 30162298111 (pull_request), same commit, ~5.5 min each. The PR run covers dev branches; the push trigger stays as the post-merge guard on main.
  • macOS release job gets the Electron binary cache the Windows job already had.

Expected effect

Cold on the first run either way. From the second run on, a change touching one package replays the rest from cache instead of re-running them — the 155s Test step and 134s Build step should collapse to whatever actually changed.


中文摘要:纯 CI 改动,不发版。test 的 inputs 把 plugins/** 整个目录纳入哈希,连带 vitest 的 results.json 和 turbo 自己写的 turbo-test.log 也算了进去 —— 跑测试这个动作本身就让测试缓存失效,所以一直是 2/43。改成源文件白名单后 43/43 全命中(49s → 0.3s),且改插件源码仍能正确失效。另外给 CI 加了 .turbo/cache 缓存、把 push 触发收到只剩 main(消除 PR 双跑),并给 release 的 macOS job 补上 Windows job 早就有的 Electron 缓存。

`test` listed `$TURBO_ROOT$/plugins/**` as an input, which pulled each
plugin's *run artefacts* into the hash — vitest's
`node_modules/.vite/vitest/*/results.json` and turbo's own
`.turbo/turbo-test.log`. Running the suite rewrote those files, so the next
run hashed differently and all 43 packages missed. Running tests was what
invalidated the test cache; it never settled above 2/43. The files are
gitignored, but explicit input globs don't consult gitignore the way
`$TURBO_DEFAULT$` does, so `git status` stayed clean while the hash moved.

Negative globs don't help here (they resolve per-package and the paths are
cross-package), so the directory glob is replaced with a whitelist of the
source shapes a plugin actually has — markdown, entry `.js`, package.json,
and the eight content directories. Artefact directories can no longer match.
Dependency semantics are unchanged: editing any plugin source still
invalidates every dependent package's test.

    pnpm test, twice, no edits between:  2/43 cached, 49s  →  43/43, 0.3s
    editing plugins/narrator/PLUGIN.md:  2/43 cached (correctly invalidated)

CI now caches `.turbo/cache` so it can benefit from that at all — it was
running cold every time.

Also scope the CI push trigger to main. A `*-dev` branch with an open PR ran
the same commit twice, because the PR ref and the branch ref hash to
different concurrency groups and neither cancels the other.

The release workflow's macOS job gets the Electron binary cache the Windows
job already had.
@ackness
ackness merged commit 5921db3 into main Jul 25, 2026
1 check passed
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