Skip to content

Stop hashing compiled output into pack:npm - #494

Merged
gtbuchanan merged 1 commit into
mainfrom
pack-npm-input-stability
Sep 16, 2026
Merged

gtbuchanan merged 1 commit into
mainfrom
pack-npm-input-stability

Conversation

@gtbuchanan

Copy link
Copy Markdown
Owner

Summary

pack:npm listed dist/source/**, minus the four files it writes itself, among its inputs. Turbo folds a dependency's task hash into its dependents, so the compile:ts and compile:skills edges already key pack:npm to the sources that produce what it packs. The glob was redundant for correctness and harmful for caching: it also keyed the task to whatever a prior run left on disk, so one source state hashed one way in a warm tree and another on a fresh checkout.

Dropping the glob and its negations leaves the dependency edges to do the keying.

Testing

pnpm check (44/44) and gtb verify both pass, but neither can show cache behavior. Measured by hand against turbo 2.10.12:

  • pack:npm is keyed to the previous run's compiled output #409's own experiment, appending a line to a compiled file under packages/eslint-plugin-yamllint/dist/source, previously moved pack:npm's hash. It now holds at f880a249f99f4a5b, and the hash is still non-empty, so turbo-run's dry-run install-skip keeps working.
  • In a minimal two-task repo, varying only the dependency's inputs moved the dependent's hash every time while the dependent's own inputs held. That propagation is what this change relies on.
  • In a scratch repo mirroring the compile/pack shape: a source edit still misses and packs the new content; reverting sources while newer output sits on disk still restores the correct tarball; and the key is identical whether the output directory exists or not.

Notes for reviewers

The premise of #409 was that the plain glob let pack:npm hit and restore a stale tarball. It doesn't, and neither failure mode it predicts reproduces, because the dependency hash covers both. The real cost was spurious misses, which is the opposite problem.

That matters for the fix chosen. #409 proposed mode: "dependencyOutputs" and was split out specifically to decide the CI trade-off that mode forces: it defers the hash until dependencies finish, turbo then reports an empty hash under --dry=json, and turbo-run would install on every build:ci, build, and test:e2e job. I confirmed that cost is real. Dropping the glob avoids it, so there is no trade-off left to accept.

The reasoning is recorded in the gtb-build-pipeline ownership reference so the glob doesn't return as an improvement.

Resolves: #409

Turbo folds a dependency's task hash into its dependents, so the
compile:ts and compile:skills edges already key pack:npm to the sources
that produce what it packs. Listing the output directory on top of that
also keyed it to whatever a prior run left on disk, so one source state
hashed one way in a warm tree and another on a fresh checkout, costing
cache hits and buying no correctness.

Keying off the dependencies' declared outputs instead, via
mode: "dependencyOutputs", defers the hash until those dependencies
finish. Turbo then reports an empty hash under --dry=json, which is what
turbo-run reads to decide whether CI can skip pnpm install. Dropping the
glob leaves that hash knowable.

Resolves: #409
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 16, 2026

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 095f10a1-d69f-4f43-bb33-07c248bb08d9

📥 Commits

Reviewing files that changed from the base of the PR and between 81e3957 and 1d3d235.

📒 Files selected for processing (7)
  • .changeset/pack-npm-input-stability.md
  • packages/cli/skills/gtb-build-pipeline/SKILL.md
  • packages/cli/skills/gtb-build-pipeline/references/dist-source-ownership.md
  • packages/cli/src/lib/turbo-config.ts
  • packages/cli/test/task-graph.test.ts
  • packages/cli/test/turbo-json-dist-source.test.ts
  • turbo.json
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • gtbuchanan/tooling (manual)
💤 Files with no reviewable changes (1)
  • turbo.json

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.

📜 Recent review details
🧰 Additional context used
🪛 LanguageTool
.changeset/pack-npm-input-stability.md

[style] ~9-~9: ‘on top of that’ might be wordy. Consider a shorter alternative.
Context: ...what it packs. Listing dist/source/** on top of that also keyed it to whatever a prior run l...

(EN_WORDINESS_PREMIUM_ON_TOP_OF_THAT)

🪛 markdownlint-cli2 (0.23.2)
.changeset/pack-npm-input-stability.md

[warning] 5-5: First line in a file should be a top-level heading

(MD041, first-line-heading, first-line-h1)

🪛 SkillSpector (2.11.0)
packages/cli/skills/gtb-build-pipeline/SKILL.md

[error] 141: [AE1] null: Referenced artifact was not completely inspected

Remediation: Make the referenced artifact locally available and fully analyzable, or remove the reference.

(analysis-evasion (AE1))

🔇 Additional comments (6)
packages/cli/src/lib/turbo-config.ts (1)

249-261: LGTM!

packages/cli/test/task-graph.test.ts (1)

173-173: LGTM!

packages/cli/test/turbo-json-dist-source.test.ts (1)

11-20: LGTM!

packages/cli/skills/gtb-build-pipeline/references/dist-source-ownership.md (1)

5-6: LGTM!

packages/cli/skills/gtb-build-pipeline/SKILL.md (1)

148-148: LGTM!

.changeset/pack-npm-input-stability.md (1)

5-12: LGTM!


📝 Walkthrough

Walkthrough

pack:npm no longer hashes dist/source/**. Its dependency hashes still include the compiled sources. Tests, build-pipeline guidance, and the changeset now reflect the revised input contract.

Changes

npm input stability

Layer / File(s) Summary
Remove compiled output inputs
packages/cli/src/lib/turbo-config.ts, turbo.json, packages/cli/test/*
pack:npm now uses metadata files as inputs and retains its compile-task dependencies and outputs. Tests verify that no dist/source path appears in its inputs.
Document the hashing contract
packages/cli/skills/gtb-build-pipeline/*, .changeset/pack-npm-input-stability.md
The documentation explains the dependency-hash and dry-run behavior. The changeset declares a patch release for @gtbuchanan/cli.

Priority: ➖ Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 1d3d2

The packaging cache-input change is consistently reflected across configuration, validation, and documentation, with no actionable current-head risk identified.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise, under 50 characters, and clearly describes the main change: removing compiled-output hashing from pack:npm.
Description check ✅ Passed The description directly explains the change, its caching rationale, the CI trade-off, and the validation performed. It is fully related to the changeset.
Linked Issues check ✅ Passed Issue #409 requires removing the prior-run dist/source/** input, preserving dependency-based invalidation, and retaining the files required for packaging. The PR removes the compiled-tree input and …
Out of Scope Changes check ✅ Passed The changes stay within issue #409. The changeset, Turbo configuration, generated-config test updates, and build-pipeline documentation explain or verify the pack:npm input change and its cache beha…
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 3…

Warning

Some tools did not complete. Review the errors below.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

packages/cli/src/lib/turbo-config.ts

ESLint skipped: missing config or dependency (missing-dependency). The ESLint configuration references a package that is not available in the sandbox.

packages/cli/test/task-graph.test.ts

ESLint skipped: the matched ESLint configuration already failed (missing-dependency).

packages/cli/test/turbo-json-dist-source.test.ts

ESLint skipped: the matched ESLint configuration already failed (missing-dependency).


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gtbuchanan
gtbuchanan marked this pull request as ready for review September 16, 2026 16:54
@gtbuchanan
gtbuchanan merged commit 46e3238 into main Sep 16, 2026
13 checks passed
@gtbuchanan
gtbuchanan deleted the pack-npm-input-stability branch September 16, 2026 17:01
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.

pack:npm is keyed to the previous run's compiled output

1 participant