Commit Graph
487 Commits
Author SHA1 Message Date
Zoltan Kochanandgithub-actions[bot] b4438d438b chore: update dependencies, Node.js, pnpm, and GitHub Actions (#15070)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-18 19:06:19 +02:00
Zoltan Kochanandgithub-actions[bot] 5276e7402b chore: update dependencies, Node.js, pnpm, and GitHub Actions (#15003)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-18 13:13:22 +02:00
Zoltan Kochan e53ce9a943 perf(python): share concurrent project resolutions (#14993)
Prepare Python projects with bounded concurrency after selecting their
interpreters and workspace sources. Collect all results before reporting an
error, preserving discovery order for publication and error selection.

Share fresh registry resolutions within one install using normalized lockfile
inputs (including overrides, constraints, and extra indexes), requires-python,
and the interpreter report as the key. A per-key mutex
allows one resolution to populate the cache while identical projects wait.
Existing lockfiles retain their replay and frozen validation paths. Local
sources and direct URLs do not share fresh resolutions. Environment installs
seed and validate the shared lockfile through the existing acceptance path.

Make backend environment sharing safe for concurrent projects. Siblings wait
for one environment to finish; recursive builds track their own active keys
and reuse completed nested environments without waiting on other backend chains.
This preserves cycle diagnostics
and avoids dependency cycles between in-flight cache entries.

Add regression coverage for identical projects, frozen lockfile validation,
project dependency-rule isolation, concurrent slot replenishment, and settling failed preparation without
publishing lockfiles. Python installation exists only in pnpm v12.

Replace benchmark artifacts on reruns so the combined report and privileged
comment workflow consume current samples. Seed distinct whole-second manifest,
lockfile, and validation times in the synchronous fast-path test; equal
whole-second mtimes conservatively trigger a content check, so the prior
fixture could fail when its initial mtime landed on a second boundary.

Related to https://github.com/pnpm/pnpm/issues/14945 (item 13).
2026-09-17 01:56:09 +02:00
Zoltan Kochan 6d73648565 chore: run the tests a change affects, with smoke tests for its dependents (#14985)
`pnpm/CONTRIBUTING.md` required `just ready` before every commit, explicitly
including documentation and comment edits: a full `cargo nextest run` over
~11,500 tests for changes that cannot break them. The root guide's "never run
all tests" rule was scoped to the TypeScript sections, so it read as not
applying to Rust.

The checks now match what a change can break. Formatter, typos, and
workspace-wide check and lint before every commit, since those are cheap and
catch the cross-crate breakage a scoped selection hides, plus the tests for
what the diff affects. The full local run is reserved for changes whose blast
radius cannot be named, because CI already runs the suite on three platforms.

`just test-affected` resolves changed files to packages through `cargo
metadata` and runs them through `run-rust-tests.mjs`, expanding any `pnpr-*`
selection so feature unification does not silently skip backend tests, and
refusing to guess when a change reaches files every crate compiles against.
Selection is crate-level rather than `rdeps()`-based: `pnpm-cli` holds a third
of the workspace's tests and sits downstream of nearly everything, so `rdeps()`
selects 84% or more of the suite for any core crate. Restructuring that target
is tracked in pnpm/pnpm#14984.

Crate-level selection leaves the dependents unrun, so the new `smoke` profile
runs in their place: one end-to-end test per area of CLI behavior, triggered by
the dependent set rather than added to every run. Membership is by behavior
area rather than code coverage, since nearly every end-to-end test walks the
same install path. An exact-name filterset fails open, so a test checks every
entry against the suite sources.

The `testing-changes` skill carries the selection cookbook and the gotchas that
make a scoped run lie.

Related to pnpm/pnpm#14984.
2026-09-16 22:26:31 +02:00
Zoltan Kochan 5471ef3bd2 test(cargo): compare pnpm's Cargo resolution against cargo's own (#14979)
pnpm v12 resolves Cargo dependencies itself rather than shelling out to
cargo, so it is a second implementation of cargo's resolver, and being a
drop-in replacement means producing the versions cargo produces rather than
merely producing a lockfile. Unit tests pin that against synthetic indexes,
which is where the rules are easiest to state and easiest to get subtly
wrong: the resolver fixes in pnpm/pnpm#14952, pnpm/pnpm#14960,
pnpm/pnpm#14961 and pnpm/pnpm#14962 were each confirmed by hand-checking a
real workspace against cargo after the unit tests were already green.

This is that hand-check, written down. For each workspace in the corpus it
resolves twice, compares the locked crates, and asks cargo whether it
accepts pnpm's lockfile with `--locked` in a copy pnpm never touched, so
the lockfile is measured apart from the source replacement written beside
it. Requirements are open rather than pinned: both resolvers read the same
index on the same day, so an upstream release changes what they agree on,
not whether they agree.

A workspace declares whether the two are expected to agree yet. A known
gap reports as such and does not fail the run, but does fail if the two
start agreeing, so a fixed issue cannot leave a stale expectation behind.
`feature-activated-deps` is the one gap today, tracking pnpm/pnpm#14978.

It runs on a daily cron rather than per-PR because it reads the live index,
where a yank or a release can change a result with nothing in this repo
changing.
2026-09-16 21:00:53 +02:00
Zoltan Kochanandgithub-actions[bot] ba2a57105e chore: update dependencies, Node.js, pnpm, and GitHub Actions (#14940)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-16 09:14:51 +02:00
Zoltan Kochanandgithub-actions[bot] 49dbe22c32 chore: update dependencies, Node.js, pnpm, and GitHub Actions (#14922)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-15 12:51:51 +02:00
Zoltan Kochan 3c0f092390 fix(peers): stop the peer walk at linked workspace packages (#14909)
An importer's peer report followed every `link:` edge into the linked
importer and kept walking, so a workspace package shared by many projects
was re-traversed once per project that reached it. Every visit canonicalized
the target and read its manifest, which made a lockfile-only install of a
6,833-project workspace take 29 s instead of 3 s and left `pnpm peers check`
running for over 15 minutes.

Stop at the edge, as pnpm's own lockfile walker does. A linked package's own
linked dependencies are its obligation, and it is an importer of the same
lockfile, so its own report already covers them.

Add a linked-workspace benchmark scenario to keep the walk linear: 225
generated projects joined by 6,369 `workspace:*` edges, every linked project
declaring a peer its consumers provide, resolved offline against no registry
package at all. The regressed walk takes 93 s on that fixture against 1.4 s.

Closes pnpm/pnpm#14906
2026-09-15 09:48:19 +02:00
Zoltan Kochan 224aed744b refactor: move cmd-shim into the pnpm monorepo (#14893)
Import cmd-shim source, tests, and snapshots from pnpm/cmd-shim at
83f9b9449c2adeec26e1cc2d03ef0fe82d2e41ca. Maintaining the shim alongside
its consumers removes the need for coordinated changes across repositories.

Publish the package as `@pnpm/bins.cmd-shim` and replace external dependencies
with workspace links. Preserve the original BSD-2-Clause license, including
its copyright notice, and keep the manifest updater from replacing it with MIT.
Reuse `@pnpm/fs.graceful-fs` and integrate the existing Node.js tests with the
workspace test scripts. Retain the existing snapshots and align the version
with the TypeScript workspace's required 1100.x band.
2026-09-14 21:30:59 +02:00
Ayush Singh 3a99eaea72 ci(rust): lint the workspace on Windows (#14808)
Rust CI / Clippy ran on Ubuntu only, so no job linted the #[cfg(windows)]
half of the workspace. The test job builds that code, which type-checks it
but runs no lints.

Add a windows row to the Clippy matrix and clear what it found: a raw-pointer
borrow of the console-mode out-parameter, an unused type parameter on the
Windows stub of link_symlinked_executable, a redundant clone in the cmd-shim
tests, and imports and test helpers that only unix code reaches.

Two findings come from Windows's wider PathBuf. PackageManifest measures 200
bytes on Linux and 208 on Windows, which crosses large_enum_variant's
threshold, so GateManifest::Found boxes it. result_large_err is allowed
workspace-wide instead: with large-error-threshold lowered on Linux, error
enums across ten crates sit just under the 128-byte limit, and the same
8-byte creep pushes them over. Boxing every one of them is its own refactor.

zizmor needs the benchmark workflow's checks: write scoped to the job that
posts a check, since a fork PR has advanced-security off and fails on any
finding.

Fixes pnpm/pnpm#14801.
2026-09-14 08:15:34 +02:00
Zoltan KochanandClaude Opus 5 3271acfe8e ci: scope the benchmark workflow's checks permission to its report job (#14879)
`checks: write` sat at the workflow level, granting it to all five jobs,
four of which never touch `GITHUB_TOKEN`. Only the report job does, in
the Bencher upload step.

zizmor's excessive-permissions audit flags the workflow-level grant. It
is the one unsuppressed finding in the repository, and because fork PRs
run the zizmor action with `advanced-security` off, the action prints
its findings and exits non-zero instead of uploading SARIF. That turns
the single medium finding into a red check on every fork PR while main
stays green.

Verified with zizmor 1.30.1, the version CI installs: the run over the
repository reports no findings with this change.


Claude-Session: https://claude.ai/code/session_01PjkYZtr2fTKD4wu3w1GCz4

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-14 08:13:44 +02:00
Zoltan Kochan 2ea04e6e52 style(rust): adopt complexity-aware rustfmt (#14875)
Pin pnpm's rustfmt fork and use a cached wrapper for local formatting,
CI, pre-push checks, and editor integration. The formatter has its own
dated nightly runtime while the workspace keeps its existing compiler.

Choose chain layout by call count and argument complexity, with a
40-column allowance for short expressions. Attach the first method when
the complete first line would otherwise end within the continuation
indentation. Preserve simple receivers,
cap intermediate leading accesses at column 80 and final accesses at
100, and separate fields and
await after wrapped methods. Apply the same rules in conditions.

Keep Max heuristics and compact struct literals, with an independent
35-column destructuring limit. Reformat pnpm and pnpr, extract only the
helpers and test modules needed for existing size limits, and fix macro
commas without relaxing lint rules.

Related to pnpm/pnpm#14562 and pnpm/pnpm#14862.
2026-09-13 22:39:50 +02:00
Zoltan Kochan 9cd124f665 refactor: limit Rust structs to eight fields (#14872)
Pin perfectionist to the merge containing too_many_struct_fields and
configure max_fields = 8 with tests included.

Refactor oversized internal state, options, and request structs across
pnpm and pnpr. Group fields by responsibility, reuse existing context
and policy types, and pass groups directly to the helpers consuming them.
Use shorter field names inside their namespace and fetching for fetch
settings. Update all callers, fixtures, and documentation links.

Reuse install/project/peer groups through their consumers instead of
reconstructing them. Share run/exec execution arguments and their mapping,
existing archive/config-dependency store contexts, and GitSource cache
inputs. Preserve owned versus borrowed representations where tasks need
different lifetimes.

Preserve fixed external configuration, serialized document, and binding
interfaces with narrowly scoped expectations that identify the format.
There are no legacy exemptions for ordinary internal structs.

Cache workspace debug/release artifacts explicitly and rotate their cache
namespace so old Perfectionist binaries cannot leak into CI after a pin
change. Reproduced the cache inclusion with Actions glob settings and tar,
and verified that the new paths exclude the lint library.

Related to pnpm/pnpm#14562.
2026-09-13 18:52:34 +02:00
Zoltan Kochanandgithub-actions[bot] 62a242f718 chore: update dependencies, Node.js, pnpm, and GitHub Actions (#14850)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-12 11:57:43 +02:00
Zoltan KochanandClaude Opus 5 822f2dcb23 chore(ci): install every crate through pnpm (#14824)
Commit the pnpm-managed Cargo source block. The block is a function of
Cargo.lock, so an install regenerates it byte for byte and the tracked
`.cargo/config.toml` stops reporting as modified after every install. A new
Rust CI step fails if the committed block and the lockfile drift apart.

Cargo now resolves every crate through `.pnpm/crates` and falls back to its
own registry nowhere, so each job that runs cargo needs an install behind it.
Eight did not have one: both cargo-unused jobs, the micro-benchmark, the
integrated benchmark's build and executor jobs, and the three release builds.
The new `install-crates` action gives them one and narrows the JavaScript half
with `--filter pacquet`, which a filter does not do to the Cargo half.

The release builds go through `cross`, which mounts the checkout at
`/project`. pnpm links each crate into `.pnpm/crates` with a relative symlink,
so a store outside the checkout stops resolving under that mount. Those jobs
install into a store inside the checkout instead, on Linux, the one host where
cross containerizes the build at all.

The two workflows that commit no longer discard the block. It is tracked
content now, and a run that changes it should carry the change.


Claude-Session: https://claude.ai/code/session_01Gg6uVUzLw1MniCLC81TQjP
Claude-Session: https://claude.ai/code/session_01HwJS1pAz9HHQpJWEJAiaUu

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-11 02:27:47 +02:00
Zoltan KochanandClaude Opus 5 4d32532cc7 chore: install the Rust dependencies with pnpm (#14689)
* chore: install the Rust dependencies with pnpm

Turn on `cargo.enabled` so `pnpm install` installs the crates `Cargo.lock`
pins alongside the JavaScript dependencies. pnpm links the registry crates
into `.pnpm/crates/crates-io` and the git-sourced ones into
`.pnpm/crates/git`, then writes a source replacement block into
`.cargo/config.toml` that points Cargo at both.

The `node-semver` fork stays patched in. pnpm installs git-sourced crates
since pnpm/pnpm#14694, which shipped in the 12.4.1 the repository pins, so
enabling this no longer costs the fork's `<=` range and `Ord for Bound`
fixes.

Document the workflow, including the two things a contributor hits first:
`pnpm install` shells out to `cargo`, so it fails when `cargo` is off
`PATH`, and the generated block leaves the tracked `.cargo/config.toml`
modified after every install.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SDxJNVEeyUBb4pcepEpGcj

* ci: initialize Rust before pnpm installs dependencies

Every `pnpm install` now shells out to `cargo metadata`, and there is no
way to opt one out: `cargo.enabled` is read from `pnpm-workspace.yaml`
only, no CLI flag or `PNPM_CONFIG_*` variable overrides it, and `--filter`
does not narrow the Cargo half. So each job whose install runs gets the
pinned toolchain first. `pnpm/setup` installs unless told not to,
`pnpm/update` runs its own install, and `pnpm pipeline` installs before it
runs anything.

The step has to precede the install rather than follow it. The rustup
action ends with `git restore .`, which would otherwise wipe the source
replacement block back out of `.cargo/config.toml`.

Keep that block out of the two workflows that commit. It points at the
gitignored `.pnpm/crates`, so a commit carrying it would break every
Rust-only job and every checkout that has not installed. Both workflows
also decide whether to commit at all by reading `git status --porcelain`,
which the block would make non-empty on every run. Each discards it right
before that check: the release PR in a step of its own, the lockfile
update through the `post-update` command pnpm/update runs between its
install and its commit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SDxJNVEeyUBb4pcepEpGcj

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-10 21:17:43 +02:00
Zoltan Kochan d2c5ecbb63 chore(ci): run checks through pnpm pipelines (#14690)
Declare CI pipelines and root task scripts, and invoke them from the
TypeScript, Rust, reusable test, and pnpr build workflows. Let pipelines
perform frozen installs and order TypeScript compilation before linting.

Keep existing test runners responsible for affected-package selection,
file-level sharding, and summary generation. Read shard settings from the
workflow environment, with explicit command-line arguments taking precedence.

Run root tasks with --include-workspace-root --full: the scripts live in the
root manifest only, and the test runners already select their own scope. Pass
--no-cache so a task that later declares outputs cannot skip a check.

Keep the dependency install in its own step in the two jobs whose commands are
timed for Bencher, so the reported duration stays a test duration. Preserve
existing job gates and artifact handoffs.
2026-09-10 21:05:01 +02:00
Zoltan Kochanandgithub-actions[bot] a75be2f56d chore: update dependencies, Node.js, pnpm, and GitHub Actions (#14806)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-10 19:11:38 +02:00
Zoltan Kochan c09981cf7d ci: parallelize integrated benchmark builds and scenarios (#14799)
Resolve main and HEAD once and build their Rust client/server pairs in
parallel while retaining the per-commit binary caches. Build the executor
in a third independent job. Exclude the peer-heavy fixture from the shared
npm proxy cache and invalidate potentially incomplete cache entries. Transfer the
binaries and shared benchmark executor in tar archives to preserve
executable permissions.

Run each scenario on a separate runner, keeping all compared revisions
within the same hyperfine invocation. Build the TypeScript CLI only for
the peer-heavy scenario. Aggregate scenario artifacts into the existing
report and Bencher formats, and propagate the peer-heavy gate result
after publishing measurements.

This changes CI orchestration only and needs no package changeset.
2026-09-10 16:56:12 +02:00
Zoltan Kochanandgithub-actions[bot] c52f5d3686 chore: update dependencies, Node.js, pnpm, and GitHub Actions (#14762)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-10 08:33:20 +02:00
Zoltan Kochanandgithub-actions[bot] c39ee2bff9 chore: update dependencies, Node.js, pnpm, and GitHub Actions (#14724)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-09 13:28:18 +02:00
Zoltan Kochan 2fa282950f style: adopt perfectionist's new size and shape rules (#14730)
Pin the perfectionist dylint library to a revision instead of a tag and
enable the four rules that revision adds: arbitrary_source_item_ordering,
core_instead_of_std, excessive_cognitive_complexity with a limit of 10,
and redundant_derive_more_forward_template.

The tree is made to pass them by refactoring rather than by exemptions:
no #[expect], no #[allow], and no raised limit. Oversized functions are
split into named steps, conditions that carried a meaning are given
names, three-way outcomes become enums, repeated parameter lists become
types that own the shared values, and the nearly sixty CLI config
overrides that repeated the same three shapes are driven from macro
tables.

cargo-dylint refuses a library built against a newer dylint_linting, so
CI moves to cargo-dylint/dylint-link 6.0.4 to match the pinned revision.
The 6.0.1 bootstrap failure the previous 6.0.0 pin worked around is fixed
there.

Related to https://github.com/pnpm/pnpm/issues/14562. That issue plans
seven size-and-shape rules; only excessive_cognitive_complexity has
landed upstream so far. It also proposed a per-site #[expect] for every
existing violation, which this PR deliberately does not do.
2026-09-09 13:15:59 +02:00
Zoltan Kochanandgithub-actions[bot] 2a762b7d53 chore: update dependencies, Node.js, pnpm, and GitHub Actions (#14681)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-08 13:29:35 +02:00
Zoltan KochanandClaude Opus 5 e91c63887e feat: add android-arm64 and android-x64 builds (#14660)
Build the Rust CLI and the NAPI addon for aarch64-linux-android and
x86_64-linux-android and publish them as `@pnpm/exe.android-*` and
`@pnpm/napi.android-*`, so installing pnpm in Termux resolves a native binary
instead of failing the preinstall with no prebuilt binary for the platform.
Closes pnpm/pnpm#14431.

pnpm 11 reached Android because it was a JavaScript CLI and bionic was
irrelevant to it. pnpm 12 ships per-platform native binaries, which turned that
into a hard install failure.

This ships a dedicated artifact rather than aliasing the existing musl one onto
android. Aliasing would mean dropping `libc: ["musl"]` from the shared packages
and weakening that metadata for Alpine consumers, and it does not work anyway:
the musl binary's `getaddrinfo` reads `/etc/resolv.conf`, which Android does
not have and which cannot be created without root, so every registry lookup
fails there. A bionic binary resolves through Android's own resolver. The
generated manifests carry `os: ["android"]` with no `libc` field, since bionic
is neither of the two the field can name.

Cross.toml pins newer images for the two targets. The ones cross picks by
default carry NDK r21, whose toolchain predates Rust's move from libgcc to
libunwind, so linking fails with `cannot find -lunwind`. They are pinned by
digest rather than tag because they build published, attested binaries.

Android has no CI behind it: nothing in the release pipeline or the test suite
runs on a device or an emulator, so this is best-effort.

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-07 16:35:46 +02:00
Zoltan Kochan 52859b9bfd feat: add freebsd-x64, linux-ppc64 and linux-s390x builds (#14656)
Build the Rust CLI and the NAPI addon for x86_64-unknown-freebsd,
powerpc64le-unknown-linux-gnu and s390x-unknown-linux-gnu, and publish them as
`@pnpm/exe.*` and `@pnpm/napi.*` platform packages, so installing pnpm on those
hosts resolves a native binary instead of failing the preinstall with no
prebuilt binary for the platform. Closes pnpm/pnpm#14597.

pnpm 11's npm package was a JavaScript CLI that ran wherever Node.js ran, so
all three worked without anyone building for them. pnpm 12 ships per-platform
native binaries, which turned that into a hard install failure. ppc64le and
s390x were the only two architectures Node.js ships an official binary for that
pnpm did not; both were reported on pnpm/pnpm#14651, which stays open for
OpenBSD, a tier 3 Rust target with no rustup std and no cross image.

The release matrix builds all three with cross on the existing x86_64 Linux
runner, the same way it already builds the aarch64 and riscv64 targets, so no
new hardware is involved.

The little-endian POWER package is `@pnpm/exe.linux-ppc64`, not `-ppc64le`.
Node reports both endiannesses as `ppc64` and npm's `cpu` field cannot express
which, so the name has to be what `process.arch` yields. Only the little-endian
build is released, matching Node.

FreeBSD's platform entry is a bare specifier rather than a glibc/musl pair. It
has no libc split, so it takes the same shape as darwin and win32 and never
reaches the libc ordering, and its manifest carries no `libc` field.
2026-09-07 14:57:22 +02:00
velonica0andZoltan Kochan 7a27a8efd9 feat: add linux-riscv64 build (#14529)
Build the Rust CLI for riscv64gc-unknown-linux-gnu and publish it as
@pnpm/exe.linux-riscv64, so installing pnpm on a riscv64 host resolves a
native binary instead of finding no prebuilt binary for the platform.

The release matrix builds the target with cross on the existing x86_64 Linux
runner, the same way it already builds both aarch64 targets, so no riscv64
hardware is involved.

PLATFORMS.linux gets a plain string specifier rather than a glibc/musl pair.
Only a glibc build is released, and the libc ordering maps over the pair's
keys, so a pair with a missing musl entry would yield an undefined specifier.

---------

Co-authored-by: Zoltan Kochan <z@kochan.io>
2026-09-07 12:30:44 +02:00
Zoltan Kochanandgithub-actions[bot] 08e64d4b83 chore: update dependencies, Node.js, pnpm, and GitHub Actions (#14603)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-07 11:29:41 +02:00
Zoltan Kochan 6ba99fb386 feat(pnpr): share cargo compilation caches (#14620)
Expose named compiler caches through the WebDAV subset used by sccache.
Apply pnpr account access and publication policies before buffering uploads,
including existing token restrictions. Entries are immutable and verified
against a digest bound to their cache scope, key, and bytes before serving.
Reuse the shared artifact store's filesystem/S3 selection, quota accounting,
publication lifecycle, and orphan reclamation.

Bound compiler uploads to two concurrent bodies per server and reject excess
requests before buffering. Store digest and payload as separate buffers in
one conditional object write. Use metadata-only HEAD and duplicate checks;
GET still verifies content before serving it.

Stock sccache trusts the server and allowed publishers; it does not verify
pnpm signed envelopes. Document trusted CI publication and HTTPS requirements.
Also document sccache 0.17's absolute Rust build-path requirement and its
read-only multilevel behavior: remote hits backfill disk, but new compilation
misses are not cached locally when a tier is read-only.

Add HTTP, policy, integrity, quota, and real Cargo integration coverage.
Install sccache for Rust CI and local test setup. Extract the existing
miette diagnostic normalization into a shared test helper to fix a shim
assertion exposed by the full suite's longer temporary paths.
2026-09-06 15:35:06 +02:00
Zoltan Kochan 427bece813 feat(cli): integrate python with shared install and artifact lifecycles (#14586)
Exercise the multi-ecosystem architecture through a usable Python
integration, not test-only metadata writers.

Keep Python requirement, marker, lockfile and environment semantics
separate from npm and Cargo. Reuse the install-wide HTTP/auth budget,
verified artifact ingestion, CAS and store index.

Extract a shared install lifecycle without ecosystem-specific branches.
Native tasks declare metadata footprints and return prepared projections.
Settle all work before publishing Cargo or Python state, and reverse
attempted publications before restoring metadata on failure.
Retain resources when rollback fails so recovery remains possible.

Enroll npm with its existing in-place materialization semantics, and
keep npm-only dispatch on its early path. Do not unify native resolvers,
lockfile formats, target identity or package layouts.

Consolidate archive ingestion below the ecosystem boundary. Share cache
validation, authenticated requests, extraction retries and publication
across tarballs and ZIPs, retaining tar streaming and ZIP decoding.
Test the shared contracts across both formats and preserve npm fast paths.

Use standard pylock.toml, independently validated with uv.
New features target pnpm v12 only. Shared archive URL-redaction fixes
also cover pnpm v11.

Related to pnpm/pnpm#14566 and pnpm/rfcs#34.
2026-09-05 22:58:05 +02:00
Zoltan Kochan cf5a7bf514 fix(ci): allow pnpm v12 install scripts in tag upgrade check (#14592)
The upgrade check only allowed install scripts for `@pnpm/exe`, so
installing the pnpm v12 wrapper failed before self-update could run.
Allow scripts for the package selected by the existing wrapper loop.
This preserves verification of both published wrappers and allows
pnpm v12 promotions to proceed through the upgrade gate.

Verified both published 12.3.4 wrappers using the workflow's pinned
pnpm 11.13.1, including self-update and doctor --offline.
2026-09-05 19:23:51 +02:00
Zoltan Kochan 04cfce2e34 docs: update sponsors (#14580) 2026-09-05 09:53:54 +02:00
Zoltan Kochanandgithub-actions[bot] 7a0a0655cb chore: update dependencies, Node.js, pnpm, and GitHub Actions (#14577)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-09-05 09:38:08 +02:00
Zoltan Kochan 1648084667 docs: make pnpm v12 the feature development target (#14561)
pnpm v12 is the target for new feature development. The TypeScript pnpm v11 implementation is maintenance-only.

Update the repository guidance so shared bugs are fixed and tested in both versions, while v12-only features and fixes do not create v11 parity work. Align the contributor, review, changeset, release, README, and PR checklist instructions with the same policy.
2026-09-05 00:01:43 +02:00
Zoltan Kochan 779b40eb47 fix(pacquet): make the placeholder bin runnable without a shebang (#14527)
The npm package's `pnpm` bin is a placeholder that the preinstall script
replaces with the native binary. It has to stay shebang-less, because a bin
shim generated from a shebang records that interpreter and pnpm 11 generates
the shim before it puts the binary at that path. Installers that skip build
scripts never replace it, and a prose placeholder is not a shell script, so
every command failed with `syntax error near unexpected token ')'`.

Make the placeholder a valid `sh` script with no shebang. On ENOEXEC the shell
and glibc's `execvp` both retry the file under `/bin/sh`, so it runs from a
symlinked bin, from a shim that execs it, and from a direct spawn; it hands
over to `bin/pnpm.mjs`, which finds the installed binary or downloads one.
A shim generated from it still execs the file itself, so pnpm 11 delegation
keeps working once the binary takes the same path.

Windows has no ENOEXEC fallback and cannot run an extension-less file, so a
script-blocked install there still cannot run pnpm.

Closes pnpm/pnpm#14346.
2026-09-04 12:20:48 +02:00
Zoltan Kochan 949c8d3b62 ci(release): retry cross builds on transient failures (#14522)
The v12.3.2 release run died in "Package pnpm-napi darwin-x64" because
Apple clang segfaulted while linking the httparse build script. Nothing
in the tree changed; the same Blacksmith image built v12.3.1 fine the
day before. Every other packaging job was cancelled and the release had
to wait for the run to finish before "re-run failed jobs" was possible.

Route the three release cross builds through a wrapper script that
retries up to three times. Cargo keeps the crates a failed attempt
finished, so a retry only redoes the crate that died.

The Windows legs of build-rust and build-pnpr now run the build step
under bash instead of the default pwsh, as the napi packaging job
already did on both Windows targets. The clang-cl environment for
win32-arm64 is exported through GITHUB_ENV and GITHUB_PATH, so it
reaches bash the same way.
2026-09-04 03:12:51 +02:00
Zoltan Kochan d34902d5a6 chore: update dependencies, Node.js, pnpm, and GitHub Actions (#14400) 2026-09-02 18:35:33 +02:00
Zoltan Kochan 28bb2a339b ci: reference same-repository actions and workflows with the self-repository syntax (#14452)
zizmor's self-repository audit flags every `uses: ./.github/...` reference
now that GitHub has a dedicated `$/` form. The `$/` form resolves against the
workflow's own commit rather than the runtime checkout, so it cannot load an
action cloned into the workspace at runtime, and GitHub treats it as pinned.

Rewrites all 22 references (18 local actions, 4 reusable workflow calls).

With the `$/` form the runner downloads the whole repository as an action
archive at job setup, and that download fails on any broken symlink in the
tree. The four broken symlinks were all test fixtures: the directory-fetcher
and cafs tests now copy their fixture into a temp dir and create the broken
symlink there, and the has-not-outdated-deps fixture drops two dangling
node_modules links that `pnpm outdated` never followed.

pnpm's GitHub Actions dependency discovery only followed `./` references
into local actions and reusable workflows; both stacks now follow `$/` too.
2026-09-02 13:58:57 +02:00
Zoltan Kochan 355741239a ci: cancel stale workflow approval requests (#14415)
Add a trusted scheduled workflow that cancels action-required workflow runs once their 30-minute approval window expires.

Use the workflow-runs API because approval-held jobs never start and therefore cannot enforce their own job timeout. Re-check each run immediately before cancellation to tolerate approvals racing the scheduled sweep.
2026-09-01 15:37:19 +02:00
Zoltan Kochan d754f7f413 fix: ignore non-pnpm releases in Docker workflow (#14391) 2026-09-01 01:39:34 +02:00
Zoltan Kochan 340c0384aa fix(release): verify declared Rust pnpm binary (#14390) 2026-09-01 01:29:29 +02:00
Zoltan Kochanandgithub-actions[bot] 4c356251c9 chore: update dependencies, Node.js, pnpm, and GitHub Actions (#14344)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-31 16:33:34 +02:00
Zoltan Kochanandgithub-actions[bot] a3f44249db chore: update dependencies, Node.js, pnpm, and GitHub Actions (#14328)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-29 16:36:52 +02:00
Benjamin Staneck 16ee230e7b fix(napi): validate peer issue options (#14313)
Decode peer dependency query options through the typed N-API boundary instead of manually rebuilding install options from JSON. This preserves shared proxy and network settings and rejects malformed fields.

Range-check the two u32 length values because N-API number conversion does not reject overflow.

Fixes pnpm/pnpm#14312.
2026-08-29 12:04:54 +02:00
Zoltan Kochanandgithub-actions[bot] d241d0ba15 chore: update dependencies, Node.js, pnpm, and GitHub Actions (#14271)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-28 15:07:35 +02:00
Zoltan Kochan 03436d6880 fix: repair TS CI compile and lint after the dependency and Node.js update (#14206)
The dependency update (pnpm/pnpm#14205) broke TS CI / Compile & Lint in
two independent ways.

streamx 2.28.1 declares the 'data' event payload as unknown, so the five
tar-stream data handlers in the releasing commands that annotated the
chunk as Buffer no longer typechecked. They now take the chunk as
unknown and cast at the use site; tar-stream emits Buffers at runtime,
so the emitted JavaScript is unchanged.

The Node.js v26.8.0 binaries on nodejs.org were built with a bogus
version string and self-report as 26.8.0-alpha.0.0.0 (Node.js shipped
26.8.1 the next day to correct it). That prerelease-looking version made
cspell's engine guard reject the runtime during lint and made node-gyp
request a nonexistent v26.8.0-alpha.0.0.0 headers tarball for native
builds. The pinned runtime is bumped to 26.8.1 in the root devEngines,
the compile-only script, the CI test matrix, and the benchmark and
release workflows.
2026-08-27 00:49:41 +02:00
Zoltan Kochanandgithub-actions[bot] 2bd58ac4d4 chore: update dependencies, Node.js, pnpm, and GitHub Actions (#14205)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-27 00:16:37 +02:00
Zoltan Kochanandgithub-actions[bot] 07527caf1c chore: update dependencies, Node.js, pnpm, and GitHub Actions (#14122)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-08-25 14:06:01 +02:00
Zoltan Kochan b4d19c87a1 fix(release): count only installer processes this step started (#14145)
The check that separates a rejected modify command line from an install
that ran and skipped a component watched for any Visual Studio installer
process by name. One already running for an unrelated reason would pass
for the one this step launches, putting the run back on the generic
"clang-cl was not installed" error it is meant to sharpen.

Snapshot the matching process ids before the launch and count only ones
that appear afterwards.
2026-08-25 02:23:09 +02:00
Zoltan Kochan 6098ce7a74 fix(release): drop the unsupported --wait from the Visual Studio installer call (#14144)
The 12.0.0-rc.11 release failed on both win32-arm64 legs with "clang-cl
was not installed under ...\VC\Tools\Llvm", five minutes after the
Visual Studio installer was asked to add the LLVM and ARM64 components.

`--wait` had been added to that `setup.exe modify` call. Microsoft
documents it as bootstrapper-only: "The --wait parameter can only be
passed into the bootstrapper; the installer (setup.exe) doesn't support
it." We invoke the installer at
`C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe`, so
it rejected the command line and installed nothing. The logs show the
call returning in under a second and no installer process alive for the
whole polling window.

The exit-code check could not catch that. `setup.exe` is a
GUI-subsystem binary, so PowerShell's call operator does not wait for it
and never sets $LASTEXITCODE from it — the value tested was still
vswhere's. Check vswhere's own result instead, where the variable
actually means something, and leave the poll loop as the sole
confirmation that the components landed, which is what it was written
for.

Regressed in pnpm/pnpm#14138; the split into separate CLI and NAPI
matrices is unaffected, it only doubled the number of legs running the
step.
2026-08-25 00:46:28 +02:00
Zoltan Kochan 05129e1fd2 perf(release): build the NAPI addon on its own runners (#14138)
The Rust release built the CLI binary and the NAPI addon back to back in
one matrix leg per target. The two are compiled under different Cargo
profiles — `release` for the CLI, `napi-release` for the addon, which
must keep `panic = "unwind"` so a panic reaching the FFI boundary becomes
a JS exception instead of aborting the host node process. Different
profile means a different target directory, so the two builds shared not
one compiled dependency: every leg paid for the whole graph twice, in
series.

Split the addon into its own `build-rust-napi` matrix over the same eight
targets. Measured on the 12.0.0-rc.9 release run, per-leg build time was:

  target             CLI     addon    leg
  win32-arm64        508s    369s     17m09s
  win32-x64          495s    363s     15m06s
  darwin-arm64       477s    241s     12m30s
  darwin-x64         461s    235s     12m10s
  linux-*        322-351s  217-238s   ~10m

The stage is bounded by its slowest leg, so dropping the addon out of
win32-arm64 takes the critical path from ~17 to ~11 minutes and the whole
release run from ~25m30s to roughly 19 minutes. The addon legs run
alongside and gate nothing.

Downstream needs no changes: the new job uploads to
`binaries-rust-napi-<code-target>`, which the `binaries-rust-*` download
pattern the verify, publish and draft-release jobs already use picks up
and merges into the same directory. It is also free of the node-gyp
payload dependency, since only the CLI archives ship `dist/`.

The toolchain prelude the two jobs share — installing cross, the
clang-cl/ARM64 Visual Studio components, the rustup target, and the guard
that the committed PNPM_VERSION matches the tag — moves into a
`rust-release-target` composite action rather than being duplicated.
zizmor flags that action's writes to GITHUB_ENV/GITHUB_PATH because a
composite action cannot see who calls it; the values come from the
Visual Studio install and `vcvarsall`, and the only caller is a release
job running on a maintainer-signed tag, so the audit is suppressed on
that step with that justification.
2026-08-24 21:16:43 +02:00