Ship README and LICENSE in published npm packages - #182
Conversation
pack:npm now copies each package's README.md and the workspace-root LICENSE into dist/source/ (the directory publishConfig.directory redirects publishing to), and the published package.json carries a license field. A package-level README/LICENSE/license overrides the shared root one. npm only auto-includes README/LICENSE from the publish directory, so they were absent from the first release. Add the MIT LICENSE and a root license field, wire the copies as pack:npm turbo inputs/outputs so cache-hit publishes restore them, and patch-bump every published package to re-publish with the corrected docs. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
🔗 Linked repositories identifiedCodeRabbit considers these linked repositories for cross-repo context during reviews:
📜 Recent review details⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
🧰 Additional context used📓 Path-based instructions (3)**/*.{ts,tsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.{ts,tsx,js,jsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
**/*.test.{ts,tsx}📄 CodeRabbit inference engine (AGENTS.md)
Files:
🧠 Learnings (3)📚 Learning: 2026-06-15T19:58:14.171ZApplied to files:
📚 Learning: 2026-06-04T02:26:02.824ZApplied to files:
📚 Learning: 2026-06-15T19:58:27.007ZApplied to files:
🪛 SkillSpector (2.1.1)packages/cli/skills/gtb-build-pipeline/SKILL.md[error] 114: [YR1] YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer). Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise. (YARA Match (YR1)) 🔇 Additional comments (7)
📝 WalkthroughWalkthroughAdds a root ChangesREADME/LICENSE Publishing in pack:npm
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/cli/skills/gtb-build-pipeline/SKILL.md`:
- Around line 53-57: The documentation for the pack:npm task currently describes
README and LICENSE handling in a way that suggests different precedence rules
for each file. Update the wording to explicitly clarify that both README.md and
LICENSE follow the same precedence pattern: package-level files are preferred,
with a fallback to workspace-root versions if the package-level copy does not
exist. Replace the phrase "copies the package `README.md` plus the
workspace-root `LICENSE` (a package-level copy of either wins)" with clearer
wording that makes it obvious both files use identical package-then-root
precedence logic to avoid confusion for operators.
In `@packages/cli/src/commands/task/pack-npm.ts`:
- Around line 88-93: In the loop that iterates over the doc files (README.md and
LICENSE) in the pack-npm.ts file, add an else clause to handle the case when
source is undefined. When a doc file no longer exists in the source (source ===
undefined), delete the corresponding file from the target directory using the
same target path construction (path.join(target, name)) to prevent stale files
from persisting across builds and getting published incorrectly.
In `@packages/cli/src/lib/turbo-config.ts`:
- Around line 206-212: Add the missing root README.md file to the inputs array
for cache correctness. In the turbo-config.ts file where the pack:npm task
inputs are defined (around line 206-212), the array includes
'$TURBO_ROOT$/LICENSE' but is missing '$TURBO_ROOT$/README.md'. Since the
copyPackageDocs function treats both LICENSE and README.md files symmetrically
and falls back to root files when package-specific versions don't exist, you
need to add '$TURBO_ROOT$/README.md' to the inputs array alongside
'$TURBO_ROOT$/LICENSE' to ensure cache invalidation when the root README.md
changes.
In `@packages/cli/test/prepack.test.ts`:
- Around line 14-17: Extract the inline object type definition for the overrides
parameter in the scaffoldPackage function into a separate interface to match the
repository's TypeScript style guide. Create a new interface that defines the
shape with the pkgManifest and rootManifest properties (both typed as
Record<string, unknown>), then update the overrides parameter to reference this
new interface instead of using the inline type definition.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 2cf09700-329b-4b20-ad4e-264c99d37dbc
📒 Files selected for processing (10)
.changeset/publish-readme-license.mdLICENSEpackage.jsonpackages/cli/skills/gtb-build-pipeline/SKILL.mdpackages/cli/src/commands/task/pack-npm.tspackages/cli/src/lib/manifest.tspackages/cli/src/lib/turbo-config.tspackages/cli/test/manifest.test.tspackages/cli/test/prepack.test.tsturbo.json
🔗 Linked repositories identified
CodeRabbit considers these linked repositories for cross-repo context during reviews:
gtbuchanan/tooling(manual)
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Prefer interface for defining object shapes in TypeScript
Use camelCase for variable names in TypeScript
Use JSDoc on exports in TypeScript files
Files:
packages/cli/test/manifest.test.tspackages/cli/src/lib/manifest.tspackages/cli/src/lib/turbo-config.tspackages/cli/test/prepack.test.tspackages/cli/src/commands/task/pack-npm.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.test.{ts,tsx}: Use expect(result).toMatchObject({ exitCode: 0 }) instead of expect(result.exitCode).toBe(0) when asserting on CommandResult
Generate incidental test data via@gtbuchanan/test-utils/builderswith pattern: import * as build from '@gtbuchanan/test-utils/builders', then const name = build.scopedPackageName()
Use Vitest native tag system for slow tests (test('name', { tags: ['slow'] }, ...) or /**@module-tagslow */)
Files:
packages/cli/test/manifest.test.tspackages/cli/test/prepack.test.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Suppress ESLint warnings with -- reason suffix on suppressions
Files:
packages/cli/test/manifest.test.tspackages/cli/src/lib/manifest.tspackages/cli/src/lib/turbo-config.tspackages/cli/test/prepack.test.tspackages/cli/src/commands/task/pack-npm.ts
.changeset/*.md
📄 CodeRabbit inference engine (AGENTS.md)
.changeset/*.md: Every PR requires a changeset; create a .changeset/.md file with YAML frontmatter listing affected packages and bump types
For PRs that don't affect published packages, create an empty changeset with no packages in frontmatter
Files:
.changeset/publish-readme-license.md
🧠 Learnings (3)
📚 Learning: 2026-06-04T02:26:02.824Z
Learnt from: gtbuchanan
Repo: gtbuchanan/tooling PR: 139
File: packages/cli/test/coverage-codecov-upload.test.ts:2-2
Timestamp: 2026-06-04T02:26:02.824Z
Learning: In tests within **/{test,e2e,__tests__}/**/*.{test,spec}.{ts,tsx,js,jsx}, follow the AGENTS.md faker convention: direct `faker-js/faker` usage is allowed only for one-off primitives when the produced value’s shape is exactly what faker returns (e.g., `faker.git.commitSha()`, `faker.string.uuid()`). Use `gtbuchanan/test-utils/builders` only when there is a domain-shaped value worth centralizing (e.g., scoped package names, semver ranges, GitHub URLs). Do not wrap a native faker generator in a builder for a plain primitive (e.g., a raw commit SHA), since that adds indirection without centralizing any domain shape.
Applied to files:
packages/cli/test/manifest.test.tspackages/cli/test/prepack.test.ts
📚 Learning: 2026-06-15T19:58:14.171Z
Learnt from: gtbuchanan
Repo: gtbuchanan/tooling PR: 162
File: packages/cli/test/discovery.test.ts:86-94
Timestamp: 2026-06-15T19:58:14.171Z
Learning: In the gtbuchanan/tooling repo, hand-authored `.pkl` source files are expected to live at the package root (top level), not under subdirectories like `src/`. Accordingly, when reviewing `discoverPackage` logic for `hasPkl`, ensure it only detects top-level `.pkl` files in the package root and does not require (or add) recursive/nested-directory `.pkl` discovery.
Applied to files:
packages/cli/test/manifest.test.tspackages/cli/src/lib/manifest.tspackages/cli/src/lib/turbo-config.tspackages/cli/test/prepack.test.tspackages/cli/src/commands/task/pack-npm.ts
📚 Learning: 2026-06-15T19:58:27.007Z
Learnt from: gtbuchanan
Repo: gtbuchanan/tooling PR: 162
File: packages/cli/test/typecheck-pkl.test.ts:8-23
Timestamp: 2026-06-15T19:58:27.007Z
Learning: When reviewing tests (e.g., in packages/**/test/**/*.test.ts), if the system-under-test explicitly branches on specific string-literal values (such as sort order, extension filters, or reserved filename exclusions like "PklProject"), require those branching inputs to be hardcoded literals in the test rather than generated via test-data builders. Do not recommend replacing these literals with builder patterns, because it would obscure what behavior is being exercised. Allow builder patterns only for incidental, domain-shaped data where the exact values do not affect the assertion logic (e.g., scoped package names or semver ranges used as opaque inputs).
Applied to files:
packages/cli/test/manifest.test.tspackages/cli/test/prepack.test.ts
🪛 markdownlint-cli2 (0.22.1)
.changeset/publish-readme-license.md
[warning] 13-13: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
🪛 SkillSpector (2.1.1)
packages/cli/skills/gtb-build-pipeline/SKILL.md
[error] 116: [YR1] YARA rule 'backdoor_persistence': Backdoor persistence with malicious payloads (shell commands, SSH key injection, hidden root users) [malware]: YARA rule matched a known malware signature (reverse shell, backdoor, ransomware, C2 framework, or info stealer).
Remediation: Remove the malware payload or compromised file entirely. Investigate how it entered the skill and audit all other artifacts for additional indicators of compromise.
(YARA Match (YR1))
🔇 Additional comments (8)
LICENSE (1)
1-22: LGTM!package.json (1)
10-10: LGTM!packages/cli/src/lib/manifest.ts (1)
27-28: LGTM!Also applies to: 38-39, 51-54, 69-77
packages/cli/src/commands/task/pack-npm.ts (1)
1-75: LGTM!Also applies to: 96-147
turbo.json (1)
145-153: Same issue: missing"$TURBO_ROOT$/README.md"in inputs.This file is auto-generated from
turbo-config.ts, so fixing the missing$TURBO_ROOT$/README.mdinput in the TypeScript source (see previous comment) will automatically correct this generated JSON.packages/cli/test/manifest.test.ts (1)
1-8: LGTM!Also applies to: 144-172
packages/cli/test/prepack.test.ts (1)
200-280: LGTM!.changeset/publish-readme-license.md (1)
1-20: LGTM!
- Make pack:npm README copy package-only (no workspace-root fallback); a README documents one package, so falling back to the monorepo root README would publish a wrong one. LICENSE stays package-then-root since a license is repo-wide. - Remove a stale dist/source/README.md or LICENSE left by a prior run so a since-deleted doc isn't republished. - Extract scaffoldPackage's overrides into a ScaffoldPackageOverrides interface; tighten the pack:npm SKILL.md note to one line. - Add tests: README does not fall back to root; stale doc removal. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Summary
The packages were published for the first time missing their
READMEandLICENSE. npm only auto-includes those files from the publish directory, whichpublishConfig.directoryredirects todist/source/— butpack:npmonly copied the generated manifest andskills/there. There was also noLICENSEfile orlicensefield anywhere in the repo.LICENSE(no copyright year, to avoid drift) and a rootlicensefield.pack:npmnow copies each package'sREADME.mdand the workspace-rootLICENSEintodist/source/, and the publishedpackage.jsoncarries alicensefield.README/LICENSE/licenseoverrides the shared root one (resolveDoc/resolveLicense, package-then-root precedence).buildRepoFieldskeeps root-precedence for the scoped repo coordinates; license is handled separately since the package should win.pack:npmturbo inputs (cache invalidates on edit) and outputs (cache-hit publishes restore them), excluding the self-generated copies from the input glob like the existingpackage.jsonexclusion.Testing
resolveLicenseunits +prepackintegration tests (README/LICENSE copy, package-over-root override, absent-docs, license-field precedence).pnpm buildgreen (67/67 tasks, incl. e2e against packed tarballs);gtb verifyreports no drift; lint clean.@gtbuchanan/eslint-config: tarball shipspackage/README.md+package/LICENSE, manifest has"license": "MIT".🤖 Generated with Claude Code