Commit Graph
48 Commits
Author SHA1 Message Date
Zoltan Kochan f00e7680aa chore(release): 11.26.0 (#14638) 2026-09-07 01:30:44 +02:00
Zoltan Kochan 9a0918ceb3 test(executor): cover the emulator quoting branch off Windows (#14623)
The rule that the shell emulator takes POSIX quoting on every platform was
only observable on Windows. Both stacks gated it behind a platform check
that is constant for a given run, so a Linux or macOS job could not tell
`windows && !shell_emulator` from `windows` alone.

Take the platform as a value in `parsed_by_windows_shell` and give
`build_command` the shell family it should quote for. Both quoting branches
and the emulator rule are now asserted on any host, which also retires the
`build_command` case that was ignored on Windows and leaves the JSON branch
covered for the first time off Windows.

Mock `is-windows` in a lifecycle test so the same rule is exercised through
`runLifecycleHook` on any host. Each assertion was confirmed to fail when
its half of the rule is removed.

Related to pnpm/pnpm#14548
2026-09-06 20:30:39 +02:00
zhsama d426763b60 fix(executor): preserve emulated script arguments (#14576)
Select POSIX argument quoting whenever the shell emulator parses a script,
including on Windows. Keep native Windows shell quoting unchanged and
apply the same selection in the TypeScript lifecycle implementation.

Cover literal arguments through the direct and recursive CLI paths and the
TypeScript lifecycle boundary.

Replace the cancellation regression's startup-sensitive four-second
assertion with a completion marker, distinct exit code and bounded watchdog.
The existing timing assertion failed under full-suite startup load.

Fixes pnpm/pnpm#14548
2026-09-06 18:47:24 +02:00
Zoltan Kochan 6d90c71efd chore(release): 11.25.0, pacquet 12.1.0, pnpr 0.1.0-alpha.9 (#14306) 2026-08-29 15:50:36 +02:00
Zoltan Kochan 7a1b7b14da feat(run): persist recursive task state (#14258)
Persist passed recursive tasks incrementally in a versioned journal under the workspace's node_modules directory. Hash the invocation's task graph, script commands, arguments, environment, and execution settings so only compatible state is reused.

Use unique per-run journals, cross-process serialization around the atomically published latest-run pointer, open file handles, and newline-committed records to reject stale, superseded, malformed, torn, or unsafe state. Remove each journal after its invocation succeeds and preserve the existing dependency-pruning fallback when no compatible state is available.

Implement the same state format and resume semantics in the TypeScript CLI and Rust pnpm port, with shared identity fixtures guarding cross-implementation compatibility.

Related to pnpm/pnpm#14211.
2026-08-28 05:06:43 +02:00
Zoltan Kochan a22206394e fix(run): clean up lifecycle process trees on failure (#14244)
On Windows, pnpm's error handler cannot rely on descendant enumeration because modern systems may lack wmic and the PowerShell fallback can exceed its time budget. Recursive exec children already register their PIDs for the taskkill fallback, but lifecycle children spawned by recursive run did not.

Use the spawn observer added in `@pnpm/npm-lifecycle` 1100.1.0 to register lifecycle children with the existing tracker. Reuse the process-tree fixture to verify recursive run cleanup with the process-enumeration paths removed from PATH.

Also disable Git checks in the publish error test so a dirty contributor worktree cannot mask the missing-version error that test exercises.

Related to pnpm/pnpm#14211.
2026-08-27 21:27:50 +02:00
Zoltan Kochan 123737055c fix(run): filter hidden regexp script matches (#14238) 2026-08-27 18:12:53 +02:00
Zoltan Kochan dcf3657187 fix(run): treat empty regexp scripts as missing (#14237)
RegExp script selectors included matching names even when their script bodies
were empty, unlike exact-name selection. Recursive task orchestration could
therefore dispatch tasks pulled in through dependsOn before eventually
reporting that the requested script did not exist.

Filter empty bodies at the shared script-selection boundary in both the
TypeScript CLI and pacquet, so pre-dispatch validation observes the same
missing-script semantics for exact and RegExp selectors.

Related to pnpm/pnpm#14211.
2026-08-27 17:53:10 +02:00
Zoltan Kochan 0f2ad88da2 feat: add per-task concurrency limits (#14229)
Add an optional positive-integer concurrency limit to workspace task settings and carry it onto resolved task nodes.

Reserve permits in the dependency-ready scheduler rather than inside workers. This lets unrelated task names use available workspace capacity, while tasks waiting on their own limit remain undispatched and do not start after a bailed failure.

Implement matching configuration validation, scheduling behavior, and integration coverage in the TypeScript CLI and pacquet.

Implements the per-task concurrency extension from pnpm/pnpm#14211.
2026-08-27 16:51:15 +02:00
Zoltan Kochan 9f3f18905e perf: retire chunk-based workspace execution loops (#14221)
Move the remaining workspace command pipelines from topological chunks to the shared dependency-ready scheduler. Recursive rebuild, per-project install-family commands, pack, publish, stage approval, dependency builds, and project lifecycle scripts can now dispatch each node as soon as its own prerequisites settle instead of waiting at a workspace-wide layer barrier.

Keep concurrency inside the scheduler so ready work cannot over-dispatch, retain the existing command-specific bail and no-bail policies, and wait for already-dispatched command work where the old Promise.all and scoped-thread paths did. Ignored cycles remain deterministic by dropping backward edges in the graph sequencer's flat order.

With all execution consumers migrated, simplify graph sequencing to order plus cycles, replace grouped project sorting with dependency maps, and remove the obsolete run-groups dependency and chunk helpers.

Implements item 2 of pnpm/pnpm#14211.
2026-08-27 15:03:46 +02:00
Zoltan Kochan a83886e47f refactor: extract workspace task scheduler (#14215)
Move workspace task graph construction and scheduling out of the recursive command implementations into dedicated TypeScript and Rust packages.

The Rust crate depends on the lower-level dependency graph sequencer so package-manager code can consume it without creating a dependency cycle. Existing recursive run and exec consumers now import the shared implementations, preserving their current behavior while enabling the follow-up scheduler migrations tracked by pnpm/pnpm#14211.

Related to pnpm/pnpm#14211.
2026-08-27 11:58:01 +02:00
Zoltan Kochan e7f3bccfff feat: workspace task orchestration (#14209)
Replace the chunked topological scheduler of recursive run/exec with
per-task scheduling in both stacks: a task — a (project, script) pair —
becomes runnable when every task it depends on has completed
successfully, and runnable tasks are dispatched under the
workspace-concurrency limit with no barrier between
dependency-independent tasks.

A new "tasks" section in pnpm-workspace.yaml declares task dependencies
with the caret convention ("^build" = the task in each workspace
dependency, "build" = the task in the same project). A task with no
entry behaves as depending on its own name in the workspace
dependencies, which is exactly what chunking implied. A project without
the script becomes a pass-through node that is reported skipped and
keeps the chain intact.

Also per the RFC: task-graph cycles are ERR_PNPM_TASK_CYCLE naming the
participating tasks, scoped to the invocation's selected graph, with
ignoreWorkspaceCycles: true downgrading the error to a warning;
--resume-from excludes exactly the anchor's transitive dependencies;
--reverse runs the reverse graph; under --no-bail dependents of a
failed task are reported skipped and do not add to the exit code; with
--bail, the first failure ends the run at once and nothing new is
dispatched; output is inherited only when at most one script can ever
be in flight; and pnpm -r run --dry-run [--json] prints the resolved
task graph without running anything (the verify-deps check included).

Implementation: the projects sorter exposes the tunneled dependency-edge
map (filteredProjectsDependencies / filtered_projects_dependencies)
instead of only its flattened chunks; the recursive summary is
task-keyed (dependsOn-pulled tasks get "<dir>#<task>" keys); pacquet's
inert --sequential now means concurrency 1 and its --no-sort
resume/reverse handling is aligned with the TypeScript CLI; the dead
chunk helpers are removed.

Related to https://github.com/pnpm/rfcs/pull/23
2026-08-27 02:41:03 +02:00
Zoltan Kochan d3ebbedc4a fix: enforce git prepare approvals on store reuse (#14160)
Git preparation was gated only while fetching a package. Once an approved project placed prepared files in the shared store, a different project could link those files without consulting its own allowBuilds policy.

Persist whether preparation was required in each git package's store-index row and check the active project policy before warm-store reuse. Legacy rows without the marker are reused only with explicit approval; otherwise they go through the existing cold fetch and preparation gate. Revalidate in-process git fetch results as well so a long-lived store controller cannot carry approval across policy changes.

Pass the canonical lockfile resolution ID into both git fetch paths so the allowBuilds identity and suggested key stay byte-for-byte exact. Mirror the marker and warm-reuse gate in pacquet using the shared msgpackr-compatible store format.

Closes pnpm/pnpm#13965.
2026-08-25 18:15:59 +02:00
Zoltan Kochan 370dfd4bd0 fix(cli): accept --production, and reproduce a prod install as --prod (#14148)
The Rust CLI registers only `--prod` on `install`, so the `pnpm install …`
command the verify-deps-before-run gate reproduces from a production-only
install — built with pnpm's `--production` spelling — was rejected by the
argument parser, aborting every `pnpm run` (Closes pnpm/pnpm#14147).

`--production` is the setting name behind `--prod`, and the TypeScript CLI
accepts it on every command where `--prod` selects dependency groups, so
restore it as an alias there too (`audit`, `licenses` and `outdated` already
had it), and emit the documented `--prod` in the reproduction command in
both stacks.

Closes #14147
2026-08-25 11:27:03 +02:00
Zoltan Kochanandgithub-actions[bot] e3cb54258c chore(release): 11.24.0, pacquet 12.0.0-rc.10 (#14134)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-24 15:53:03 +02:00
Zoltan Kochanandgithub-actions[bot] 726d6b4a04 chore(release): 11.23.0 (#14111)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-23 15:47:36 +02:00
Zoltan Kochan 9720df211a feat(cli): port the six CLI flags the Rust CLI was missing (#14104)
The TypeScript CLI accepts `--stream`, `--aggregate-output`,
`--use-stderr`, `--reporter-hide-prefix`, `--ignore-workspace`, and
`--workspace-packages`; pacquet rejected all six. Section 2 of
pnpm/pnpm#14101.

`--stream` is the substantial one. A recursive `run` inherited the
terminal for every project, so pacquet had no way to attribute a line to
the project that wrote it, and `--parallel` — which expands to
`--stream` in pnpm's `run` shorthand table — produced unreadable
interleaved output. `RunScript` grows a `ScriptOutput`: `Inherit` keeps
the old path, `Streamed` pipes the child and republishes each line as a
`pnpm:lifecycle` event through the new `StreamedScript`, which also
absorbs the line pumps `run_lifecycle_hook` already had. The reporter
gains `streamLifecycleOutput`, so the lifecycle stream renders
append-only while the rest of the frame still redraws in place — the
same split pnpm's reporter makes.

`--aggregate-output` buffers a script's events until it exits and then
renders the run as one block, formatting at flush time so the prefix
color wheel advances in print order. `--reporter-hide-prefix` drops the
prefix from the script's own output lines only, leaving the `$ <script>`
echo and the `Done` / `Failed` line labelled. It is a `run` / `exec`
option, so it is scope-validated and hidden like the other
command-scoped globals; a recursive `exec` reads its explicit `false` as
the signal to start prefixing, matching pnpm's
`reporterHidePrefix === false` gate.

`--ignore-workspace` stops the workspace search in `Config::current`, so
`pnpm-workspace.yaml` contributes neither settings nor sibling projects
and a blocked dependency build is not scaffolded into its `allowBuilds`.
`--workspace-packages` is resolved into
`Config::workspace_package_patterns` alongside the manifest's own
`packages`, which `discover_workspace_projects` now takes from the
config rather than re-reading the manifest at every call site.

The five boolean settings also become readable from
`pnpm-workspace.yaml`, the global `config.yaml`, and `PNPM_CONFIG_*`.

This is pacquet-only: the TypeScript CLI already has all six.
2026-08-23 15:03:12 +02:00
Zoltan Kochan c9b8632ea6 feat(config): declare each registry once in the registries setting (#13942)
Registries do not all lay out tarball URLs the way the npm registry does.
JFrog Artifactory repeats the scope in a scoped package's tarball filename
(`@acme/widget/-/@acme/widget-1.0.0.tgz`) where npm strips it. pnpm cannot
rebuild such a URL, so it writes it out for every scoped package instead of
omitting it, and the lockfile carries a host-specific URL per dependency.

pnpm had no place to record such a fact, because it had no place to
describe a registry at all — only three ways to name one. `registries`
mapped a scope to a URL, `namedRegistries` mapped a bare-specifier prefix
to a URL, and neither could carry anything else.

`registries` now declares a registry once, keyed by its URL, with every
fact about it in the entry: a `serverType`, the `scopes` routed to it,
and the `prefix` it answers to. `serverType` has three states:

  undeclared  strict; only the exact canonical URL is reconstructible
  npm         also serves the percent-encoded scoped path
  artifactory repeats the scope in the tarball filename

registry.npmjs.org resolves to `npm` as a built-in, so its behavior is
unchanged and the old hostname check becomes that one default rather than a
special case in the predicate. `npm` cannot be the default: asserting
npmjs-compatibility is a claim only the operator can make.

The URL is the key because every fact in an entry is a fact about that
server. Keying the layout by scope would bind it to whoever the scope
currently points at, so two developers whose scope resolves differently
would write lockfiles that disagree about which URLs may be omitted.
`scopes` and `prefix` are routes to the registry and are inverted at
config-read time into the two lookups the rest of pnpm already queries,
leaving the resolver, installer, and lockfile layers untouched and the
precedence chain (builtin < .npmrc < yaml < `_auth` < CLI) unchanged.

The layout is declared, never inferred. Sniffing the registry URL cannot work:
a virtual repository serves both layouts at once, depending on whether each
package was synced from upstream or published locally, so no registry-level
signal — route, response header, or probe — decides it. Declaring it also
keeps a wrong guess a fixable misconfiguration instead of a silent breakage.

`serverType` feeds a single URL builder that both sides of the lockfile use:
the writer omits a tarball URL only when the builder reproduces it, and the
reader rebuilds it with the same call. They therefore agree by construction,
so pnpm never has to assume a registry serves some second URL as well.

The setting lives in pnpm-workspace.yaml rather than .npmrc because the
lockfile depends on it: one developer omitting URLs that another reconstructs
differently would break a frozen install. A `serverType` in the global
config.yaml is ignored for the same reason, while the routes declared
alongside it are kept. Credentials are rejected there — the file is
committed — and still belong in .npmrc. The registry URL is the map key, so
the request-destination env gate applies to keys as well as values.
Credentials and unknown fields are refused after parsing, since a parse
error renders the offending source line verbatim.

A map whose values are all strings is the older `<scope>: <url>` shape and
is still read as one. Mixing the two shapes in one map is refused, and so is
a URL-keyed entry written as a string. `namedRegistries` is deprecated in
favor of `prefix` and is read only for prefixes `registries` does not
declare; a prefix stays singular because it is the registry's identity in a
lockfile dep path.

An entry that routes nothing to itself and matches no configured registry is
reported as a warning rather than silently ignored; it is a warning and not
an error because a shared config dependency can legitimately describe
registries a given project does not use.

Config dependencies and pnpr-server-mode resolution pass no server type; in
both, the writer and the reader share that default, so they stay consistent.

Closes pnpm/get-npm-tarball-url#16. Supersedes pnpm/pnpm#13920.
2026-08-17 01:28:21 +02:00
Zoltan Kochan ae462e10ea feat(gvs): restore NODE_PATH resolution for scripts, ESM included (#13931)
With a global virtual store, package directories live outside the
project, so Node's upward node_modules walk from their real paths never
reaches the project's hoisted node_modules — undeclared (phantom)
dependencies stop resolving, and Node ignores NODE_PATH entirely for
ESM imports (Related to pnpm/pnpm#9618).

When enableGlobalVirtualStore is on (and extendNodePath is not
disabled), every child process pnpm spawns — run, exec, lifecycle
scripts, dlx — now receives NODE_PATH pointing at the private hoist dir
and the root node_modules, plus a NODE_OPTIONS --import flag that
registers a resolve hook restoring NODE_PATH lookups for ESM, replacing
the plugin-esm-node-path config dependency.

The flag is a self-contained constant: the registration module and the
hook are nested data: URLs, so no loader file has to exist on disk and
the flag stays valid regardless of which project or pnpm version
spawned the child. It prefers module.registerHooks() (in-thread, no
DEP0205 deprecation warning) and falls back to module.register() on
Node >=18.19 <22.15. Everything outside the RFC 3986 unreserved set is
percent-encoded: encodeURIComponent alone leaves single quotes bare,
and the NODE_OPTIONS tokenizer treats those as quote delimiters.

Both stacks embed identical hook sources and each asserts its derived
flag against the shared golden file
pnpm11/exec/esm-node-path-loader/test/import-flag.txt, so they cannot
drift apart silently.

Where the nodeOptions setting overwrites NODE_OPTIONS (run, exec,
recursive run, install lifecycle), the flag is re-applied. pacquet's
dlx and global installs force GVS off for their self-contained trees
and now strip the injected env from the caller's cloned config, so a
tool never resolves phantoms from the invoking project's tree; the
TypeScript dlx (GVS on by default) adds the flag and lets the bin shim
supply NODE_PATH.

This deliberately does not address the TypeScript-compiler side of
pnpm/pnpm#13210: tsc, tsserver, and bundlers implement their own
resolution and honor neither NODE_PATH nor Node loader hooks. That
class remains packageExtensions / compat-DB territory.
2026-08-16 11:20:12 +02:00
Zoltan Kochanandgithub-actions[bot] 93fcba4224 chore(release): 11.22.0, pacquet 12.0.0-rc.6 (#13926)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-15 18:50:30 +02:00
Zoltan Kochan 286d7ea37b fix(injected-deps-syncer): unlink a bin the script dropped (#13848)
Both stacks only ever created bin links. A build step that stopped
declaring a bin left its shim behind in every `.bin` the install had
written it to, pointing at a command that was no longer there.

Take the bin set from the manifest as it stood *before* the scripts ran
and unlink whatever the new manifest no longer declares. The copies
cannot answer that question themselves: their `package.json` is
hardlinked to the source, so a script that rewrites it in place has
already changed the copies too, and by sync time no record of the old
bins survives on disk. `pnpm run` already holds the pre-script manifest,
so it passes it down.

The install spreads an injected package's bins over three directories —
beside the copy, inside it, and the virtual store's hoisted `.bin` — and
this function had only ever written to the first. All three are cleared.
A stale name another package legitimately owns is put back by the relink
that follows, so removing first costs nothing.
2026-08-12 08:54:42 +02:00
Zoltan Kochanandgithub-actions[bot] 8adb97ed05 chore(release): 11.21.0, pacquet 12.0.0-rc.2 (#13742)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-09 16:02:53 +02:00
Zoltan Kochanandgithub-actions[bot] ebc48abdc5 chore(release): 11.20.0, pacquet 12.0.0-beta.4 (#13608)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-03 15:48:54 +02:00
Zoltan Kochan d3556f6ba9 refactor(text): move lexCompare and nerfDart into the monorepo (#13535)
Both utilities lived in the pnpm/components Bit workspace, where their
component names collide with same-named components elsewhere in the Bit
registry. Move the code here and publish it under new names:

  `@pnpm/util.lex-comparator` -> `@pnpm/text.ordinal-comparator`
  `@pnpm/config.nerf-dart`    -> `@pnpm/config.registry-auth-key`

The new names describe what the utilities do: the comparator is ordinal
rather than locale-aware, and the mapped URL is the key that registry
settings are stored under in `.npmrc`. The exported functions keep their
names, so consumers only change their import specifiers.

Implementations and tests are carried over unchanged. The rationale from
the components' docs pages moves into doc comments: why `localeCompare`
cannot be used for values compared across machines, and where `nerfDart`
originates.

No pacquet counterpart is needed. The Rust stack has its own
implementations of both and no user-visible behavior changes.
2026-07-31 23:00:10 +02:00
Zoltan Kochan 536b7a2c8a chore(release): 11.19.0 (#13524) 2026-07-31 10:46:26 +02:00
Zoltan Kochanandgithub-actions[bot] 925c33d780 chore(release): 11.18.0, pacquet 12.0.0-beta.0 (#13481)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-29 09:29:53 +02:00
Zoltan Kochan 56907deda0 fix(cli): close the six pnpm-12-on-n8n defects (#13375)
Six independent pacquet-side defects found while installing and building
n8n with pnpm 12. Each is a divergence from the TypeScript CLI, so every
fix moves pacquet onto pnpm's existing behavior rather than inventing new
behavior.

Finding 2 — an `allowBuilds` placeholder written by pnpm made
`WorkspaceSettings` refuse to load the config at all. The value is now an
`AllowBuild` enum; only decided entries reach `Config::allow_builds`,
matching `createAllowBuildFunction`. The raw value stays on
`WorkspaceSettings` so `pnpm config list` and the `updateConfig` hook
still see what the file says.

Finding 3 — `diffy`'s matcher is byte-exact, while `@pnpm/patch-package`
compares lines with trailing whitespace stripped and retries a hunk
within twenty lines of its recorded position. `pacquet-patching` now
applies hunks itself with those tolerances, keeping `diffy` for parsing.
The file is modeled as `split('\n')` throughout, so untouched CRLF lines
keep their `\r` and a file without a final newline keeps that shape.

Finding 4 — `Config::user_agent` is threaded to install lifecycle
scripts, `pnpm run`, `exec`, and `dlx`, which previously saw nothing or
the bare string `pnpm`. It still reports `node/?` rather than the host
Node version; filling that in costs a `node --version` spawn on every
command, which is a separate trade-off to make.

Finding 5 — `/pattern/` script selectors select every matching script in
single-project and recursive runs, mirroring `tryBuildRegExpFromCommand`
+ `getSpecifiedScripts`. This adds `regex` to the workspace
dependencies; it was already in the lock transitively.

Finding 6 — concurrent `packageManager` switches raced on the shared
global-virtual-store slot: the destructive re-stage removed a directory
another process was still writing, and the native-binary relink used
unlink-then-hardlink, pulling the executable out from under a sibling
running it. The install is now serialized by an advisory lock (a new
`pacquet_fs::DirLock`, which gives up rather than failing so a lost lock
is never worse than today), and the relink skips an already-correct
destination and otherwise swaps via rename.

Finding 8 — settings drift under a frozen install reports
`ERR_PNPM_LOCKFILE_CONFIG_MISMATCH` naming the one field instead of
`ERR_PNPM_OUTDATED_LOCKFILE` with the whole map dumped; ignored build
scripts keep their `(patch_hash=…)` suffix; and a deprecated package is
reported once, since pacquet's resolver re-emits one it later meets at a
shallower depth.

All six are pacquet-only bugs; the TypeScript CLI already behaves this
way, so there is nothing to mirror.

Closes pnpm/pnpm#13322
2026-07-25 20:34:26 +02:00
Zoltan Kochanandgithub-actions[bot] 454e7d62b3 chore(release): 11.17.0, pacquet 12.0.0-alpha.19, pnpr 0.1.0-alpha.5 (#13237)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-23 17:07:05 +02:00
Matt Cowley a4f25f2266 fix(exec): revert script ordering change for pnpm run --sequential /regex/ (#13175)
Reverts the lexicographical sorting of scripts introduced in pnpm/pnpm#13074, as this was a breaking change in behaviour. When using `pnpm run --sequential /regex/`, scripts will now be executed in the order they are listed in `package.json`, giving developers control over the order without needing odd script prefixes. Fixes pnpm/pnpm#13174.
2026-07-23 12:15:34 +02:00
Zoltan Kochanandgithub-actions[bot] d1edab423e chore(release): 11.16.0, pacquet 12.0.0-alpha.18 (#13216)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-22 21:58:38 +02:00
Zoltan Kochanandgithub-actions[bot] 331c26aa4b chore(release): 11.15.1, pacquet 12.0.0-alpha.16 (#13162)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-20 00:19:20 +02:00
Zoltan Kochanandgithub-actions[bot] 32a30c4d70 chore(release): 11.15.0, pacquet 12.0.0-alpha.15, pnpr 0.1.0-alpha.4 (#13126)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-18 14:19:57 +02:00
Zoltan Kochan f4948525df chore: remove repository changelogs (#13119)
Remove the legacy repository changelog files now that release changelog storage defaults to the registry. The publish path composes and injects CHANGELOG.md into release tarballs, so keeping historical copies in source control duplicates generated release data.

Update adm-zip to the patched 0.6 release and override vulnerable transitive versions after the dependency audit began rejecting versions below 0.6.0.
2026-07-18 13:10:25 +02:00
Zoltan Kochanandgithub-actions[bot] f8b08ea63f chore(release): 11.14.0, pacquet 12.0.0-alpha.14 (#13113)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-18 00:01:20 +02:00
Alessio Attilio e7138afe9d feat(exec): restore --sequential flag and sort regex-matched scripts lexicographically (#13074)
Restored `--sequential` (`-s`) CLI flag for `pnpm run` to force `workspaceConcurrency=1` for matched scripts across workspace packages and within individual packages. Added `.sort((a, b) => a.localeCompare(b))` to `getSpecifiedScripts` so that multi-script execution triggered by a RegExp selector executes in deterministic lexicographical order. Updated `cliOptionsTypes` in TypeScript and `RunArgs` across all Rust CLI commands (`run`, `clean`, `restart`, `stop`, `dispatch_script`) to ensure seamless parsing and parity.
2026-07-17 13:20:26 +02:00
Zoltan Kochanandgithub-actions[bot] ca66b76fb2 chore(release): 11.13.1 (#13058)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-16 00:36:19 +02:00
Zoltan Kochanandgithub-actions[bot] 682f57e773 chore(release): 11.13.0, pacquet 12.0.0-alpha.9, pnpr 0.1.0-alpha.1 (#12986)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-13 22:19:04 +02:00
armanandZoltan Kochan b46f96165f fix: kill spawned process trees with taskkill on Windows error exits (#12925)
Main thread panicked: begin > end (105 > 28) when slicing
`@pnpm/npm-lifecycle@1100.0.0(patch_hash=e3541c…)(supports-color@10.2.2)`
at pacquet/crates/resolving-deps-resolver/src/resolve_peers.rs:2490:51

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-07-13 16:30:01 +02:00
Zoltan Kochanandgithub-actions[bot] 98722fab10 chore(release): 11.12.0 (#12937)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-11 11:34:29 +02:00
Zoltan Kochan 8e17c3d366 refactor: rename the pacquet/ directory to pnpm/ (#12913)
Pure directory move plus path fixups: the Rust port ships as pnpm v12,
so the source tree now lives at pnpm/ (alongside pnpm11/, the frozen
TypeScript line). No identifiers change in this pass — crate names
(pacquet-*), the pacquet bin, PACQUET_VERSION, the @pacquet/* npm
package names v11's runPacquet spawns, the .pacquet virtual-store dir,
the benchmark harness's clone dir, and the pacquet-*.yml workflow
filenames (npm trusted publishing is bound to them) all stay for a
follow-up.

Also removes the root /pnpm/ .gitignore entry (build detritus in the
pre-pnpm11 package location): pnpm/ is real source now and must not be
ignored. Developers with a stale generated pnpm/ dir should delete it
before checking out this change.
2026-07-10 18:06:56 +02:00
Zoltan KochanandClaude Fable 5 d2ed60afba test: make git-resolver and dlx git tests immune to GitHub flakiness (#12885)
The git-resolver unit tests hit live github.com by default: the mocks for
fetchWithDispatcher and graceful-git existed, but beforeEach restored the
real implementations. When GitHub throttles the shared CI runner IPs, the
HEAD probe in isRepoPublic() fails (it has zero retries and treats any
error as "private"), and resolution silently degrades from the hosted
tarball to a git clone, changing the resolved id and failing the
assertions. This broke the main branch build at
https://github.com/pnpm/pnpm/actions/runs/29026897310/job/86153736091

The mocks are now the default: fetch reports every repository as public
and graceful-git serves ls-remote output from a fixture table captured
from the real repositories, with the same commit hashes the assertions
already expected. The private-repo-over-HTTPS test now calls
mockFetchAsPrivate() explicitly instead of relying on a real 404 for the
nonexistent github.com/foo/bar. The one live-network case in
parsePref.test.ts got the same treatment. The suite drops from ~40s to
under half a second and runs offline.

The dlx e2e test stays a genuine end-to-end test against GitHub, but its
allowBuild list now approves both resolution shapes of the same commit
(codeload tarball and git+https clone), so the resolver's
rate-limit-induced fallback no longer trips the
GIT_DEP_PREPARE_NOT_ALLOWED gate, as seen in
https://github.com/pnpm/pnpm/actions/runs/29029971938/job/86170695840

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 00:53:03 +02:00
Zoltan Kochanandgithub-actions[bot] 8e1e4c0aae chore(release): 11.11.0 (#12886)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-09 22:29:10 +02:00
Zoltan Kochanandgithub-actions[bot] 7cd1e4f4f6 chore(release): 11.10.0 (#12799)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-04 21:05:03 +02:00
Adrian NiculescuandZoltan Kochan c1212355bf fix: respect transitive dependencies when sorting filtered projects (#12688)
The recursive command runners sorted opts.selectedProjectsGraph, which keeps
only the selected projects as keys. Edges to unselected projects were dropped,
so a transitive dependency between two selected projects (a -> b -> c with only
a and c selected) was lost and the two ran out of order.

sortFilteredProjects resolves the order through the full workspace graph: for
each sorted project it walks dependencies, tunneling past unselected projects
and stopping at selected ones, so a transitive relationship becomes a direct
edge. Projects without a real dependency stay in the same chunk, preserving
concurrency.

Prod-only filters (--filter-prod) prune dev edges. Their selected projects are
sorted through the prod-pruned full graph, so transitive prod deps are honored
without reintroducing the dropped dev edges. In a mixed selection each project
is sorted through the graph that matches how it was selected: regularly filtered
projects through the full graph, prod-only ones through the prod-pruned graph.
Carrying prod-only projects on the full graph would let a dev-only reverse edge
form a cycle and collapse a real prod dependency and its dependent into one
chunk.

Fixes pnpm/pnpm#8335

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-07-02 17:03:35 +02:00
Zoltan Kochanandgithub-actions[bot] 9671d9aeed chore(release): 11.9.0 (#12611)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-06-23 17:16:24 +02:00
Zoltan Kochan ec7cf70853 fix(dlx): shorten dlx cache path to avoid Windows MAX_PATH failures (#12605)
The dlx cache path is <cacheDir>/dlx/<key>/<prepare>/node_modules/.pnpm/
<pkgId>/node_modules/<pkg>. The <key> (64-char sha256 hex) and <prepare>
(<time>-<pid> in hex) segments are dlx overhead on top of pnpm's already-
deep virtual-store layout. For a transitive dep with a long name this tips
the package directory over Windows' MAX_PATH (260) — measured at 259 chars
for @pnpm.e2e/pre-and-postinstall-scripts-example in the dlx e2e test. A
lifecycle script then runs with that directory as its cwd, and CreateProcess
fails to resolve an over-length cwd, which Node surfaces as the confusing
"spawn C:\Windows\system32\cmd.exe ENOENT". Flaky rather than constant
because the <prepare> and temp-dir segments vary in length, straddling 260.

Shorten both dlx-specific segments:
- cache key: createShortHash (32 hex, 128 bits) instead of createHexHash
  (64). pacquet already truncated to 32, so this also restores parity.
- prepare dir: encode time and pid in base36 instead of hex.
2026-06-23 13:06:42 +02:00
Zoltan Kochan d577eeaf76 fix(dlx): make failed-install cache cleanup best-effort on Windows (#12575)
* fix(dlx): make failed-install cache cleanup best-effort

On Windows, `pnpm dlx` could fail with a spurious "EBUSY: resource busy
or locked, rmdir" error. When an install into the dlx cache failed, the
catch block removed the partially-populated prepare dir with
`fs.promises.rm(cachedDir, { recursive: true, force: true })`. That call
has no retries, so it died on the same lingering Windows handle (a
just-run install script's child process, or antivirus scanning freshly
written files) and threw EBUSY — which then replaced and masked the
original install error.

Make the cleanup best-effort: swallow its failure so the original error
always surfaces, and add `maxRetries`/`retryDelay` so the removal itself
succeeds once the transient lock clears. A leftover prepare dir is
harmless — it has a unique name and findCache only trusts the `pkg`
symlink.

The pacquet port already removes the prepare dir best-effort (`let _ =
fs::remove_dir_all(...)`) and returns the original error, so the
user-visible behavior already matches; only the (non-observable) retry
is absent there.

* fix(dlx): log dlx cache cleanup failures instead of swallowing them

Catch the best-effort cache cleanup with a narrow handler that logs the
failure via logger.warn (mirroring tryRemovePkg in modules-cleaner's
prune) instead of a blanket `.catch(() => {})`. The original install
error is still the one rethrown, so cleanup failures stay visible without
ever masking the real cause.
2026-06-22 15:13:10 +02:00
Zoltan Kochan fc2f33912e refactor: move the TypeScript pnpm CLI into a pnpm11/ directory (#12537)
The TypeScript pnpm CLI freezes at v11; pnpm 12 will be the Rust pacquet
port. To make that split legible, all TypeScript source, test, and build
directories move under a new top-level pnpm11/ directory. The name states
the version boundary rather than implying a behavioral fork, since the two
stacks are meant to behave identically.

Scope is source-only: the shared workspace root stays at the repo root.
pnpm-workspace.yaml, package.json, pnpm-lock.yaml, .pnpmfile.cjs,
.meta-updater, __patches__, .changeset, .husky, and the lint/spell configs
remain in place, so one pnpm workspace and one Cargo workspace still span
all three products. pnpr/client and pacquet/tasks/registry-mock stay as
cross-product workspace members.

Rewiring the move required:
- pnpm-workspace.yaml globs prefixed with pnpm11/
- root package.json script paths, eslint.config.mjs, tsconfig.lint.json,
  .gitignore, and CODEOWNERS updated
- .meta-updater/src/index.ts literals repointed (pnpm11/pnpm/package.json,
  pnpm11/__utils__, pnpm11/__typings__, and the main package directory)
- regenerated every moved package's repository/homepage URL via meta-updater
- pnpm11/pnpm/bundle-deps.ts and __utils__/scripts/src/typecheck-only.ts
  climb one more level to reach the repo root

.meta-updater stays at the repo root because @pnpm/meta-updater resolves
its config at <cwd>/.meta-updater/main.mjs.

TS CI (.github/workflows/ci.yml) now only runs when pnpm11/-relevant paths
change, via a dorny/paths-filter changes job plus a TS CI / Success
aggregate gate; branch protection should require only that gate.
2026-06-20 14:36:25 +02:00