From 1674d528932eb9db570ef8b93ec755a4e18874ce Mon Sep 17 00:00:00 2001 From: "Craig Macomber (Microsoft)" <42876482+CraigMacomber@users.noreply.github.com> Date: Wed, 13 May 2026 18:50:02 +0000 Subject: [PATCH 01/11] Update root workspace to pnpm 11 --- .npmrc | 15 --- package.json | 101 +-------------- .../compat-workspaces/full/package.json | 11 +- .../compat-workspaces/scripts/only-pnpm.cjs | 29 ----- .../tools/changelog-generator-wrapper/.npmrc | 6 - pnpm-workspace.yaml | 115 +++++++++++++++++- scripts/only-pnpm.cjs | 2 +- 7 files changed, 128 insertions(+), 151 deletions(-) delete mode 100644 .npmrc delete mode 100644 packages/test/test-version-utils/compat-workspaces/scripts/only-pnpm.cjs delete mode 100644 packages/tools/changelog-generator-wrapper/.npmrc diff --git a/.npmrc b/.npmrc deleted file mode 100644 index 7b53b06f3fc7..000000000000 --- a/.npmrc +++ /dev/null @@ -1,15 +0,0 @@ -engine-strict=true -frozen-lockfile=true -strict-peer-dependencies=true -link-workspace-packages=true - -# Disable pnpm update notifications since we use corepack to install package managers -update-notifier=false -# Use the number of cores on the machine by default. -workspace-concurrency=0 - -# Hoist these dependencies to the root workspace -public-hoist-pattern[]=@arethetypeswrong/cli -# ['*eslint*', '*prettier*'] is the default, so we add those as well -public-hoist-pattern[]=*eslint* -public-hoist-pattern[]=*prettier* diff --git a/package.json b/package.json index 5cb6eeedb2fa..0c9357043321 100644 --- a/package.json +++ b/package.json @@ -190,10 +190,12 @@ "type-fest": "^2.19.0", "typescript": "~5.4.5" }, - "packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319", - "engines": { - "node": ">=22.22.2", - "pnpm": "10" + "packageManager": "pnpm@11.1.1+sha512.d1fdf5f73c617b64fa1a56a81c3c8dfe0e966e33a6010aa256b517ae77be21d93e05affc0de1a83b0e4f29d569f68b446ae8f068cd7247c0bb3df0fb4d7bdf9a", + "devEngines": { + "runtime": { + "name": "node", + "version": ">=22.22.2" + } }, "fluidBuild": { "tasks": { @@ -349,96 +351,5 @@ "script": false } } - }, - "pnpm": { - "comments": [ - "biome is overridden to make review of the upgrade easier. This can be removed once merged.", - "node types are forced to a consistent version to avoid conflicts between globals.", - "nodegit is replaced with an empty package here because it's currently only used by good-fences for features we do not need, and has issues building when changing node versions. See https://github.com/smikula/good-fences/issues/105 for details. Note that using '-' to completely drop it, results in build failures complaining about nodegit not being there.", - "codemirror and marked overrides are because simplemde use * versions, and the fully up to date versions of its deps do not work. packageExtensions was tried to fix this, but did not work.", - "@fluentui/react-positioning's dependency on @floating-ui/dom causes a peer dependency violation, so overriding it forces a version that meets peer dependency requirements is installed.", - "oclif includes some AWS-related features, but we don't use them, so we drop those dependencies. This helps reduce lockfile churn since the deps release very frequently.", - "axios pre-1.0 needs an override to stay current on a version with no reported CVEs. Caret dependencies aren't enough on a pre-1.0 package.", - "Security overrides: tar is overridden to address path traversal CVEs (GHSA-8qq5-rm4j-mr97, GHSA-r6q2-hw4h-h46w, GHSA-34x7-hfp2-rc4v).", - "qs: overridden to ^6.15.0 to resolve a known vulnerability in older versions.", - "fast-xml-parser: overridden to ^4.5.4 to resolve multiple CVEs in 4.5.3 (entity encoding bypass, DoS via entity expansion, stack overflow). Stays within @langchain/anthropic's declared ^4.4.1 range.", - "systeminformation: overridden to ^5.31.0 to resolve command injection vulnerabilities.", - "simple-git: overridden to ^3.32.3 to resolve a CG alert.", - "diff: overridden to patched versions to resolve a known ReDoS vulnerability. diff@3.x and diff@7.x have no fix in their major range so they are bumped to the nearest patched major.", - "serialize-javascript: overridden to ^7.0.4 to resolve GHSA-5c6j-r48x-rmvq. No 6.x fix exists; 7.x is API-compatible (only drops Node <20 support).", - "express: overridden to ^4.22.1 to resolve a known vulnerability in express 4.21.2.", - "picomatch: overridden to patched versions to resolve a known security vulnerability.", - "node-forge: overridden to ^1.4.0 to resolve known security vulnerabilities.", - "langsmith: overridden to ^0.5.15 to resolve a known security vulnerability. The consumer declares ^0.3.x so the override is needed to cross the minor version boundary." - ], - "overrides": { - "@biomejs/biome": "~2.4.5", - "@types/node": "catalog:types", - "diff@>=3 <4": "^4.0.4", - "diff@>=5 <6": "^5.2.2", - "diff@>=7 <8": "^8.0.3", - "diff@>=8 <9": "^8.0.3", - "fast-xml-parser": "^4.5.4", - "node-forge": "^1.4.0", - "good-fences>nodegit": "npm:empty-npm-package@1.0.0", - "qs": "^6.15.0", - "simple-git": "^3.32.3", - "systeminformation": "^5.31.0", - "simplemde>codemirror": "^5.65.11", - "simplemde>marked": "^4.3.0", - "@fluentui/react-positioning>@floating-ui/dom": "~1.5.4", - "oclif>@aws-sdk/client-cloudfront": "-", - "oclif>@aws-sdk/client-s3": "-", - "axios@<0.30.0": "^0.30.0", - "tar": "^7.5.11", - "minimatch@>=3 <4": "^3.1.5", - "minimatch@>=5 <6": "^5.1.9", - "minimatch@>=6 <7": "^6.2.3", - "minimatch@>=7 <8": "^7.4.9", - "minimatch@>=8 <9": "^8.0.7", - "minimatch@>=9 <10": "^9.0.9", - "minimatch@>=10 <11": "^10.2.4", - "serialize-javascript@>=6 <7": "^7.0.4", - "express@>=4 <5": "^4.22.1", - "picomatch@>=2 <3": "^2.3.2", - "picomatch@>=4 <5": "^4.0.4", - "langsmith": "^0.5.15" - }, - "peerDependencyComments": [ - "The react-split-pane package used by devtools-view has a peer dependency on React 16, but it doesn't seem to be maintained and it works fine with React 18. TODO: AB#18876", - "@types/node is ignored because it is usually not needed by packages, and if it is, then the package will hit a compilation failure.", - "Peer dependencies on fluid-framework are never fulfilled since that's an in-repo dependency; we expect a customer using some packages to install it as a dependency.", - "markdown-magic is provided by another dependency so is ignored here.", - "oclif includes some AWS-related features, but we don't use them, so we ignore @aws-sdk peer dependencies." - ], - "peerDependencyRules": { - "allowedVersions": { - "react": "18.3.1", - "react-dom": "18.3.1" - }, - "ignoreMissing": [ - "@types/node", - "fluid-framework", - "markdown-magic", - "@aws-sdk/*" - ] - }, - "patchedDependencies": { - "@microsoft/api-extractor@7.58.1": "patches/@microsoft__api-extractor@7.58.1.patch" - }, - "onlyBuiltDependencies": [ - "@azure/msal-node-extensions", - "@azure/msal-node-runtime", - "@biomejs/biome", - "@parcel/watcher", - "@vvago/vale", - "classic-level", - "core-js", - "esbuild", - "keytar", - "msgpackr-extract", - "puppeteer", - "unrs-resolver" - ] } } diff --git a/packages/test/test-version-utils/compat-workspaces/full/package.json b/packages/test/test-version-utils/compat-workspaces/full/package.json index 7c8dd93cfba6..d623281a6180 100644 --- a/packages/test/test-version-utils/compat-workspaces/full/package.json +++ b/packages/test/test-version-utils/compat-workspaces/full/package.json @@ -10,7 +10,12 @@ }, "license": "MIT", "author": "Microsoft and contributors", - "scripts": { - "preinstall": "node ../scripts/only-pnpm.cjs" - } + "scripts": { + "preinstall": "node ../../../../../scripts/only-pnpm.cjs" + }, + "packageManager": "pnpm@11.1.1+sha512.d1fdf5f73c617b64fa1a56a81c3c8dfe0e966e33a6010aa256b517ae77be21d93e05affc0de1a83b0e4f29d569f68b446ae8f068cd7247c0bb3df0fb4d7bdf9a", + "engines": { + "node": ">=22.22.2", + "pnpm": "11" + } } diff --git a/packages/test/test-version-utils/compat-workspaces/scripts/only-pnpm.cjs b/packages/test/test-version-utils/compat-workspaces/scripts/only-pnpm.cjs deleted file mode 100644 index 91d351b71e3b..000000000000 --- a/packages/test/test-version-utils/compat-workspaces/scripts/only-pnpm.cjs +++ /dev/null @@ -1,29 +0,0 @@ -/*! - * Copyright (c) Microsoft Corporation and contributors. All rights reserved. - * Licensed under the MIT License. - */ - -/** - * This script is used to prompt users to use pnpm in a project. This helps guide new contributors to the right tools. - * To use this script in a project, add a "preinstall" script to the package.json that calls this script. - */ - -const message = ` -╔══════════════════════════════════════════════════════════════════╗ -║ ║ -║ Use "pnpm install" for installation in this project. ║ -║ ║ -║ If you don't have pnpm, enable corepack via "corepack enable". ║ -║ Then run "pnpm install" to install dependencies. ║ -║ ║ -║ For more details, see the README. ║ -║ ║ -╚══════════════════════════════════════════════════════════════════╝ -`; - -const used_pnpm = process.env.npm_config_user_agent.startsWith(`pnpm`); - -if (!used_pnpm) { - console.error(message); - process.exit(1); -} diff --git a/packages/tools/changelog-generator-wrapper/.npmrc b/packages/tools/changelog-generator-wrapper/.npmrc deleted file mode 100644 index ff7cd5deb92b..000000000000 --- a/packages/tools/changelog-generator-wrapper/.npmrc +++ /dev/null @@ -1,6 +0,0 @@ -engine-strict=true -frozen-lockfile=true -strict-peer-dependencies=true - -# Disable pnpm update notifications since we use corepack to install package managers -update-notifier=false diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index c4e0a6e37b7d..d4cc4754f636 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -67,8 +67,10 @@ trustPolicyExclude: # current 7.x line publishes through the npm-cli OIDC/Actions pipeline. The 5.x/6.x # lines will not be retroactively re-published with provenance. Pulled in by widely- # used legacy tooling that pins ^5 / ^6. - - "semver@5.7.2" - - "semver@6.3.1" + # Note: multiple versions of the same package must be combined with "||" — pnpm's + # trust-policy evaluator returns on the first name match and does not aggregate + # subsequent entries for the same package. + - "semver@5.7.2||6.3.1" # undici-types@6.21.0 (published 2024-11-13, by matteo.collina) — pipeline regression. # Prior trusted: undici-types@6.19.2 (provenance, 2024-06-18, by matteo.collina). # Same publisher (undici project lead). Type-only package (.d.ts shipped from undici @@ -90,3 +92,112 @@ catalogs: # Type definitions types: "@types/node": "~22.19.17" +overrides: + # biome is overridden to make review of the upgrade easier. This can be removed once merged. + '@biomejs/biome': ~2.4.5 + # node types are forced to a consistent version to avoid conflicts between globals. + '@types/node': catalog:types + # diff is overridden to patched versions to resolve a known ReDoS vulnerability. diff@3.x and diff@7.x + # have no fix in their major range so they are bumped to the nearest patched major. + diff@>=3 <4: ^4.0.4 + diff@>=5 <6: ^5.2.2 + diff@>=7 <8: ^8.0.3 + diff@>=8 <9: ^8.0.3 + # fast-xml-parser is overridden to ^4.5.4 to resolve multiple CVEs in 4.5.3 (entity encoding bypass, + # DoS via entity expansion, stack overflow). Stays within @langchain/anthropic's declared ^4.4.1 range. + fast-xml-parser: ^4.5.4 + # node-forge is overridden to ^1.4.0 to resolve known security vulnerabilities. + node-forge: ^1.4.0 + # nodegit is replaced with an empty package here because it's currently only used by good-fences for + # features we do not need, and has issues building when changing node versions. + # See https://github.com/smikula/good-fences/issues/105 for details. Note that using '-' to completely + # drop it results in build failures complaining about nodegit not being there. + good-fences>nodegit: npm:empty-npm-package@1.0.0 + # qs is overridden to ^6.15.0 to resolve a known vulnerability in older versions. + qs: ^6.15.0 + # simple-git is overridden to ^3.32.3 to resolve a CG alert. + simple-git: ^3.32.3 + # systeminformation is overridden to ^5.31.0 to resolve command injection vulnerabilities. + systeminformation: ^5.31.0 + # codemirror and marked overrides are because simplemde uses * versions, and the fully up-to-date + # versions of its deps do not work. packageExtensions was tried to fix this, but did not work. + simplemde>codemirror: ^5.65.11 + simplemde>marked: ^4.3.0 + # @fluentui/react-positioning's dependency on @floating-ui/dom causes a peer dependency violation, + # so overriding it forces a version that meets peer dependency requirements to be installed. + '@fluentui/react-positioning>@floating-ui/dom': ~1.5.4 + # oclif includes some AWS-related features, but we don't use them, so we drop those dependencies. + # This helps reduce lockfile churn since the deps release very frequently. + oclif>@aws-sdk/client-cloudfront: '-' + oclif>@aws-sdk/client-s3: '-' + # axios pre-1.0 needs an override to stay current on a version with no reported CVEs. + # Caret dependencies aren't enough on a pre-1.0 package. + axios@<0.30.0: ^0.30.0 + # tar is overridden to address path traversal CVEs (GHSA-8qq5-rm4j-mr97, GHSA-r6q2-hw4h-h46w, + # GHSA-34x7-hfp2-rc4v). + tar: ^7.5.11 + minimatch@>=3 <4: ^3.1.5 + minimatch@>=5 <6: ^5.1.9 + minimatch@>=6 <7: ^6.2.3 + minimatch@>=7 <8: ^7.4.9 + minimatch@>=8 <9: ^8.0.7 + minimatch@>=9 <10: ^9.0.9 + minimatch@>=10 <11: ^10.2.4 + # serialize-javascript is overridden to ^7.0.4 to resolve GHSA-5c6j-r48x-rmvq. + # No 6.x fix exists; 7.x is API-compatible (only drops Node <20 support). + serialize-javascript@>=6 <7: ^7.0.4 + # express is overridden to ^4.22.1 to resolve a known vulnerability in express 4.21.2. + express@>=4 <5: ^4.22.1 + # picomatch is overridden to patched versions to resolve a known security vulnerability. + picomatch@>=2 <3: ^2.3.2 + picomatch@>=4 <5: ^4.0.4 + # langsmith is overridden to ^0.5.15 to resolve a known security vulnerability. + # The consumer declares ^0.3.x so the override is needed to cross the minor version boundary. + langsmith: ^0.5.15 +peerDependencyRules: + # The react-split-pane package used by devtools-view has a peer dependency on React 16, but it doesn't + # seem to be maintained and it works fine with React 18. TODO: AB#18876 + allowedVersions: + react: 18.3.1 + react-dom: 18.3.1 + ignoreMissing: + # @types/node is ignored because it is usually not needed by packages, and if it is, then the + # package will hit a compilation failure. + - '@types/node' + # Peer dependencies on fluid-framework are never fulfilled since that's an in-repo dependency; + # we expect a customer using some packages to install it as a dependency. + - fluid-framework + # markdown-magic is provided by another dependency so is ignored here. + - markdown-magic + # oclif includes some AWS-related features, but we don't use them, so we ignore @aws-sdk peer + # dependencies. + - '@aws-sdk/*' +patchedDependencies: + '@microsoft/api-extractor@7.58.1': patches/@microsoft__api-extractor@7.58.1.patch +# engineStrict: true +frozenLockfile: true +strictPeerDependencies: true +linkWorkspacePackages: true +# Disable pnpm update notifications since we use corepack to install package managers +updateNotifier: false +# Use the number of cores on the machine by default. +workspaceConcurrency: 0 +# Hoist these dependencies to the root workspace +publicHoistPattern: + - '@arethetypeswrong/cli' + # ['*eslint*', '*prettier*'] is the default, so we add those as well + - '*eslint*' + - '*prettier*' +allowBuilds: + '@azure/msal-node-extensions': true + '@azure/msal-node-runtime': true + '@biomejs/biome': true + '@parcel/watcher': true + '@vvago/vale': true + classic-level: true + core-js: true + esbuild: true + keytar: true + msgpackr-extract: true + puppeteer: true + unrs-resolver: true diff --git a/scripts/only-pnpm.cjs b/scripts/only-pnpm.cjs index 91d351b71e3b..5544c6646283 100644 --- a/scripts/only-pnpm.cjs +++ b/scripts/only-pnpm.cjs @@ -21,7 +21,7 @@ const message = ` ╚══════════════════════════════════════════════════════════════════╝ `; -const used_pnpm = process.env.npm_config_user_agent.startsWith(`pnpm`); +const used_pnpm = (process.env.npm_execpath ?? "").includes(`pnpm`); if (!used_pnpm) { console.error(message); From ed9dc4b7c42ee33b659dda3c2fc950ca92d83d51 Mon Sep 17 00:00:00 2001 From: "Craig Macomber (Microsoft)" <42876482+CraigMacomber@users.noreply.github.com> Date: Wed, 13 May 2026 20:11:12 +0000 Subject: [PATCH 02/11] Remove pipeline override of workspace-concurrency 0 since we already set that in the workspace. --- tools/pipelines/build-performance-observability.yml | 1 - tools/pipelines/templates/include-install-pnpm.yml | 2 -- 2 files changed, 3 deletions(-) diff --git a/tools/pipelines/build-performance-observability.yml b/tools/pipelines/build-performance-observability.yml index dc3177e44ca8..e2d9f70ad449 100644 --- a/tools/pipelines/build-performance-observability.yml +++ b/tools/pipelines/build-performance-observability.yml @@ -134,7 +134,6 @@ extends: # Point all npm/pnpm commands at the authenticated .npmrc echo "##vso[task.setvariable variable=NPM_CONFIG_USERCONFIG]$(Pipeline.Workspace)/${{ variables.FluidFrameworkDirectory }}/.npmrc" pnpm config set store-dir $(Pipeline.Workspace)/.pnpm-store - pnpm config set -g workspace-concurrency 0 pnpm config set registry "$(ado-feeds-primary-registry)" - task: Bash@3 diff --git a/tools/pipelines/templates/include-install-pnpm.yml b/tools/pipelines/templates/include-install-pnpm.yml index 6207eb48abe4..a1a28c546b34 100644 --- a/tools/pipelines/templates/include-install-pnpm.yml +++ b/tools/pipelines/templates/include-install-pnpm.yml @@ -70,7 +70,6 @@ steps: inputs: targetType: 'inline' workingDirectory: '$(Pipeline.Workspace)/${{ parameters.buildDirectory }}' - # workspace-concurrency 0 means use use the CPU core count. This is better than the default (4) for larger agents. script: | set -eu -o pipefail echo "Using node $(node --version)" @@ -82,7 +81,6 @@ steps: pnpm config set store-dir ${{ parameters.pnpmStorePath }} echo "Pnpm store: ${{ parameters.pnpmStorePath }}" echo "Primary registry: ${NPM_REGISTRY}" - pnpm config set -g workspace-concurrency 0 pnpm config set registry "${NPM_REGISTRY}" if [ ${NPM_REGISTRY} == "https://registry.npmjs.org/" ]; then echo "##vso[task.setvariable variable=registryType]public" From 59709f2774eb432cf54f1b2b144dc738074572ae Mon Sep 17 00:00:00 2001 From: "Craig Macomber (Microsoft)" <42876482+CraigMacomber@users.noreply.github.com> Date: Wed, 13 May 2026 21:11:38 +0000 Subject: [PATCH 03/11] Recreate npmrc --- .npmrc | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 .npmrc diff --git a/.npmrc b/.npmrc new file mode 100644 index 000000000000..c0755a388858 --- /dev/null +++ b/.npmrc @@ -0,0 +1,8 @@ +# This file is intentionally empty. +# +# Repository-wide pnpm configuration is consolidated in pnpm-workspace.yaml (the +# preferred location starting in pnpm 10). This file is kept so that: +# - settings that can only be expressed in .npmrc (e.g. registry auth tokens +# written by CI tooling) have a project-level target file, and +# - any future per-project options that don't have a pnpm-workspace.yaml +# equivalent have an obvious place to land. From 3fc244835446f2bf5bb0b6bcdda9af84d1a74e6e Mon Sep 17 00:00:00 2001 From: "Craig Macomber (Microsoft)" <42876482+CraigMacomber@users.noreply.github.com> Date: Wed, 13 May 2026 21:24:40 +0000 Subject: [PATCH 04/11] Fix missing npmrc file properly --- .npmrc | 8 -------- tools/pipelines/templates/include-install-pnpm.yml | 2 ++ 2 files changed, 2 insertions(+), 8 deletions(-) delete mode 100644 .npmrc diff --git a/.npmrc b/.npmrc deleted file mode 100644 index c0755a388858..000000000000 --- a/.npmrc +++ /dev/null @@ -1,8 +0,0 @@ -# This file is intentionally empty. -# -# Repository-wide pnpm configuration is consolidated in pnpm-workspace.yaml (the -# preferred location starting in pnpm 10). This file is kept so that: -# - settings that can only be expressed in .npmrc (e.g. registry auth tokens -# written by CI tooling) have a project-level target file, and -# - any future per-project options that don't have a pnpm-workspace.yaml -# equivalent have an obvious place to land. diff --git a/tools/pipelines/templates/include-install-pnpm.yml b/tools/pipelines/templates/include-install-pnpm.yml index a1a28c546b34..b37e92d57bea 100644 --- a/tools/pipelines/templates/include-install-pnpm.yml +++ b/tools/pipelines/templates/include-install-pnpm.yml @@ -77,6 +77,8 @@ steps: echo "Using pnpm $(pnpm -v)" # This ensures all subsequent tasks in this job will use the pnpm configuration set here. echo "##vso[task.setvariable variable=NPM_CONFIG_USERCONFIG]$NPM_CONFIG_USERCONFIG" + # Ensure the user .npmrc exists so the npmAuthenticate task can populate it. + touch "$NPM_CONFIG_USERCONFIG" echo "Pnpm user config location: $(pnpm config get userconfig)" pnpm config set store-dir ${{ parameters.pnpmStorePath }} echo "Pnpm store: ${{ parameters.pnpmStorePath }}" From 240715f30f0d865096c840e4e1d2262751c6d7b1 Mon Sep 17 00:00:00 2001 From: "Craig Macomber (Microsoft)" <42876482+CraigMacomber@users.noreply.github.com> Date: Wed, 13 May 2026 21:38:56 +0000 Subject: [PATCH 05/11] Disable verifyDepsBeforeRun --- pnpm-workspace.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index d4cc4754f636..55af935af2d2 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -182,6 +182,10 @@ linkWorkspacePackages: true updateNotifier: false # Use the number of cores on the machine by default. workspaceConcurrency: 0 +# pnpm 11 enabled this check by default, which runs a frozen-lockfile install before every `pnpm run