Skip to content

fix(turbo): declare build outputs so cache hits restore dist/ - #2870

Open
im10furry wants to merge 1 commit into
openapi-ts:mainfrom
im10furry:fix/turbo-cache-restore-outputs
Open

fix(turbo): declare build outputs so cache hits restore dist/#2870
im10furry wants to merge 1 commit into
openapi-ts:mainfrom
im10furry:fix/turbo-cache-restore-outputs

Conversation

@im10furry

Copy link
Copy Markdown

Changes

turbo.json never declared outputs for any task, so Turborepo had no idea which files a task produces. A cache hit therefore replays the task's logs and reports success without writing dist/:

$ rm -rf packages/openapi-typescript-helpers/dist
$ npx turbo run build --filter=openapi-typescript-helpers
openapi-typescript-helpers:build: cache miss, executing a2386593374fa018

$ rm -rf packages/openapi-typescript-helpers/dist
$ npx turbo run build --filter=openapi-typescript-helpers
openapi-typescript-helpers:build: cache hit, replaying logs a2386593374fa018   # reports success
$ ls packages/openapi-typescript-helpers/dist
ls: No such file or directory                                                  # ...but produced nothing

That is a false green: turbo run build can succeed with no artifacts on disk, so anything that consumes a package fails or silently reads stale output. The clearest case is openapi-react-query, whose test script shells out to the openapi-typescript CLI:

$ cd packages/openapi-react-query && pnpm run test
> openapi-typescript test/fixtures/api.yaml -o test/fixtures/api.d.ts
Error [ERR_MODULE_NOT_FOUND]: Cannot find module
  '.../packages/openapi-typescript/dist/index.mjs' imported from '.../openapi-typescript/bin/cli.js'

Reproduction

  1. npx turbo run build --filter=openapi-react-query — populates the cache
  2. delete every packages/*/dist
  3. npx turbo run build --filter=openapi-react-query — cache hit, reports success
  4. cd packages/openapi-react-query && pnpm run test

On main, step 4 exits 1 with the ERR_MODULE_NOT_FOUND above. With this PR it exits 0, with 37 tests passing. I checked both directions — removing the new line reproduces the failure again.

Fix

Declare "outputs": ["dist/**"] on the build task so Turbo caches and restores the artifacts. Every package's build writes to dist/.

How to Review

  • One line plus a comment in turbo.json; nothing else changes.
  • Declaring outputs changes a task's hash, so the first run after this lands rebuilds everything once. After that, cache hits restore dist/ as they should.
  • No effect on CI as it stands today, since the workflow doesn't persist .turbo/cache. It matters for local turbo usage, and it's a prerequisite for caching Turborepo output in CI.
  • I found this while trying to add that CI caching in ci: stop the test-e2e job from hanging for 6 hours #2869. It looked like a large speedup (>>> FULL TURBO, 7/7 cached, 93ms), but that was only because nothing ran; the moment I forced the tests to execute, the missing artifacts surfaced on three platforms. I've kept ci: stop the test-e2e job from hanging for 6 hours #2869 to the e2e fix only and left the caching out.

For what it's worth, my first guess was wrong: I assumed the task graph was missing a cross-package ^build edge. It isn't — the graph is correct (openapi-react-query#test → openapi-react-query#build → openapi-typescript#build), and the missing outputs is the whole cause.

Checklist

  • Unit tests updated — not applicable, build configuration only
  • docs/ updated (if necessary) — not applicable
  • pnpm run update:examples run (only applicable for openapi-typescript) — not applicable

No changeset: turbo.json is build orchestration and is not published.

Without an outputs declaration Turborepo has no idea which files the
build task produces, so a cache hit replays the logs and reports success
while writing nothing:

  $ rm -rf packages/openapi-typescript-helpers/dist
  $ npx turbo run build --filter=openapi-typescript-helpers
  openapi-typescript-helpers:build: cache hit, replaying logs a23865...
  $ ls packages/openapi-typescript-helpers/dist
  ls: No such file or directory

Anything that consumes the package then fails on the missing artifacts.
openapi-react-query's test script shells out to the openapi-typescript
CLI and dies with ERR_MODULE_NOT_FOUND for dist/index.mjs; with this
change the same sequence exits 0 with 37 tests passing.

Declaring outputs also makes it safe to persist .turbo/cache in CI,
which does not currently work for this reason.
@im10furry
im10furry requested a review from a team as a code owner September 11, 2026 09:18
@im10furry
im10furry requested a review from drwpow September 11, 2026 09:18
@netlify

netlify Bot commented Sep 11, 2026

Copy link
Copy Markdown

👷 Deploy request for openapi-ts pending review.

Visit the deploys page to approve it

Name Link
🔨 Latest commit 22c4f21

@changeset-bot

changeset-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 22c4f21

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@im10furry

Copy link
Copy Markdown
Author

Note on the pending test-e2e. This branch is based on current main, so its e2e job hits the repo-wide hang in playwright install --with-deps (6-hour job limit on every run since 2026-08-24). That's unrelated to this change — two 1-line config edits can't affect it.

#2869 moves that job into the official Playwright container and is green in 57s. Like #2868, this PR doesn't touch .github/workflows/ci.yml, so once #2869 lands the fixed workflow applies here and test-e2e will go green without any change to this diff.

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