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>
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.
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.
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.
* chore: update dependencies, Node.js, pnpm, and GitHub Actions
* chore: hold typescript on 6.x for typescript-eslint compatibility
The update-lockfile job bumped the `typescript` catalog entry to 7.0.2,
which typescript-eslint refuses to load against — it hard-errors at load
with "typescript-eslint does not support TS 7.0" — failing the
Compile & Lint job.
The 7.x compiler is already used for the build via
`@typescript/native-preview` (tsgo); the `typescript` npm package only
serves the JS-API tooling (eslint, jest), which needs 6.x until
typescript-eslint adds TS >=7.1 support
(https://github.com/typescript-eslint/typescript-eslint/issues/10940).
Revert the catalog entry to 6.0.3 and add `typescript` to
`update.ignoreDeps` so the update-lockfile workflow stops re-bumping it.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* chore: drop the stray typescript@7.0.2 from the lockfile
openpgp declares an optional `typescript` peer (>=4.7). After the catalog
was reverted to 6.0.3, pnpm's incremental resolution kept openpgp latched
onto the leftover typescript@7.0.2 node, leaving it (and its native
platform packages) in the lockfile and tripping peer-mismatch review bots.
Re-point openpgp's optional peer to 6.0.3 so typescript@7.0.2 is gone
entirely; the openpgp subtree is now identical to the base branch.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Lands the pieces of the npm registry protocol that pnpm-registry was missing, and switches the TypeScript test harness off verdaccio onto pnpm-registry. `@pnpm/registry-mock` (the npm package) is untouched.
### Server-side additions (`registry/crates/pnpm-registry`)
- `PUT /-/user/org.couchdb.user:<name>` — adduser / login, returns a Bearer token. In-memory user + token stores.
- `PUT /:pkg` — publish (scoped + unscoped). Base64-decodes `_attachments`, merges into the existing packument, writes manifest + tarball atomically. 100 MiB body limit.
- `GET /-/package/:pkg/dist-tags` + `PUT/DELETE /-/package/:pkg/dist-tags/:tag` — rewrites the on-disk packument so tag changes survive a restart.
- `Authorization: Bearer` and `Authorization: Basic` both identify the caller.
- Per-package access policy (wax glob patterns). Defaults mirror `@pnpm/registry-mock`'s `config.yaml`: `@private/*` and `@pnpm.e2e/needs-auth` require auth; everything else is anonymous read, authenticated write. Enforced on every packument / version-manifest / tarball GET and every write endpoint.
### TypeScript-test migration
- `__utils__/jest-config/with-registry/globalSetup.js` keeps `prepare()` from `@pnpm/registry-mock` (still needed for the tempy storage path written into the runtime-config yaml — `getIntegrity` reads it from there) but spawns `pnpm-registry` instead of verdaccio. `addUser`, `addDistTag`, `getIntegrity`, `REGISTRY_MOCK_*` from registry-mock work as-is — they're plain npm-wire-protocol HTTP calls.
- Binary lookup follows pacquet's pattern: `PNPM_REGISTRY_BIN` env override, then `target/release/pnpm-registry`, then `target/debug/pnpm-registry`.
- CI test job (`.github/workflows/test.yml`) installs the Rust toolchain via the existing `./.github/actions/rustup` composite action and builds `pnpm-registry --release` before tests run. Per-platform — Linux and Windows in the matrix each build their own.
* ci(pacquet): fix all zizmor code-scanning findings
Resolves the 90 alerts opened by zizmor against the imported pacquet-*
workflows and shared composite actions:
- unpinned-uses: pin every third-party action to a SHA + version comment
(matching SHAs already used elsewhere in the repo where applicable;
taiki-e/install-action collapsed onto v2.78.0 with explicit `tool:` input).
- artipacked: add `persist-credentials: false` to every actions/checkout.
- template-injection: pass `inputs.*` and `steps.*.outputs.*` through `env:`
in binstall/rustup composite actions and pacquet-release-to-npm.yml.
- excessive-permissions: add top-level `permissions: contents: read` to
pacquet-release-to-npm.yml; move issues/pull-requests writes from the
workflow level to the benchmark-compare job in pacquet-micro-benchmark.yml.
- dangerous-triggers: keep workflow_run in pacquet-integrated-benchmark-
comment.yml but suppress with a documented zizmor: ignore — the trigger
is the recommended pattern for posting comments back to fork PRs.
- superfluous-actions: keep softprops/action-gh-release with a zizmor:
ignore (matches release.yml).
Verified by running `zizmor .github` locally with no remaining findings.
* ci(pacquet): point SHA pins at the patch-version tag
Swatinem/rust-cache and montudor/action-zip were pinned to the SHA the
major-version alias (`v2`, `v1`) resolves to, but the version comments
claimed `v2.9.1` / `v1.0.0`. zizmor's online `ref-version-mismatch`
audit flagged the inconsistency. Repoint at the SHAs the patch-version
tags actually annotate so the pin and the comment agree.
* chore(pacquet): wire pacquet workflows into monorepo
Move Cargo workspace, Rust toolchain configs, justfile, composite actions,
and 7 workflow files out of `pacquet/` and up to the repo root so:
- cargo / just / taplo run from repo root, the way the rest of the
monorepo's tooling does
- GitHub Actions actually discovers the workflows (it only reads
`.github/workflows/` at the repo root)
Workflows are prefixed with `pacquet-` and renamed to "Pacquet ..." so
they don't collide with the existing pnpm CI. Path filters are scoped
to `pacquet/**` so they don't trigger on every commit. The cargo entry
from pacquet's standalone `dependabot.yml` is folded into the root one;
pacquet's `CODEOWNERS` and `pull_request_template.md` are dropped because
the root copies supersede them.
Path rewrites:
- `Cargo.toml` workspace members → `pacquet/crates/*`, `pacquet/tasks/*`
- all path-deps in `[workspace.dependencies]` → `pacquet/...`
- `justfile` recipes (`install`, `install-hooks`) point at `pacquet/...`
- `.taplo.toml` include globs → `pacquet/crates/*/*.toml`, `pacquet/tasks/*/*.toml`
- `pacquet/npm/pacquet/scripts/generate-packages.mjs` REPO_ROOT walks one
more level up
- workflow `paths:` filters, `hashFiles(...)`, and shell paths all updated
Verified: `cargo metadata` resolves the workspace, `cargo fmt --check`
clean, `taplo format --check` picks up all 26 Cargo.tomls, `actionlint`
reports no new issues (the `type:`-on-input warnings on the rustup action
predate this move).
* chore(pacquet): drop pnpm version pin from pacquet CI workflows
The monorepo's root `package.json` declares `pnpm@11.1.1` under
`packageManager`, which conflicts with the workflows' explicit
`version: 11.0.0-rc.5` and trips `pnpm/action-setup` ERR_PNPM_BAD_PM_VERSION.
The pin was a pacquet-era workaround for the v9 lockfile while pnpm 11
was still pre-release. Stable 11.x writes v9 too, so let action-setup
read the version from `packageManager` like every other workflow in
this repo does.
* chore(pacquet): use pnpm/setup matching the rest of the monorepo
Replaces `pnpm/action-setup@v6` with the same `pnpm/setup@b1cac3...`
SHA the rest of pnpm/pnpm uses (release.yml, test.yml, ci.yml,
benchmark.yml, audit.yml). Reads pnpm version from `packageManager`
in root package.json, and skips the implicit `pnpm install` since
pacquet does its own scoped install via `just install` (which only
touches `pacquet/tasks/registry-mock/`).
The release workflow now also installs Node via the same action
(`runtime: node@22`) instead of via `pnpm runtime -g set node 22`,
since pnpm/setup handles runtimes in one step.
* chore(pacquet): tighten permissions and Dependabot cooldown
Address zizmor warnings on the pacquet CI changes:
- `dependabot.yml`: the cargo entry I added in the previous commit
inherited from pacquet's standalone repo and is missing the
`cooldown: default-days: 7` the github-actions entry uses. Add it
so cargo and github-actions debounce updates consistently.
- `pacquet-ci.yml`, `pacquet-codecov.yml`, `pacquet-cargo-unused.yml`
lacked a top-level `permissions:` block, so GITHUB_TOKEN inherited
the repo default. Declare `contents: read` — every job in these
workflows only reads the repo and runs local checks.
The other four pacquet workflows already declare permissions
explicitly (integrated-benchmark/comment, micro-benchmark, release).
* chore(pacquet): add "reimagining" to cspell dictionary
cspell at the repo root scans all `**/README.md` and was rejecting
`pacquet/README.md` and `pacquet/npm/pacquet/README.md`, which describe
pacquet as "not a reimagining of pnpm." Add the word to the existing
allow-list rather than rewording two READMEs imported from a separate
repo.
* fix(pacquet): prefix workspace-relative paths with pacquet/
Two Rust source files looked up paths off the cargo workspace root
(\`cargo locate-project --workspace\`), which now resolves to the
monorepo root rather than the pacquet directory. Add the \`pacquet/\`
prefix:
- \`tasks/registry-mock/src/dirs.rs\` — \`registry_mock()\` was
pointing the node launcher at \`<repo>/tasks/registry-mock/launch.mjs\`
instead of \`<repo>/pacquet/tasks/registry-mock/launch.mjs\`, which
failed every Pacquet CI test job ("Cannot find module ...launch.mjs").
- \`tasks/micro-benchmark/src/main.rs\` — same idea for the
fixtures folder.