Passer au contenu principal

pnpm 11.15-11.19

· 10 mins à lire
Zoltan Kochan
Lead maintainer of pnpm

pnpm 11.15 through 11.19 teach pnpm update and pnpm outdated to update GitHub Actions, let pnpm update write changesets for the bumps it makes, introduce cleaner update and audit settings sections, add publishConfig.name for publishing a package under a different name, harden pnpm self-update against project-supplied configuration, make web-based login work without a TTY, and accept = as a save-prefix. They also cut peak resolution memory by several times on large workspaces and speed up repeat installs after compatible dependency changes.

Minor Changes

Updating GitHub Actions

pnpm outdated and pnpm update can now check and update the GitHub Actions referenced by your repository's workflow files. The check is opt-in for every command: pass --include-github-actions, or set update.githubActions to true in pnpm-workspace.yaml to enable it by default. Updated actions are pinned to exact commit hashes, with their release tags preserved in comments:

- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0

Actions whose refs cannot be read — for example, an action in a private repository — are skipped with a warning instead of failing the command. For actions hosted on a GitHub Enterprise Server, the new update.githubActionsServer setting (or the GITHUB_SERVER_URL environment variable) sets the base URL of the GitHub server (#13220).

See Updating GitHub Actions.

Changesets from pnpm update

pnpm update gained a --changeset flag (update.changeset enables it by default; --no-changeset overrides the setting for one run). After the update completes, pnpm writes a .changeset/pnpm-update-<suffix>.md file declaring a patch bump for every workspace package whose dependencies or optionalDependencies were changed by the update and a major bump when peerDependencies changed, including packages that consume an updated catalog entry via the catalog: protocol. Private packages, packages without a name, and packages listed in the ignore array of .changeset/config.json are skipped.

New update and audit settings sections

pnpm-workspace.yaml now has update and audit settings sections, superseding the awkwardly named updateConfig, auditConfig, and top-level auditLevel settings:

update:
ignoreDeps: # was updateConfig.ignoreDependencies
- webpack
- "@babel/*"

audit:
level: high # was auditLevel
ignore: # was auditConfig.ignoreGhsas
- GHSA-xxxx-yyyy-zzzz

The deprecated settings keep working until the next major version. When both a new section value and its deprecated counterpart are set, the new section takes precedence and a warning is printed.

publishConfig.name

publishConfig.name publishes a package under a different name than the one its manifest carries in the workspace (#13345). It is for a project whose published name is already taken by a sibling project, which otherwise has to be renamed by a build step just before publishing. Only the published artifact is renamed — dependents, pnpm-lock.yaml, and release tooling keep addressing the project by its manifest name — and the new name reaches the packed manifest, the tarball filename, and everything that addresses the package at the registry.

pnpm self-update ignores project settings

pnpm self-update no longer takes any instruction from the project it is run in:

  • pnpm is fetched through the same trusted registry and auth configuration used when switching pnpm versions, so a project .npmrc or pnpm-workspace.yaml can no longer redirect the download or attach credentials to it, and the project's default .pnpmfile.(c|m)js is no longer loaded.
  • The project's minimumReleaseAge, trustPolicy, and ci settings no longer affect self-update. They still govern the project's own dependencies; for self-update these values come from the built-in default, your global config, a PNPM_CONFIG_* environment variable, or a command-line flag. This fixes self-update failing inside a workspace that raises the release-age cutoff, and stops a repository from either waiving the cooldown or keeping you on an outdated pnpm by raising it.

When self-update refuses a version that is younger than the cutoff, an interactive run now offers to update anyway; non-interactive runs still fail, and CI never prompts.

Web-based login without a TTY

pnpm login no longer requires an interactive terminal when the registry supports web-based login: without a TTY it prints the authentication URL (skipping the QR code and the "Press ENTER to open the URL in your browser" prompt) and polls the registry until the browser approval completes. Only the classic username/password login still fails with ERR_PNPM_LOGIN_NON_INTERACTIVE in a non-interactive terminal.

save-prefix accepts =

The savePrefix setting now accepts =: newly added dependencies are saved with an explicit = operator (=1.2.3) instead of the setting being silently treated as the default ^. pnpm update also keeps the explicit = operator of an exact version pin: a dependency saved as =3.5.1 now updates to =3.5.2 instead of the bare 3.5.2.

Other minor changes

  • The first release of a package now publishes the version written in its manifest verbatim, instead of bumping off it. A newly added package seeded at 1100.0.0 with a minor changeset is published as 1100.0.0 rather than skipping straight to 1100.1.0.
  • pnpm setup now appends PNPM_HOME and the global bin directory to the GitHub Actions environment files (GITHUB_ENV and GITHUB_PATH), so later steps in the same job can run pnpm add --global and other global commands (#9191).
  • allowBuilds entries can now approve git-hosted packages that pnpm downloads as a tarball, such as github: dependencies, by their repository URL without the resolved commit hash — matching the hashless git+ matching already supported for cloned git dependencies. GitLab and Bitbucket tarball downloads are matched the same way.
  • Optional peer dependencies declared only via peerDependenciesMeta (for example debug's supports-color peer) are now resolved from a satisfying version already present in the dependency graph, the same way explicitly declared optional peer dependencies are. Previously an unrelated dependency change could rewrite such peer resolutions across the whole lockfile.
  • Fixed an installed optional dependency being left without one of its own required dependencies, which made importing the parent fail with MODULE_NOT_FOUND. A dependency is now only skipped when every path to it is optional, or when the package that pulls it in was itself skipped (#13286).

Security

  • The token poll for web-based authentication no longer reads the body of non-OK or still-pending responses, and caps the token response body it does read at 64 KiB, so a malicious or compromised registry cannot exhaust memory through the poll (#12721).
  • Updated adm-zip to prevent crafted ZIP archives from causing excessive memory allocation.

Patch Changes

  • Fixed pnpm install running out of memory while resolving large dependency graphs (#8441). Registry documents kept in memory during resolution are now condensed down to the fields installation actually reads, which reduces peak resolution memory by several times on workspaces with more than a thousand packages.
  • Sped up installs after compatible catalog or direct dependency range changes by retaining the locked version without resolving the dependency graph again, and after safe overrides changes by reusing unambiguous compatible resolutions instead of running a full lockfile resolution.
  • pnpm install now detects a supportedArchitectures change and re-evaluates previously skipped platform-specific optional dependencies, instead of reporting the project as up to date.
  • overrides now also govern peers that pnpm auto-installs, so an auto-installed peer can no longer bring in a second copy of the very package an override pinned (#13320).
  • An auto-installed optional peer is no longer hoisted at a version the workspace root's own dependency on that package excludes (#13320), and under resolvePeersFromWorkspaceRoot, a root dependency declared with link:, file:, or a path form of workspace: now satisfies another project's missing peer at the linked package's own version instead of being hoisted as a broken path (#13373).
  • The root project's pnpm:devPreinstall script runs before resolution and linking again, as it did in pnpm 11.12 and earlier, so workspaces that use the hook to prepare state the install depends on are no longer linked against files that were never created (#13313).
  • Installs through a pnpr server now apply the project's whole verification policy (minimumReleaseAgeExclude, trustPolicy*, trustLockfile), honor --frozen-lockfile, resolve catalog: references in dependencies and overrides, and no longer crash in workspaces with minimumReleaseAge active (#13275, #13232).
  • Prevented minimumReleaseAge from replacing latest with a SemVer-greater version than the registry tag target (#13034), and the install summary no longer prints (X is available) when the registry's latest tag is still held back by the policy (#11698).
  • Local directory dependencies (file: directories and injected workspace packages) now get a global-virtual-store slot of their own per project, instead of sharing one slot across every project that depends on a directory of the same name (#13335). Failed builds of scoped packages under enableGlobalVirtualStore are also cleaned up correctly.
  • Preserved a workspace dependency's link: entry when a run does not target it — e.g. pnpm update <other-pkg> or a plain install after a root/catalog dependency change — with injectWorkspacePackages, instead of spuriously rewriting it to a peer-suffixed file: protocol (#10433).
  • Workspace dependencies declared with a relative path (e.g. "foo": "workspace:../foo") are no longer silently dropped from the workspace projects graph, so --filter selection and the topological order of recursive commands take them into account.
  • pnpm update --workspace no longer links dependencies the user never named: registry-only dependencies listed in update.ignoreDeps keep their specifiers, and selectors that match no direct dependency no longer fall back to linking every workspace dependency.
  • pnpm update --interactive now measures its table in terminal columns rather than characters, so wide characters (CJK, most emoji) no longer break the layout or abort the command (#13357). Its Workspace column also names every project a shared update applies to and falls back to a project's path when it has no usable name.
  • Fixed pnpm add --save-exact/--save-prefix and pnpm update writing a package's version with the peerDependencies range's prefix whenever the same package also appeared in peerDependencies (#13108).
  • Fixed pnpm licenses list to report every version when the same package is installed under multiple aliases (#13438).
  • Fixed pnpm login, pnpm adduser, and pnpm logout against a registry hosted under a URL subpath when the configured URL has no trailing slash.
  • When the authentication URL cannot be rendered as a QR code, web-based login now displays the URL alone with a warning instead of aborting.
  • pnpm setup now removes leftover v10-layout shims at the top of PNPM_HOME, so pnpm self-update no longer warns about a v10 installation layout after PATH has been migrated (#12496).
  • The pnpm version command now supports the from-git argument, and pnpm version -r no longer writes a versioning-ledger entry the next run fails to read when a release consumed no intents.
  • Fixed pnpm dedupe updating valid catalog resolutions when another matching version exists in the lockfile, prevented pnpm dedupe --check from removing an incompatible node_modules directory, and sorted its snapshot output for stable diffs.
  • pnpm -r run "/pattern/" --no-bail no longer exits zero when one of a project's matched scripts fails and a later one passes.
  • Fixed empty bundledDependencies arrays causing nondeterministic lockfile changes (#13123).
  • Restored the store block a first install prints, naming how packages were materialized and where the stores live (#13315).
  • Stripped Unicode formatting characters from registry- and manifest-derived terminal output.