Skip to content

Commit 1520027

Browse files
Copiloticlanton
andauthored
[rush] Add globalOnlyBuiltDependencies support for PNPM 10.x (#5522)
* Initial plan * Add globalOnlyBuiltDependencies support to PNPM configuration Co-authored-by: iclanton <5010588+iclanton@users.noreply.github.com> * Update snapshots and API review file for globalOnlyBuiltDependencies Co-authored-by: iclanton <5010588+iclanton@users.noreply.github.com> * Move onlyBuiltDependencies to package.json instead of pnpm-workspace.yaml Co-authored-by: iclanton <5010588+iclanton@users.noreply.github.com> * Update test snapshots for onlyBuiltDependencies warning Co-authored-by: iclanton <5010588+iclanton@users.noreply.github.com> * Add changelog entry for globalOnlyBuiltDependencies feature Co-authored-by: iclanton <5010588+iclanton@users.noreply.github.com> * Rush change. * Update test to use PNPM 10.1.0 to avoid hardcoded path in warning Co-authored-by: iclanton <5010588+iclanton@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: iclanton <5010588+iclanton@users.noreply.github.com> Co-authored-by: Ian Clanton-Thuon <iclanton@users.noreply.github.com>
1 parent b777094 commit 1520027

File tree

11 files changed

+103
-1
lines changed

11 files changed

+103
-1
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@microsoft/rush",
5+
"comment": "Add support for the `globalOnlyBuiltDependencies` PNPM 10.x option to specify an allowlist of packages permitted to run build scripts to `common/config/rush/pnpm-config.json`.",
6+
"type": "none"
7+
}
8+
],
9+
"packageName": "@microsoft/rush"
10+
}

common/reviews/api/rush-lib.api.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,7 @@ export interface _IPnpmOptionsJson extends IPackageManagerOptionsJsonBase {
743743
globalCatalogs?: Record<string, Record<string, string>>;
744744
globalIgnoredOptionalDependencies?: string[];
745745
globalNeverBuiltDependencies?: string[];
746+
globalOnlyBuiltDependencies?: string[];
746747
globalOverrides?: Record<string, string>;
747748
globalPackageExtensions?: Record<string, IPnpmPackageExtension>;
748749
globalPatchedDependencies?: Record<string, string>;
@@ -1155,6 +1156,7 @@ export class PnpmOptionsConfiguration extends PackageManagerOptionsConfiguration
11551156
readonly globalCatalogs: Record<string, Record<string, string>> | undefined;
11561157
readonly globalIgnoredOptionalDependencies: string[] | undefined;
11571158
readonly globalNeverBuiltDependencies: string[] | undefined;
1159+
readonly globalOnlyBuiltDependencies: string[] | undefined;
11581160
readonly globalOverrides: Record<string, string> | undefined;
11591161
readonly globalPackageExtensions: Record<string, IPnpmPackageExtension> | undefined;
11601162
get globalPatchedDependencies(): Record<string, string> | undefined;

libraries/rush-lib/assets/rush-init/common/config/rush/pnpm-config.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,31 @@
306306
/*[LINE "HYPOTHETICAL"]*/ "fsevents"
307307
],
308308

309+
/**
310+
* The `globalOnlyBuiltDependencies` setting specifies which dependencies are permitted to run
311+
* build scripts (`preinstall`, `install`, and `postinstall` lifecycle events). This is the inverse
312+
* of `globalNeverBuiltDependencies`. In PNPM 10.x, build scripts are disabled by default for
313+
* security, so this setting is required to explicitly permit specific packages to run their
314+
* build scripts. The settings are written to the `onlyBuiltDependencies` field of the
315+
* `pnpm-workspace.yaml` file that is generated by Rush during installation.
316+
*
317+
* (SUPPORTED ONLY IN PNPM 10.1.0 AND NEWER)
318+
*
319+
* PNPM documentation: https://pnpm.io/settings#onlybuiltdependencies
320+
*
321+
* Example:
322+
* "globalOnlyBuiltDependencies": [
323+
* "esbuild",
324+
* "playwright",
325+
* "@swc/core"
326+
* ]
327+
*/
328+
/*[BEGIN "HYPOTHETICAL"]*/
329+
"globalOnlyBuiltDependencies": [
330+
"esbuild"
331+
],
332+
/*[END "HYPOTHETICAL"]*/
333+
309334
/**
310335
* The `globalIgnoredOptionalDependencies` setting suppresses the installation of optional NPM
311336
* dependencies specified in the list. This is useful when certain optional dependencies are

libraries/rush-lib/src/logic/installManager/InstallHelpers.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ interface ICommonPackageJson extends IPackageJson {
3131
packageExtensions?: typeof PnpmOptionsConfiguration.prototype.globalPackageExtensions;
3232
peerDependencyRules?: typeof PnpmOptionsConfiguration.prototype.globalPeerDependencyRules;
3333
neverBuiltDependencies?: typeof PnpmOptionsConfiguration.prototype.globalNeverBuiltDependencies;
34+
onlyBuiltDependencies?: typeof PnpmOptionsConfiguration.prototype.globalOnlyBuiltDependencies;
3435
ignoredOptionalDependencies?: typeof PnpmOptionsConfiguration.prototype.globalIgnoredOptionalDependencies;
3536
allowedDeprecatedVersions?: typeof PnpmOptionsConfiguration.prototype.globalAllowedDeprecatedVersions;
3637
patchedDependencies?: typeof PnpmOptionsConfiguration.prototype.globalPatchedDependencies;
@@ -76,6 +77,24 @@ export class InstallHelpers {
7677
commonPackageJson.pnpm.neverBuiltDependencies = pnpmOptions.globalNeverBuiltDependencies;
7778
}
7879

80+
if (pnpmOptions.globalOnlyBuiltDependencies) {
81+
if (
82+
rushConfiguration.rushConfigurationJson.pnpmVersion !== undefined &&
83+
semver.lt(rushConfiguration.rushConfigurationJson.pnpmVersion, '10.1.0')
84+
) {
85+
terminal.writeWarningLine(
86+
Colorize.yellow(
87+
`Your version of pnpm (${rushConfiguration.rushConfigurationJson.pnpmVersion}) ` +
88+
`doesn't support the "globalOnlyBuiltDependencies" field in ` +
89+
`${rushConfiguration.commonRushConfigFolder}/${RushConstants.pnpmConfigFilename}. ` +
90+
'Remove this field or upgrade to pnpm 10.1.0 or newer.'
91+
)
92+
);
93+
}
94+
95+
commonPackageJson.pnpm.onlyBuiltDependencies = pnpmOptions.globalOnlyBuiltDependencies;
96+
}
97+
7998
if (pnpmOptions.globalIgnoredOptionalDependencies) {
8099
if (
81100
rushConfiguration.rushConfigurationJson.pnpmVersion !== undefined &&

libraries/rush-lib/src/logic/pnpm/PnpmOptionsConfiguration.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ export interface IPnpmOptionsJson extends IPackageManagerOptionsJsonBase {
114114
* {@inheritDoc PnpmOptionsConfiguration.globalNeverBuiltDependencies}
115115
*/
116116
globalNeverBuiltDependencies?: string[];
117+
/**
118+
* {@inheritDoc PnpmOptionsConfiguration.globalOnlyBuiltDependencies}
119+
*/
120+
globalOnlyBuiltDependencies?: string[];
117121
/**
118122
* {@inheritDoc PnpmOptionsConfiguration.globalIgnoredOptionalDependencies}
119123
*/
@@ -365,6 +369,20 @@ export class PnpmOptionsConfiguration extends PackageManagerOptionsConfiguration
365369
*/
366370
public readonly globalNeverBuiltDependencies: string[] | undefined;
367371

372+
/**
373+
* The `globalOnlyBuiltDependencies` setting specifies an allowlist of dependencies that are permitted
374+
* to run build scripts (`preinstall`, `install`, and `postinstall` lifecycle events). This is the inverse
375+
* of `globalNeverBuiltDependencies`. In PNPM 10.x, build scripts are disabled by default for security,
376+
* so this setting is required to explicitly permit specific packages to run their build scripts.
377+
* The settings are copied into the `pnpm.onlyBuiltDependencies` field of the `common/temp/package.json`
378+
* file that is generated by Rush during installation.
379+
*
380+
* (SUPPORTED ONLY IN PNPM 10.1.0 AND NEWER)
381+
*
382+
* PNPM documentation: https://pnpm.io/package_json#pnpmonlybuiltdependencies
383+
*/
384+
public readonly globalOnlyBuiltDependencies: string[] | undefined;
385+
368386
/**
369387
* The ignoredOptionalDependencies setting allows you to exclude certain optional dependencies from being installed
370388
* during the Rush installation process. This can be useful when optional dependencies are not required or are
@@ -468,6 +486,7 @@ export class PnpmOptionsConfiguration extends PackageManagerOptionsConfiguration
468486
this.globalPeerDependencyRules = json.globalPeerDependencyRules;
469487
this.globalPackageExtensions = json.globalPackageExtensions;
470488
this.globalNeverBuiltDependencies = json.globalNeverBuiltDependencies;
489+
this.globalOnlyBuiltDependencies = json.globalOnlyBuiltDependencies;
471490
this.globalIgnoredOptionalDependencies = json.globalIgnoredOptionalDependencies;
472491
this.globalAllowedDeprecatedVersions = json.globalAllowedDeprecatedVersions;
473492
this.unsupportedPackageJsonSettings = json.unsupportedPackageJsonSettings;

libraries/rush-lib/src/logic/pnpm/test/PnpmOptionsConfiguration.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,19 @@ describe(PnpmOptionsConfiguration.name, () => {
7474
]);
7575
});
7676

77+
it('loads onlyBuiltDependencies', () => {
78+
const pnpmConfiguration: PnpmOptionsConfiguration = PnpmOptionsConfiguration.loadFromJsonFileOrThrow(
79+
`${__dirname}/jsonFiles/pnpm-config-onlyBuiltDependencies.json`,
80+
fakeCommonTempFolder
81+
);
82+
83+
expect(TestUtilities.stripAnnotations(pnpmConfiguration.globalOnlyBuiltDependencies)).toEqual([
84+
'esbuild',
85+
'playwright',
86+
'@swc/core'
87+
]);
88+
});
89+
7790
it('loads minimumReleaseAge', () => {
7891
const pnpmConfiguration: PnpmOptionsConfiguration = PnpmOptionsConfiguration.loadFromJsonFileOrThrow(
7992
`${__dirname}/jsonFiles/pnpm-config-minimumReleaseAge.json`,
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"globalOnlyBuiltDependencies": ["esbuild", "playwright", "@swc/core"]
3+
}

libraries/rush-lib/src/logic/test/InstallHelpers.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ describe('InstallHelpers', () => {
6767
}
6868
},
6969
neverBuiltDependencies: ['fsevents', 'level'],
70+
onlyBuiltDependencies: ['esbuild', 'playwright'],
7071
pnpmFutureFeature: true
7172
}
7273
})

libraries/rush-lib/src/logic/test/pnpmConfig/common/config/rush/pnpm-config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
}
1414
},
1515
"globalNeverBuiltDependencies": ["fsevents", "level"],
16+
"globalOnlyBuiltDependencies": ["esbuild", "playwright"],
1617
"globalCatalogs": {
1718
"default": {
1819
"react": "^18.0.0",
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"pnpmVersion": "6.23.1",
2+
"pnpmVersion": "10.1.0",
33
"rushVersion": "5.58.0",
44
"projects": []
55
}

0 commit comments

Comments
 (0)