[pull] main from pnpm:main#266
Merged
Merged
Conversation
* feat(pacquet/config): port --recursive and --workspace-concurrency settings Mirror pnpm's `workspaceConcurrency` (a `.npmrc` / `pnpm-workspace.yaml` / `PNPM_CONFIG_WORKSPACE_CONCURRENCY` config-file key, default `getDefaultWorkspaceConcurrency()`, resolved through `getWorkspaceConcurrency`) and CLI-only `recursive` (`-r`) boolean. - Add `Config::workspace_concurrency` (resolved via the existing `resolve_child_concurrency` port of `getWorkspaceConcurrency`) and `Config::recursive`, plus `default_workspace_concurrency`. - Read `workspaceConcurrency` from workspace yaml, global config.yaml, and the `PNPM_CONFIG_*` env overlay; resolve negative offsets the same way `childConcurrency` does. - Add the `--workspace-concurrency` install flag (overrides the config-resolved value) and the global `-r` / `--recursive` flag (sets `Config::recursive`, matching pnpm's CLI-only nature). `workspaceConcurrency` is parsed and stored for config-surface parity; pacquet's frozen install materializes the whole workspace in one shared pass, so there is no per-project parallel loop for it to throttle yet (same posture as `preferOffline`). `recursive` is likewise a surface flag on install today, since install already spans the workspace. * docs(pacquet/config): drop private intra-doc link to fix Doc CI `default_workspace_concurrency`'s public doc linked the crate-private `default_child_concurrency`, which `rustdoc -D rustdoc::private-intra-doc-links` (implied by `-D warnings`) rejects. Use plain backticks instead. * style(pacquet/cli): drop redundant comment on workspace_concurrency destructure bind The sibling `offline: _` / `prefer_offline: _` binds carry no comment; match them for consistency. * test(pacquet/cli): cover the --workspace-concurrency override resolution The inline `if let Some(value) = args.workspace_concurrency` override body was only reachable when install ran *with* the flag, so the flag-absent integration runs left it uncovered. Extract the resolution into `InstallArgs::resolve_workspace_concurrency` and apply it unconditionally at the dispatch (matching upstream's final `getWorkspaceConcurrency` pass), so the substantive logic is covered by fast unit tests (absent / positive / negative) and the call site is an unconditional assignment the existing install tests already exercise. * style(pacquet/cli): pipe-trait the workspace-concurrency test parse calls Per review: rewrite the `InstallArgsHarness::try_parse_from([...])` calls in the new workspace-concurrency tests as `[...].pipe(InstallArgsHarness::try_parse_from)` so they read left-to-right, matching the codebase's pipe-trait convention. * docs(pacquet/config): drop inaccurate .npmrc source from workspaceConcurrency docs workspace_concurrency is populated only from pnpm-workspace.yaml, global config.yaml, and the PNPM_CONFIG_WORKSPACE_CONCURRENCY env overlay. Config::current reads .npmrc but applies only the auth/network subset, so a workspace-concurrency= entry in .npmrc never reaches the field. Align the doc comments and PR summary with actual behavior, matching the sibling childConcurrency docs. --------- Co-authored-by: Claude <noreply@anthropic.com>
…1964) The e2e/integration test harness spawns `pnpm-registry` as a faster verdaccio replacement. CI used to install Rust and build the crate from source on every test job — adding several minutes per platform. `@pnpm/pnpr` now publishes the prebuilt binary to npm, and `pnpm install` already pulls in the matching `@pnpm/pnpr.<platform>-<arch>` package via optionalDependencies. The Jest globalSetup resolves that binary through `@pnpm/pnpr/bin/pnpr`'s own module path (the wrapper carries the platform packages as siblings in its `node_modules`, not on the parent chain of this file). - Add `@pnpm/pnpr` to `pnpm-workspace.yaml` catalog and depend on it from `@pnpm/jest-config`. - Replace `resolvePnpmRegistryBin`'s `$CARGO_TARGET_DIR` lookup with `require.resolve` through the npm-installed wrapper. The `PNPM_REGISTRY_BIN` env var is still honored as an escape hatch for contributors who want to point at a locally-built Rust binary. - Remove the "Install Rust toolchain" + "Build pnpm-registry" steps from `.github/workflows/test.yml`. --- Written by an agent (Claude Code, claude-opus-4-7).
trailofbits/dylint 6.0.1 (published 2026-05-26 17:51 UTC) ships
prebuilt cargo-binstall artifacts that bake in a path from the
dylint repo's own CI workspace:
error: failed to get `dylint_driver` as a dependency of package
`dylint_driver-nightly-2026-04-16-x86_64-unknown-linux-gnu`
Caused by:
failed to read `/home/runner/work/dylint/dylint/driver/Cargo.toml`
Caused by:
No such file or directory (os error 2)
Downstream runners don't have that workspace, so the driver bootstrap
fails before any lint runs and the Dylint job goes red on every PR.
6.0.0 (the version main was passing with 90 minutes earlier) is
unaffected. Pin both binaries until upstream cuts 6.0.2.
---
Written by an agent (Claude Code, claude-opus-4-7).
…11967) `fetching/git-fetcher/src/index.ts` passed the lockfile-controlled `resolution.commit` value straight to `git fetch --depth 1 origin <commit>` and `git checkout <commit>` with no `--` separator and no format validation. A malicious `pnpm-lock.yaml` could put a value such as `--upload-pack=touch /tmp/pwned` in `resolution.commit`; `git` parses anything starting with `-` as an option, and on SSH or local-file transports `--upload-pack` runs the supplied command as the user running `pnpm install`. HTTPS ignores `--upload-pack`, but the SSH/file paths are enough to reach code execution. The fix validates `resolution.commit` against `/^[0-9a-f]{40}$/i` at the entry of the fetcher and throws `INVALID_GIT_COMMIT` otherwise. This is strictly stronger than adding a `--` separator — a validated value cannot start with `-` or contain shell-significant characters at all. Pacquet's `pacquet-git-fetcher` crate shells out to `git` along the same code path (`pacquet/crates/git-fetcher/src/fetcher.rs`) and had the identical issue. Ported the same check there, with a new `GitFetcherError::InvalidCommit` variant carrying the `INVALID_GIT_COMMIT` diagnostic code. Reported by [AutoFyn](https://github.com/SignalPilot-Labs/AutoFyn).
* fix(lockfile.utils): require integrity for tarball-shaped lockfile resolutions A tampered lockfile that strips the `integrity` field from a tarball resolution let the worker download the URL contents and mint a fresh integrity from the unverified bytes, so an attacker who could also serve content at the referenced URL would install a tampered package without any error — including under `--frozen-lockfile`. pnpm now rejects such entries at lockfile-read time with `ERR_PNPM_MISSING_TARBALL_INTEGRITY`, matching pacquet's existing `pacquet_package_manager::missing_tarball_integrity` guard. * test(lockfile.utils): drop redundant integrity-less snapshot that fails strict typecheck * test(pacquet/package-manager): cover MissingTarballIntegrity rejection in snapshot_cache_key Match the upstream guard landed alongside #11966 (`lockfile/utils/src/pkgSnapshotToResolution.ts`) with a test on the pacquet side: a `LockfileResolution::Tarball` with `integrity: None` — what a tampered lockfile looks like — must short-circuit the warm-batch cache-key derivation by surfacing `InstallPackageBySnapshotError::MissingTarballIntegrity`. The structural guard already existed but had no negative test. * fix(lockfile.utils): exempt git-hosted and file: tarballs from the integrity guard The strict guard added in the parent commit broke pnpm's own `with-git-protocol-dep` and `with-non-package-dep` fixtures: the install pipeline writes git-hosted tarball entries (codeload.github.com URLs) to the lockfile without an `integrity:` line, because the commit SHA in the URL is the integrity anchor — git's content-addressed model binds the bytes to the commit, so a separate hash adds nothing. Exempt git-hosted tarballs (detected either via the `gitHosted: true` flag or a URL on the known git hosts, matching the URL fallback in `toLockfileResolution`) and `file:` tarballs (local paths the user already controls). The strict check still fires for any other remote tarball — which is where the AutoFyn-reported vector actually manifests. Also export `isGitHostedTarballUrl` from `toLockfileResolution.ts` so the URL fallback can be shared rather than duplicated. * test(pacquet/package-manager): trim doc comment to the contract-level intent Per the repo convention that tests are documentation, the test name and body already cover what's being asserted; the prior comment duplicated that. Keep only the non-obvious why: why this guard exists at the cache-key site at all (warm-batch short-circuit) when the install-side check also rejects the same input.
Reshape pnpm-registry's Config to match verdaccio's `config.yaml` schema (storage, uplinks, packages) so the same file can drive either server. The previous Config exposed a single `upstream: Option<String>` resolved at startup; this replaces it with named uplinks plus per-package `proxy:` rules walked in declared order — same semantics as verdaccio, minus the surface pnpm-registry does not implement (auth, web, plugins, middlewares, logs routing, secret), which are accepted and ignored.
Highlights:
* `Config { listen, public_url, storage, uplinks, packages, packument_ttl }` with `UplinkConfig { url }` and `PackageAccess { access, publish, unpublish, proxy }`. `packages` is an `IndexMap` walked in declared order, first-match-wins: the first pattern matching a request is the rule that applies, and if that rule has no `proxy:` the package is storage-only (resolution returns `None` instead of falling through to a later catch-all). That makes the bundled `@private/*` / `@pnpm.e2e/needs-auth` / unscoped-fixture rules behave the way the YAML says they should.
* `Config::from_yaml(path, ...)` loads via `serde-saphyr` and resolves a relative `storage:` against the config file's parent. The verdaccio-only sections in the YAML are skipped silently so `registry-mock`'s upstream `config.yaml` parses untouched.
* `DEFAULT_CONFIG_YAML` — the bundled file mirrored from `@pnpm/registry-mock` — is `include_str!`-ed and re-exported from `lib.rs` so other crates (tests, benchmarks, future embedders) can use the same defaults without reading from disk. `Config::from_default_yaml(base_dir, ...)` parses it.
* CLI: `-c` / `--config <path>` overrides the bundled default. `--storage` survives as a runtime override (handy for tests without a custom YAML); `--upstream` and `--static` are gone because the YAML now drives both. `--packument-ttl-secs` is optional — the loaded config's value wins when the flag is not supplied. The mock orchestrator at `pacquet/tasks/registry-mock` drops its `--upstream` flag — that command spawns the locally-built binary so it tracks this PR's source directly. The jest harness at `__utils__/jest-config/with-registry/globalSetup.js` keeps `--upstream` for now because CI installs `@pnpm/pnpr` from npm; the flag will be dropped in the same PR that bumps `@pnpm/pnpr` to a build that lacks it.
* `server.rs` pre-builds one `Upstream` per declared uplink at router construction (keyed by name, in an `IndexMap`) and resolves the right client per request via `Config::resolve_uplink`. No per-request `ThrottledClient` allocations.
Existing tests are kept working by retaining the `Config::proxy` / `Config::static_serve` constructors and switching the test helper from `config.upstream = ...` to mutating
`config.uplinks["npmjs"].url`. All 107 tests in `pnpm-registry` pass (55 unit + 26 + 9 + 17 integration).
<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit
* **New Features**
* YAML-based registry configuration with package-level routing, multiple uplinks, auth and audit middleware
* New --config option to load custom registry configs; optional storage override and packument TTL setting
* **Chores**
* Default registry now uses the bundled configuration (web UI disabled by default)
* Configuration refactor to support Verdaccio-style routing patterns and per-package access/publish rules
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Zoltan Kochan <z@kochan.io>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )