fix(ts): exclude test artifacts from package#3055
Conversation
| } | ||
|
|
||
| const packOutput = JSON.parse(chunks.join('')) | ||
| const files = packOutput[0]?.files?.map((file) => file.path) ?? [] |
There was a problem hiding this comment.
Issue: The ?? [] fallback lets the guard pass vacuously. If npm pack --json ever emits an unexpected shape, or the piped stdout gets corrupted (note npm pack --dry-run runs prepack/postpack, and any stdout they emit is prepended to this JSON), files becomes [], forbiddenFiles is empty, and the script prints OK (0 files) — a green check that verified nothing. That's the failure mode a regression guard most needs to avoid.
Suggestion: Assert the payload is non-empty and contains the expected entrypoint before checking for forbidden files, e.g.:
if (files.length === 0 || !files.includes('dist/src/index.js')) {
throw new Error(`Unexpected npm pack output; got ${files.length} files`)
}so a malformed/empty payload fails loudly instead of passing silently.
|
Assessment: Request Changes The fix works and is runtime-safe (verified: no production code imports from Review themes
Nice touch wiring the contents check into |
yonib05
left a comment
There was a problem hiding this comment.
The fix works on the happy path, but the prune/rebuild mechanism is more fragile than the problem needs. npm's files field supports negation patterns, so this can be:
"files": ["dist", "!dist/**/__tests__", "!dist/**/__fixtures__", "!dist/**/*.test.*", "README.md", "LICENSE"]Same tarball, no prepack prune, no postpack rebuild, no dist mutation. Keep the tarball assertion in test:package as the regression check. Alternatively, stop compiling tests into dist with a build tsconfig that excludes them; nothing consumes dist/tests (vitest runs from src).
Either of those makes most of the inline comments below moot.
One more small thing: lint and format only cover src test/integ, so the two new scripts are not checked by either.
| } | ||
|
|
||
| const packOutput = JSON.parse(chunks.join('')) | ||
| const files = packOutput[0]?.files?.map((file) => file.path) ?? [] |
There was a problem hiding this comment.
This fails open. If prepack fails, npm pack --dry-run --json prints {"error":{...}} on stdout and exits 1, but the pipe's exit code comes from this script, and ?.files ?? [] turns the error object into an empty list. Verified locally: a failing prepack prints [package-contents] OK (0 files) and exits 0, so a broken build passes the check.
Fail if the parsed output has an error key, and assert files.length > 0.
| "build": "tsc --project src/tsconfig.json", | ||
| "prepack": "npm run build", | ||
| "prepack": "npm run build && node scripts/prune-package-artifacts.js", | ||
| "postpack": "rm -rf dist && npm run build", |
There was a problem hiding this comment.
rm -rf doesn't exist on Windows (npm runs lifecycle scripts under cmd.exe), and CI runs test:package on windows-latest. postpack fails on every pack there, and the fail-open pipe in test:package hides it, so the package check never actually runs on the Windows matrix jobs.
| "scripts": { | ||
| "build": "tsc --project src/tsconfig.json", | ||
| "prepack": "npm run build", | ||
| "prepack": "npm run build && node scripts/prune-package-artifacts.js", |
There was a problem hiding this comment.
If pack fails or is interrupted after prepack, postpack never runs and dist stays pruned. Since the build is composite/incremental and the tsbuildinfo still lists the deleted files as emitted, the next npm run build is a no-op and doesn't restore them. Only a manual clean recovers.
| "test:all": "vitest run --project unit-node --project unit-browser", | ||
| "test:all:coverage": "vitest run --coverage --project unit-node --project unit-browser", | ||
| "test:package": "cd test/packages/esm-module && npm install && node esm.js && cd ../cjs-module && npm install && node cjs.js", | ||
| "test:package": "npm run build && cd test/packages/esm-module && npm install && node esm.js && cd ../cjs-module && npm install && node cjs.js && cd ../../.. && npm pack --dry-run --json | node test/packages/assert-package-contents.js", |
There was a problem hiding this comment.
This now runs three full tsc builds per invocation: the leading npm run build, prepack's build, and postpack's rebuild (which is a cold build because rm -rf dist deletes the tsbuildinfo). CI already builds right before test:package, so every matrix job pays for three redundant compiles.
| import { join } from 'node:path' | ||
|
|
||
| const distDir = new URL('../dist/', import.meta.url) | ||
| const testFilePattern = /\.test(?:\.[^/.]+)*\.(?:js|d\.ts)(?:\.map)?$/ |
There was a problem hiding this comment.
This regex and the __tests__/__fixtures__ names are duplicated in assert-package-contents.js. If one side is updated and the other isn't, either test files ship with a green check or packing breaks. Put the patterns in one shared place.
| chunks.push(chunk) | ||
| } | ||
|
|
||
| const packOutput = JSON.parse(chunks.join('')) |
There was a problem hiding this comment.
Lifecycle script stdout gets interleaved before the JSON on npm's stdout (only the > pkg script banners go to stderr). This works today only because tsc and the prune script print nothing on success; any future console.log in prepack breaks JSON.parse here with a confusing error.
Use npm files-field negation patterns to exclude test artifacts from the tarball declaratively, dropping the prepack prune script and the postpack rebuild. Removes the Windows rm -rf failure, the interrupted-pack dist corruption, and the triple tsc build. The strands-agents#3004 regression guard now fails loudly on an empty/errored/unparseable pack payload instead of passing vacuously. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
47cd960 to
6e6de70
Compare
|
Thanks for the review @yonib05 — adopted the
On the last point — lint/format only covering |
Description
This PR keeps generated test artifacts out of the published TypeScript npm package.
The TypeScript build still uses the existing
src/tsconfig.json, butprepacknow prunes generated__tests__,__fixtures__, and compiled.test.*artifacts fromdistbefore npm assembles the tarball.postpackrebuildsdistafterward so local project-reference type checking is not left with missing declaration outputs.I also wired a package contents assertion into
test:packageso future changes fail if test artifacts re-enter the dry-run tarball.Related Issues
Resolves #3004
Documentation PR
No documentation changes needed.
Type of Change
Bug fix
Testing
npm run test:package -w strands-tsnpm run type-check -w strands-tsnpm run lint -w strands-tsnpm run format:check -w strands-tshatch run prepareChecklist
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.