Skip to content

pacquet: promote --filter/--filter-prod to recursive mode (CLI-wide, prerequisite for driving release.yml) #12723

Description

@KSXGitHub

What this issue is (and isn't)

This tracks one shared CLI-argument behavior that pacquet is missing: passing --filter (or --filter-prod) on its own must put the command into recursive mode, even without -r/--recursive. It is not about publish logic, and not about applying the filter once recursive (that was #12711, already done). Like #12711, this belongs outside the publish PR (#12691) because it governs every recursive-capable command, not just publish.

Why

pnpm's own deployment CI (.github/workflows/release.yml) drives publishing entirely through --filter, without -r:

pn --filter=@pnpm/exe publish --tag=next-11 --access=public --provenance
pn publish --filter=!pnpm --filter=!@pnpm/exe --access=public --provenance
pn publish --filter=pnpm --tag=next-11 --access=public --provenance

For pacquet to be a drop-in pn in this workflow, pn publish --filter=pnpm must behave as a recursive publish over the filtered set. Today it does not — it falls through to the single-package path and would try to publish the current directory.

Upstream behavior to match

pnpm promotes recursive in cli/parse-cli-args, for all commands, when a filter is present:

// pnpm11/cli/parse-cli-args/src/index.ts (around line 219)
if (options['recursive'] !== true && (options['filter'] || options['filter-prod'] || recursiveCommandUsed)) {
  options['recursive'] = true
  // ...
}

pnpm/src/main.ts then builds the filter set from config.filter/config.filterProd, and — when every selector is an exclusion (!pnpm, !@pnpm/exe) and the command is not run at the workspace root — additionally pushes !{.} so the root project is excluded too.

Current pacquet state

  • recursive is taken straight from the -r/--recursive flag and threaded through RunCtx.recursive; there is no promotion from --filter.
  • The only place --filter affects routing is the install fast-path bail in pacquet/crates/cli/src/cli_args/dispatch.rs (if self.recursive || !self.filter.is_empty() || !self.filter_prod.is_empty()), which merely disables a fast path — it does not enter the recursive command dispatch.
  • Consequence: run, exec, pack, and publish all require an explicit -r to go recursive, diverging from pnpm whenever only --filter is passed.

(Permalinks pinned at a70a996e88: dispatch routing in pacquet/crates/cli/src/cli_args/dispatch.rs, publish entry in pacquet/crates/cli/src/cli_args/publish.rs where if recursive || self.recursive selects the recursive path.)

Proposed change

Promote recursive to true when filter or filter_prod is non-empty, at the same single point where the raw -r flag is read (so it applies CLI-wide, matching parse-cli-args rather than being special-cased per command). Two sub-points to port faithfully:

  1. The all-exclusion augmentation (!{.}) from main.ts so --filter=!pnpm --filter=!@pnpm/exe also excludes the workspace root. Note: in this repo the root manifest is private: true, so recursive publish's existing eligibility check already drops it; the augmentation still matters for non-private-root workspaces and for non-publish commands.
  2. Confirm no already-ported run/exec/pack test asserts the current (non-promoting) behavior; update any that encode the divergence.

Acceptance

  • pn <recursive-capable-cmd> --filter=<sel> (no -r) enters recursive mode and operates on the filtered set.
  • pn publish --filter=pnpm and pn publish --filter=!pnpm --filter=!@pnpm/exe select the intended projects, matching release.yml.
  • Behavior parity verified for run/exec/pack/publish.

Not part of this issue

  • Building @pnpm/exe artifacts and the root release scripts (copy-artifacts, make-release-description) — TS/Node-specific release steps, tracked under the Rust Roadmap (#11633).
  • --batch publishing — intentionally unported; not used by release.yml.

Written by an agent (Claude Code, claude-opus-4-8).

Metadata

Metadata

Assignees

Labels

rustPull requests that update rust code

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions