fix: keep workspace-root excluded when --recursive --filter uses only negative filters#11480
Conversation
PR #10465 stopped the implicit workspace-root exclusion for `pnpm -r run/exec/test/add` whenever any --filter was provided. That gate was too broad: with a negative-only filter set (e.g. `--filter '!a'`) the workspace root started showing up in the matched projects, contradicting the documented default behavior. Only suppress the implicit root exclusion when the user provided at least one positive (non-`!`) filter that could have been intended to select the root. Negative-only filter sets keep the documented default, and `--include-workspace-root` continues to opt the root in explicitly. Close #11341.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThis PR fixes a regression in recursive workspace filtering: when all provided filters are negative (e.g., ChangesRecursive Filter Root Exclusion
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related issues
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Pull request overview
Fixes a regression in recursive command filtering where the workspace root was incorrectly included when users supplied only negative (!) --filter arguments, restoring the documented default behavior (root excluded unless explicitly opted in).
Changes:
- Adjust implicit workspace-root exclusion logic to remain active when all user-provided filters are negative.
- Add regression tests for
--recursive --filter '!<pkg>'with/without--include-workspace-root. - Add a changeset documenting the patch-level fix.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
pnpm/src/main.ts |
Refines the condition that adds the implicit !{<root>} filter so negative-only filter sets still exclude the root. |
pnpm/test/recursive/filter.ts |
Adds regression coverage for negative-only filter behavior and the --include-workspace-root override. |
.changeset/recursive-filter-root-exclusion.md |
Documents the regression and the corrected default behavior in a patch changeset. |
Comments suppressed due to low confidence (1)
pnpm/src/main.ts:256
- This condition has a double-negation and is hard to parse (
!filters.some(...!filter.startsWith('!'))). For readability/maintainability, consider extracting a named boolean (e.g.hasPositiveFilter) or usingfilters.every(({filter}) => filter.startsWith('!')).
} else if (
!filters.some(({ filter }) => !filter.startsWith('!')) &&
workspaceDir &&
config.workspacePackagePatterns &&
!isRootOnlyPatterns(config.workspacePackagePatterns) &&
!config.includeWorkspaceRoot &&
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
The --stream reporter prefixes output lines with the project's relative directory, so the workspace root appears as `. which$`, not `root which$`. The original assertion would have passed even if the regression were still present. Verified the corrected assertion fails against the buggy code and passes against the fix.
… negative filters (#11480) * fix: include workspace root only when --filter is positive PR #10465 stopped the implicit workspace-root exclusion for `pnpm -r run/exec/test/add` whenever any --filter was provided. That gate was too broad: with a negative-only filter set (e.g. `--filter '!a'`) the workspace root started showing up in the matched projects, contradicting the documented default behavior. Only suppress the implicit root exclusion when the user provided at least one positive (non-`!`) filter that could have been intended to select the root. Negative-only filter sets keep the documented default, and `--include-workspace-root` continues to opt the root in explicitly. Close #11341. * test: fix root-exclusion assertion to match --stream prefix The --stream reporter prefixes output lines with the project's relative directory, so the workspace root appears as `. which$`, not `root which$`. The original assertion would have passed even if the regression were still present. Verified the corrected assertion fails against the buggy code and passes against the fix.
… negative filters (#11480) * fix: include workspace root only when --filter is positive PR #10465 stopped the implicit workspace-root exclusion for `pnpm -r run/exec/test/add` whenever any --filter was provided. That gate was too broad: with a negative-only filter set (e.g. `--filter '!a'`) the workspace root started showing up in the matched projects, contradicting the documented default behavior. Only suppress the implicit root exclusion when the user provided at least one positive (non-`!`) filter that could have been intended to select the root. Negative-only filter sets keep the documented default, and `--include-workspace-root` continues to opt the root in explicitly. Close #11341. * test: fix root-exclusion assertion to match --stream prefix The --stream reporter prefixes output lines with the project's relative directory, so the workspace root appears as `. which$`, not `root which$`. The original assertion would have passed even if the regression were still present. Verified the corrected assertion fails against the buggy code and passes against the fix.
Summary
Fixes #11341. When
pnpm --recursive --filter '!<pkg>' run/exec/test/addwas used, the workspace root started appearing in the matched projects in 10.33.0+, contradicting the documented default behavior that root is excluded for these commands unless--include-workspace-rootis set.Root cause
PR #10465 (which fixed #10462 —
--filter <root>not finding the root in single-package workspaces) gated the implicit root-exclusion onfilters.length === 0. That gate was too broad: any user filter — including a negative one like--filter '!a'— disabled the implicit exclusion.Fix
Suppress the implicit root exclusion only when the user provided at least one positive (non-
!) filter that could have been intended to select the root. Negative-only filter sets keep the documented default, and--include-workspace-rootcontinues to opt the root in explicitly.--filter '!a'--filter a--filter root-name--include-workspace-root --filter '!a'The
isRootOnlyPatternsguard from #10927 still ensures single-package workspaces (packages: ['.']or emptypnpm-workspace.yaml) are unaffected.Test plan
pnpm/test/recursive/filter.tscovering--filter '!a'with and without--include-workspace-root.--filterdoesn't find root package withpnpm-workspace.yaml#10462 (--filter <root>) still passes.pnpm --filter pnpm run compileand lint pass.Written by an agent (Claude Code, claude-opus-4-7).
Summary by CodeRabbit
Bug Fixes
Tests
Documentation