@depup/nx 23.2.0-depup.2 → 23.2.1-depup.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -11
- package/changes.json +18 -10
- package/dist/release/changelog-renderer/index.d.ts +4 -0
- package/dist/release/changelog-renderer/index.js +17 -1
- package/dist/src/command-line/migrate/prompt-files.js +2 -9
- package/dist/src/command-line/release/changelog.js +3 -1
- package/dist/src/command-line/report/report.d.ts +2 -0
- package/dist/src/command-line/report/report.js +28 -1
- package/dist/src/command-line/reset/reset.js +1 -3
- package/dist/src/daemon/client/daemon-environment.d.ts +10 -0
- package/dist/src/daemon/client/daemon-environment.js +44 -0
- package/dist/src/daemon/server/handle-client-env.js +24 -3
- package/dist/src/native/nx.wasm32-wasi.debug.wasm +0 -0
- package/dist/src/native/nx.wasm32-wasi.wasm +0 -0
- package/dist/src/nx-cloud/update-manager.js +4 -3
- package/dist/src/plugins/js/lock-file/pruned-output.d.ts +10 -9
- package/dist/src/plugins/js/lock-file/pruned-output.js +37 -13
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.d.ts +16 -0
- package/dist/src/project-graph/plugins/isolation/isolated-plugin.js +59 -22
- package/dist/src/tasks-runner/forked-process-task-runner.d.ts +3 -0
- package/dist/src/tasks-runner/forked-process-task-runner.js +15 -6
- package/dist/src/tasks-runner/init-tasks-runner.js +32 -2
- package/dist/src/tasks-runner/life-cycles/task-history-life-cycle.js +16 -11
- package/dist/src/tasks-runner/running-tasks/batch-process.js +3 -0
- package/dist/src/tasks-runner/running-tasks/shared-running-task.d.ts +1 -0
- package/dist/src/tasks-runner/running-tasks/shared-running-task.js +12 -1
- package/dist/src/tasks-runner/task-orchestrator.d.ts +3 -0
- package/dist/src/tasks-runner/task-orchestrator.js +31 -3
- package/dist/src/utils/min-release-age/behavior/pnpm.js +17 -9
- package/dist/src/utils/package-json.js +13 -2
- package/dist/src/utils/params.js +1 -1
- package/dist/src/utils/path.d.ts +6 -0
- package/dist/src/utils/path.js +15 -0
- package/package.json +40 -32
package/README.md
CHANGED
|
@@ -13,32 +13,33 @@ npm install @depup/nx
|
|
|
13
13
|
|
|
14
14
|
| Field | Value |
|
|
15
15
|
|-------|-------|
|
|
16
|
-
| Original | [nx](https://www.npmjs.com/package/nx) @ 23.2.
|
|
17
|
-
| Processed | 2026-09-
|
|
16
|
+
| Original | [nx](https://www.npmjs.com/package/nx) @ 23.2.1 |
|
|
17
|
+
| Processed | 2026-09-16 |
|
|
18
18
|
| Smoke test | failed |
|
|
19
|
-
| Deps updated |
|
|
19
|
+
| Deps updated | 75 |
|
|
20
20
|
|
|
21
21
|
## Dependency Changes
|
|
22
22
|
|
|
23
23
|
| Dependency | From | To |
|
|
24
24
|
|------------|------|-----|
|
|
25
|
-
| @clack/core | 1.4.3 | ^1.5.
|
|
26
|
-
| @clack/prompts | 1.7.0 | ^1.8.
|
|
25
|
+
| @clack/core | 1.4.3 | ^1.5.1 |
|
|
26
|
+
| @clack/prompts | 1.7.0 | ^1.8.1 |
|
|
27
27
|
| @emnapi/core | 1.4.5 | ^1.11.3 |
|
|
28
28
|
| @emnapi/runtime | 1.4.5 | ^1.11.3 |
|
|
29
29
|
| @emnapi/wasi-threads | 1.0.4 | ^2.1.0 |
|
|
30
30
|
| @jest/diff-sequences | 30.0.1 | ^30.5.0 |
|
|
31
|
-
| @napi-rs/wasm-runtime | 0.2.4 | ^1.2.
|
|
32
|
-
| @tybys/wasm-util | 0.9.0 | ^0.10.
|
|
31
|
+
| @napi-rs/wasm-runtime | 0.2.4 | ^1.2.4 |
|
|
32
|
+
| @tybys/wasm-util | 0.9.0 | ^0.10.4 |
|
|
33
33
|
| @zkochan/js-yaml | 0.0.7 | ^0.0.11 |
|
|
34
34
|
| agent-base | 6.0.2 | ^9.0.0 |
|
|
35
35
|
| ansi-regex | 5.0.1 | ^6.3.0 |
|
|
36
36
|
| ansi-styles | 4.3.0 | ^7.0.0 |
|
|
37
|
-
| argparse | 2.0.1 | ^3.0.
|
|
37
|
+
| argparse | 2.0.1 | ^3.0.2 |
|
|
38
38
|
| asynckit | 0.4.0 | ^0.5.0 |
|
|
39
39
|
| axios | 1.18.1 | ^1.20.0 |
|
|
40
40
|
| balanced-match | 4.0.3 | ^4.0.4 |
|
|
41
41
|
| bl | 4.1.0 | ^7.0.12 |
|
|
42
|
+
| brace-expansion | 5.0.9 | ^5.0.12 |
|
|
42
43
|
| buffer | 5.7.1 | ^6.0.3 |
|
|
43
44
|
| chalk | 4.1.2 | ^6.0.0 |
|
|
44
45
|
| cli-cursor | 3.1.0 | ^5.0.0 |
|
|
@@ -53,7 +54,7 @@ npm install @depup/nx
|
|
|
53
54
|
| dotenv | 16.4.7 | ^17.4.2 |
|
|
54
55
|
| dotenv-expand | 12.0.3 | ^1000.0.0 |
|
|
55
56
|
| ejs | 5.0.1 | ^6.0.1 |
|
|
56
|
-
| emoji-regex | 8.0.0 | ^
|
|
57
|
+
| emoji-regex | 8.0.0 | ^11.0.0 |
|
|
57
58
|
| es-object-atoms | 1.1.1 | ^1.1.2 |
|
|
58
59
|
| escape-string-regexp | 1.0.5 | ^5.0.0 |
|
|
59
60
|
| fast-wrap-ansi | 0.2.0 | ^0.2.2 |
|
|
@@ -61,7 +62,7 @@ npm install @depup/nx
|
|
|
61
62
|
| flat | 5.0.2 | ^6.0.1 |
|
|
62
63
|
| has-flag | 4.0.0 | ^5.0.1 |
|
|
63
64
|
| https-proxy-agent | 5.0.1 | ^9.1.0 |
|
|
64
|
-
| ignore | 7.0.5 | ^7.0.
|
|
65
|
+
| ignore | 7.0.5 | ^7.0.9 |
|
|
65
66
|
| is-docker | 3.0.0 | ^4.0.0 |
|
|
66
67
|
| is-fullwidth-code-point | 3.0.0 | ^5.1.0 |
|
|
67
68
|
| is-interactive | 1.0.0 | ^2.0.0 |
|
|
@@ -76,7 +77,7 @@ npm install @depup/nx
|
|
|
76
77
|
| minimatch | 10.2.5 | ^10.2.6 |
|
|
77
78
|
| npm-run-path | 4.0.1 | ^6.0.0 |
|
|
78
79
|
| onetime | 5.1.2 | ^8.0.0 |
|
|
79
|
-
| open | 10.1.0 | ^11.0.
|
|
80
|
+
| open | 10.1.0 | ^11.0.4 |
|
|
80
81
|
| ora | 5.4.1 | ^9.4.1 |
|
|
81
82
|
| path-key | 3.1.1 | ^4.0.0 |
|
|
82
83
|
| readable-stream | 3.6.2 | ^4.7.0 |
|
|
@@ -93,6 +94,7 @@ npm install @depup/nx
|
|
|
93
94
|
| tar-stream | 2.2.0 | ^3.2.1 |
|
|
94
95
|
| which | 3.0.1 | ^7.0.0 |
|
|
95
96
|
| wrap-ansi | 7.0.0 | ^10.0.1 |
|
|
97
|
+
| yaml | 2.9.0 | ^2.9.1 |
|
|
96
98
|
| yargs | 17.7.2 | ^18.1.0 |
|
|
97
99
|
| yargs-parser | 21.1.1 | ^22.0.0 |
|
|
98
100
|
|
package/changes.json
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
"bumped": {
|
|
3
3
|
"@clack/core": {
|
|
4
4
|
"from": "1.4.3",
|
|
5
|
-
"to": "^1.5.
|
|
5
|
+
"to": "^1.5.1"
|
|
6
6
|
},
|
|
7
7
|
"@clack/prompts": {
|
|
8
8
|
"from": "1.7.0",
|
|
9
|
-
"to": "^1.8.
|
|
9
|
+
"to": "^1.8.1"
|
|
10
10
|
},
|
|
11
11
|
"@emnapi/core": {
|
|
12
12
|
"from": "1.4.5",
|
|
@@ -26,11 +26,11 @@
|
|
|
26
26
|
},
|
|
27
27
|
"@napi-rs/wasm-runtime": {
|
|
28
28
|
"from": "0.2.4",
|
|
29
|
-
"to": "^1.2.
|
|
29
|
+
"to": "^1.2.4"
|
|
30
30
|
},
|
|
31
31
|
"@tybys/wasm-util": {
|
|
32
32
|
"from": "0.9.0",
|
|
33
|
-
"to": "^0.10.
|
|
33
|
+
"to": "^0.10.4"
|
|
34
34
|
},
|
|
35
35
|
"@zkochan/js-yaml": {
|
|
36
36
|
"from": "0.0.7",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
},
|
|
51
51
|
"argparse": {
|
|
52
52
|
"from": "2.0.1",
|
|
53
|
-
"to": "^3.0.
|
|
53
|
+
"to": "^3.0.2"
|
|
54
54
|
},
|
|
55
55
|
"asynckit": {
|
|
56
56
|
"from": "0.4.0",
|
|
@@ -68,6 +68,10 @@
|
|
|
68
68
|
"from": "4.1.0",
|
|
69
69
|
"to": "^7.0.12"
|
|
70
70
|
},
|
|
71
|
+
"brace-expansion": {
|
|
72
|
+
"from": "5.0.9",
|
|
73
|
+
"to": "^5.0.12"
|
|
74
|
+
},
|
|
71
75
|
"buffer": {
|
|
72
76
|
"from": "5.7.1",
|
|
73
77
|
"to": "^6.0.3"
|
|
@@ -126,7 +130,7 @@
|
|
|
126
130
|
},
|
|
127
131
|
"emoji-regex": {
|
|
128
132
|
"from": "8.0.0",
|
|
129
|
-
"to": "^
|
|
133
|
+
"to": "^11.0.0"
|
|
130
134
|
},
|
|
131
135
|
"es-object-atoms": {
|
|
132
136
|
"from": "1.1.1",
|
|
@@ -158,7 +162,7 @@
|
|
|
158
162
|
},
|
|
159
163
|
"ignore": {
|
|
160
164
|
"from": "7.0.5",
|
|
161
|
-
"to": "^7.0.
|
|
165
|
+
"to": "^7.0.9"
|
|
162
166
|
},
|
|
163
167
|
"is-docker": {
|
|
164
168
|
"from": "3.0.0",
|
|
@@ -218,7 +222,7 @@
|
|
|
218
222
|
},
|
|
219
223
|
"open": {
|
|
220
224
|
"from": "10.1.0",
|
|
221
|
-
"to": "^11.0.
|
|
225
|
+
"to": "^11.0.4"
|
|
222
226
|
},
|
|
223
227
|
"ora": {
|
|
224
228
|
"from": "5.4.1",
|
|
@@ -284,6 +288,10 @@
|
|
|
284
288
|
"from": "7.0.0",
|
|
285
289
|
"to": "^10.0.1"
|
|
286
290
|
},
|
|
291
|
+
"yaml": {
|
|
292
|
+
"from": "2.9.0",
|
|
293
|
+
"to": "^2.9.1"
|
|
294
|
+
},
|
|
287
295
|
"yargs": {
|
|
288
296
|
"from": "17.7.2",
|
|
289
297
|
"to": "^18.1.0"
|
|
@@ -293,6 +301,6 @@
|
|
|
293
301
|
"to": "^22.0.0"
|
|
294
302
|
}
|
|
295
303
|
},
|
|
296
|
-
"timestamp": "2026-09-
|
|
297
|
-
"totalUpdated":
|
|
304
|
+
"timestamp": "2026-09-16T00:31:36.139Z",
|
|
305
|
+
"totalUpdated": 75
|
|
298
306
|
}
|
|
@@ -106,5 +106,9 @@ export default class DefaultChangelogRenderer {
|
|
|
106
106
|
protected groupChangesByScope(changes: ChangelogChange[]): Record<string, ChangelogChange[]>;
|
|
107
107
|
protected extractBreakingChangeExplanation(message: string): string | null;
|
|
108
108
|
private isBreakingChangeBoundary;
|
|
109
|
+
protected isAiAgentAuthor(author: {
|
|
110
|
+
name: string;
|
|
111
|
+
email: string;
|
|
112
|
+
}): boolean;
|
|
109
113
|
protected formatName(name?: string): string;
|
|
110
114
|
}
|
|
@@ -3,6 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
const semver_1 = require("semver");
|
|
4
4
|
// Stripped from breaking change explanations (e.g. bot/session markers).
|
|
5
5
|
const HtmlCommentRegex = /<!--[\s\S]*?-->/g;
|
|
6
|
+
// Keyed on email: agent display names track model versions (e.g. "Claude Opus
|
|
7
|
+
// 5 (1M context)"), and a human contributor can share a name with an agent.
|
|
8
|
+
const AiAgentAuthorEmails = new Set([
|
|
9
|
+
'noreply@anthropic.com',
|
|
10
|
+
'claude@anthropic.com',
|
|
11
|
+
'amp@ampcode.com',
|
|
12
|
+
'cursoragent@cursor.com',
|
|
13
|
+
'openhands@all-hands.dev',
|
|
14
|
+
'opendevin@all-hands.dev',
|
|
15
|
+
]);
|
|
16
|
+
// The Copilot coding agent's trailer is not always [bot]-suffixed.
|
|
17
|
+
const CopilotAuthorEmailRegex = /^(?:\d+\+)?copilot@users\.noreply\.github\.com$/;
|
|
6
18
|
class DefaultChangelogRenderer {
|
|
7
19
|
/**
|
|
8
20
|
* A ChangelogRenderer class takes in the determined changes and other relevant metadata
|
|
@@ -212,7 +224,7 @@ class DefaultChangelogRenderer {
|
|
|
212
224
|
}
|
|
213
225
|
for (const author of change.authors) {
|
|
214
226
|
const name = this.formatName(author.name);
|
|
215
|
-
if (!name || name.includes('[bot]')) {
|
|
227
|
+
if (!name || name.includes('[bot]') || this.isAiAgentAuthor(author)) {
|
|
216
228
|
continue;
|
|
217
229
|
}
|
|
218
230
|
if (!_authors.has(name)) {
|
|
@@ -371,6 +383,10 @@ class DefaultChangelogRenderer {
|
|
|
371
383
|
// Git metadata delimiter following the body
|
|
372
384
|
trimmed === '"');
|
|
373
385
|
}
|
|
386
|
+
isAiAgentAuthor(author) {
|
|
387
|
+
const email = (author.email || '').trim().toLowerCase();
|
|
388
|
+
return (AiAgentAuthorEmails.has(email) || CopilotAuthorEmailRegex.test(email));
|
|
389
|
+
}
|
|
374
390
|
formatName(name = '') {
|
|
375
391
|
return name
|
|
376
392
|
.split(' ')
|
|
@@ -44,15 +44,8 @@ async function resolvePromptFiles(packageName, packageVersion, migrations, migra
|
|
|
44
44
|
? resolvedPromptFiles
|
|
45
45
|
: undefined;
|
|
46
46
|
}
|
|
47
|
-
function isPromptPathWithinMigrationsDir(migrationsDir, promptRelPath) {
|
|
48
|
-
const rel = (0, path_1.relative)(migrationsDir, (0, path_1.join)(migrationsDir, promptRelPath));
|
|
49
|
-
return !((0, path_1.isAbsolute)(promptRelPath) ||
|
|
50
|
-
rel === '..' ||
|
|
51
|
-
rel.startsWith(`..${path_1.sep}`) ||
|
|
52
|
-
rel.startsWith(`..${path_1.posix.sep}`));
|
|
53
|
-
}
|
|
54
47
|
function assertPromptPathWithinMigrationsDir(migrationsDir, promptRelPath, packageName, packageVersion) {
|
|
55
|
-
if (!
|
|
48
|
+
if (!(0, path_2.isContainedRelativePath)(promptRelPath)) {
|
|
56
49
|
throw new Error(`Invalid prompt path "${promptRelPath}" in package "${packageName}@${packageVersion}": prompt paths must be relative and resolve within the package's migrations directory.`);
|
|
57
50
|
}
|
|
58
51
|
}
|
|
@@ -77,7 +70,7 @@ exports.PromptResolutionError = PromptResolutionError;
|
|
|
77
70
|
* directory and point at an existing file.
|
|
78
71
|
*/
|
|
79
72
|
function resolvePrompt(promptPath, migrationsDir) {
|
|
80
|
-
if (!
|
|
73
|
+
if (!(0, path_2.isContainedRelativePath)(promptPath)) {
|
|
81
74
|
throw new PromptResolutionError(promptPath, migrationsDir);
|
|
82
75
|
}
|
|
83
76
|
const resolvedPath = (0, path_1.join)(migrationsDir, promptPath);
|
|
@@ -380,7 +380,9 @@ function createAPI(overrideReleaseConfig, ignoreNxJsonConfig) {
|
|
|
380
380
|
}
|
|
381
381
|
else {
|
|
382
382
|
const groupCacheKey = `${releaseGroup.name}:fixed`;
|
|
383
|
-
const fromSHA = await getCachedFromSHA(groupCacheKey, releaseGroup.releaseTag.pattern, {
|
|
383
|
+
const fromSHA = await getCachedFromSHA(groupCacheKey, releaseGroup.releaseTag.pattern, {
|
|
384
|
+
releaseGroupName: releaseGroup.name,
|
|
385
|
+
}, workspacePreid ?? projectsPreid?.[Object.keys(projectsPreid)[0]], releaseGroup.releaseTag.checkAllBranchesWhen, releaseGroup.releaseTag.requireSemver, releaseGroup.releaseTag.strictPreid);
|
|
384
386
|
if (!fromSHA) {
|
|
385
387
|
throw new Error(`Unable to determine the previous git tag. If this is the first release of your release group, use the --first-release option or set the "release.changelog.automaticFromRef" config property in nx.json to generate a changelog from the first commit. Otherwise, be sure to configure the "release.releaseTag.pattern" property in nx.json to match the structure of your repository's git tags.`);
|
|
386
388
|
}
|
|
@@ -13,6 +13,7 @@ export declare const patternsWeIgnoreInCommunityReport: Array<string | RegExp>;
|
|
|
13
13
|
*
|
|
14
14
|
*/
|
|
15
15
|
export declare function reportHandler(): Promise<void>;
|
|
16
|
+
export declare function cacheSectionLines(cache: NonNullable<ReportData['cache']>): string[];
|
|
16
17
|
export interface ReportData {
|
|
17
18
|
pm: PackageManager;
|
|
18
19
|
pmVersion: string;
|
|
@@ -49,6 +50,7 @@ export interface ReportData {
|
|
|
49
50
|
cache: {
|
|
50
51
|
max: number;
|
|
51
52
|
used: number;
|
|
53
|
+
location: string;
|
|
52
54
|
} | null;
|
|
53
55
|
}
|
|
54
56
|
export declare function getReportData(): Promise<ReportData>;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.patternsWeIgnoreInCommunityReport = exports.packagesWeCareAbout = void 0;
|
|
4
4
|
exports.reportHandler = reportHandler;
|
|
5
|
+
exports.cacheSectionLines = cacheSectionLines;
|
|
5
6
|
exports.getReportData = getReportData;
|
|
6
7
|
exports.findMisalignedPackagesForPackage = findMisalignedPackagesForPackage;
|
|
7
8
|
exports.findInstalledPowerpackPlugins = findInstalledPowerpackPlugins;
|
|
@@ -11,6 +12,8 @@ exports.findInstalledPackagesWeCareAbout = findInstalledPackagesWeCareAbout;
|
|
|
11
12
|
const tslib_1 = require("tslib");
|
|
12
13
|
const pc = tslib_1.__importStar(require("picocolors"));
|
|
13
14
|
const output_1 = require("../../utils/output");
|
|
15
|
+
const path_1 = require("path");
|
|
16
|
+
const os_1 = require("os");
|
|
14
17
|
const package_manager_1 = require("../../utils/package-manager");
|
|
15
18
|
const fileutils_1 = require("../../utils/fileutils");
|
|
16
19
|
const package_json_1 = require("../../utils/package-json");
|
|
@@ -25,6 +28,7 @@ const operators_1 = require("../../project-graph/operators");
|
|
|
25
28
|
const versions_1 = require("../../utils/versions");
|
|
26
29
|
const nx_key_1 = require("../../utils/nx-key");
|
|
27
30
|
const cache_1 = require("../../tasks-runner/cache");
|
|
31
|
+
const cache_directory_1 = require("../../utils/cache-directory");
|
|
28
32
|
const client_1 = require("../../daemon/client/client");
|
|
29
33
|
const nx_package_group_1 = require("../../utils/nx-package-group");
|
|
30
34
|
const nxPackageJson = (0, fileutils_1.readJsonFile)(require.resolve('nx/package.json'));
|
|
@@ -140,7 +144,7 @@ async function reportHandler() {
|
|
|
140
144
|
}
|
|
141
145
|
if (cache) {
|
|
142
146
|
bodyLines.push(LINE_SEPARATOR);
|
|
143
|
-
bodyLines.push(
|
|
147
|
+
bodyLines.push(...cacheSectionLines(cache));
|
|
144
148
|
}
|
|
145
149
|
if (outOfSyncPackageGroup) {
|
|
146
150
|
bodyLines.push(LINE_SEPARATOR);
|
|
@@ -182,6 +186,28 @@ async function reportHandler() {
|
|
|
182
186
|
bodyLines,
|
|
183
187
|
});
|
|
184
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* The report is meant to be pasted into public issues, so the home directory
|
|
191
|
+
* is elided rather than printing the user's account name.
|
|
192
|
+
*/
|
|
193
|
+
function collapseHome(path) {
|
|
194
|
+
const home = (0, os_1.homedir)();
|
|
195
|
+
return path === home || path.startsWith(home + path_1.sep)
|
|
196
|
+
? `~${path.slice(home.length)}`
|
|
197
|
+
: path;
|
|
198
|
+
}
|
|
199
|
+
function cacheSectionLines(cache) {
|
|
200
|
+
const unlimited = cache.max === 0;
|
|
201
|
+
const max = unlimited ? '∞' : (0, cache_1.formatCacheSize)(cache.max);
|
|
202
|
+
const share = unlimited
|
|
203
|
+
? ''
|
|
204
|
+
: ` (${((cache.used / cache.max) * 100).toFixed(1)}%)`;
|
|
205
|
+
return [
|
|
206
|
+
'Cache',
|
|
207
|
+
`- Usage: ${(0, cache_1.formatCacheSize)(cache.used)} / ${max}${share}`,
|
|
208
|
+
`- Location: ${collapseHome(cache.location)}`,
|
|
209
|
+
];
|
|
210
|
+
}
|
|
185
211
|
function findDependencyChain(graph, targetNode) {
|
|
186
212
|
const reversedGraph = (0, operators_1.reverse)(graph);
|
|
187
213
|
// BFS to find shortest path to root dependency
|
|
@@ -266,6 +292,7 @@ async function getReportData() {
|
|
|
266
292
|
? {
|
|
267
293
|
max: (0, cache_1.resolveMaxCacheSize)(nxJson),
|
|
268
294
|
used: new cache_1.DbCache({ nxCloudRemoteCache: null }).getUsedCacheSpace(),
|
|
295
|
+
location: cache_directory_1.cacheDir,
|
|
269
296
|
}
|
|
270
297
|
: null;
|
|
271
298
|
return {
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resetHandler = resetHandler;
|
|
4
4
|
const node_fs_1 = require("node:fs");
|
|
5
|
-
const node_path_1 = require("node:path");
|
|
6
5
|
const client_1 = require("../../daemon/client/client");
|
|
7
6
|
const tmp_dir_1 = require("../../daemon/tmp-dir");
|
|
8
7
|
const cache_directory_1 = require("../../utils/cache-directory");
|
|
@@ -125,8 +124,7 @@ async function resetCloudClient() {
|
|
|
125
124
|
}
|
|
126
125
|
function removeInstalledNxCloudClient() {
|
|
127
126
|
return incrementalBackoff(INCREMENTAL_BACKOFF_FIRST_DELAY, INCREMENTAL_BACKOFF_MAX_DURATION, () => {
|
|
128
|
-
|
|
129
|
-
(0, node_fs_1.rmSync)((0, node_path_1.join)(cloudClientDir, 'cloud'), { recursive: true, force: true });
|
|
127
|
+
(0, node_fs_1.rmSync)((0, update_manager_1.getBundleInstallDefaultLocation)(), { recursive: true, force: true });
|
|
130
128
|
});
|
|
131
129
|
}
|
|
132
130
|
function cleanupCacheEntries() {
|
|
@@ -62,3 +62,13 @@ export declare function getAppliedDaemonClientEnv(): {
|
|
|
62
62
|
* previous client is stale all the same.
|
|
63
63
|
*/
|
|
64
64
|
export declare function applyDaemonEnvFromClient(newEnv: NodeJS.ProcessEnv): string[];
|
|
65
|
+
/**
|
|
66
|
+
* Yarn Berry creates a fresh BERRY_BIN_FOLDER for every invocation and puts it
|
|
67
|
+
* first on PATH. The wrappers inside are runtime state the daemon and workers
|
|
68
|
+
* must receive, but the folder's random name is not project-graph identity:
|
|
69
|
+
* two invocations whose environments differ only by it would compute the same
|
|
70
|
+
* graph. Strips the folder from PATH and pins the var to a sentinel so such
|
|
71
|
+
* environments compare equal. Returns a copy; never mutates runtime env.
|
|
72
|
+
*/
|
|
73
|
+
export declare function normalizeDaemonEnvironmentForGraph(env: NodeJS.ProcessEnv, platform?: NodeJS.Platform): NodeJS.ProcessEnv;
|
|
74
|
+
export declare function getChangedEnvKeys(before: NodeJS.ProcessEnv, after: NodeJS.ProcessEnv): string[];
|
|
@@ -6,6 +6,8 @@ exports.getDaemonClientEnvGeneration = getDaemonClientEnvGeneration;
|
|
|
6
6
|
exports.getDaemonSpawnEnv = getDaemonSpawnEnv;
|
|
7
7
|
exports.getAppliedDaemonClientEnv = getAppliedDaemonClientEnv;
|
|
8
8
|
exports.applyDaemonEnvFromClient = applyDaemonEnvFromClient;
|
|
9
|
+
exports.normalizeDaemonEnvironmentForGraph = normalizeDaemonEnvironmentForGraph;
|
|
10
|
+
exports.getChangedEnvKeys = getChangedEnvKeys;
|
|
9
11
|
const file_hasher_1 = require("../../hasher/file-hasher");
|
|
10
12
|
const DAEMON_ENV_REQUIRED_SETTINGS = {
|
|
11
13
|
NX_PROJECT_GLOB_CACHE: 'false',
|
|
@@ -376,3 +378,45 @@ function applyDaemonEnvFromClient(newEnv) {
|
|
|
376
378
|
appliedClientEnv = { ...newEnv };
|
|
377
379
|
return [...changedKeys];
|
|
378
380
|
}
|
|
381
|
+
const BERRY_BIN_FOLDER_GRAPH_IDENTITY = '<YARN_BERRY_BIN_FOLDER>';
|
|
382
|
+
/**
|
|
383
|
+
* Yarn Berry creates a fresh BERRY_BIN_FOLDER for every invocation and puts it
|
|
384
|
+
* first on PATH. The wrappers inside are runtime state the daemon and workers
|
|
385
|
+
* must receive, but the folder's random name is not project-graph identity:
|
|
386
|
+
* two invocations whose environments differ only by it would compute the same
|
|
387
|
+
* graph. Strips the folder from PATH and pins the var to a sentinel so such
|
|
388
|
+
* environments compare equal. Returns a copy; never mutates runtime env.
|
|
389
|
+
*/
|
|
390
|
+
function normalizeDaemonEnvironmentForGraph(env, platform = process.platform) {
|
|
391
|
+
const normalized = { ...env };
|
|
392
|
+
const berryBinFolder = normalized.BERRY_BIN_FOLDER;
|
|
393
|
+
if (!berryBinFolder) {
|
|
394
|
+
return normalized;
|
|
395
|
+
}
|
|
396
|
+
const pathKey = Object.keys(normalized).find((key) => key.toUpperCase() === 'PATH');
|
|
397
|
+
if (pathKey && normalized[pathKey]) {
|
|
398
|
+
const pathDelimiter = platform === 'win32' ? ';' : ':';
|
|
399
|
+
const canonicalize = (value) => {
|
|
400
|
+
const withPlatformSeparators = platform === 'win32' ? value.replaceAll('/', '\\') : value;
|
|
401
|
+
return platform === 'win32'
|
|
402
|
+
? withPlatformSeparators.toLowerCase()
|
|
403
|
+
: withPlatformSeparators;
|
|
404
|
+
};
|
|
405
|
+
const canonicalBerryBinFolder = canonicalize(berryBinFolder);
|
|
406
|
+
normalized[pathKey] = normalized[pathKey]
|
|
407
|
+
.split(pathDelimiter)
|
|
408
|
+
.filter((entry) => canonicalize(entry) !== canonicalBerryBinFolder)
|
|
409
|
+
.join(pathDelimiter);
|
|
410
|
+
}
|
|
411
|
+
normalized.BERRY_BIN_FOLDER = BERRY_BIN_FOLDER_GRAPH_IDENTITY;
|
|
412
|
+
return normalized;
|
|
413
|
+
}
|
|
414
|
+
function getChangedEnvKeys(before, after) {
|
|
415
|
+
const changedKeys = [];
|
|
416
|
+
for (const key of new Set([...Object.keys(before), ...Object.keys(after)])) {
|
|
417
|
+
if (before[key] !== after[key]) {
|
|
418
|
+
changedKeys.push(key);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
return changedKeys;
|
|
422
|
+
}
|
|
@@ -29,12 +29,30 @@ async function handleClientEnv(env) {
|
|
|
29
29
|
while (inFlightApply) {
|
|
30
30
|
await inFlightApply;
|
|
31
31
|
}
|
|
32
|
+
const graphEnvBefore = (0, daemon_environment_1.normalizeDaemonEnvironmentForGraph)(process.env);
|
|
33
|
+
const previousClientEnv = (0, daemon_environment_1.getAppliedDaemonClientEnv)()?.env;
|
|
32
34
|
const changedEnvKeys = (0, daemon_environment_1.applyDaemonEnvFromClient)(env);
|
|
33
35
|
if (changedEnvKeys.length === 0) {
|
|
34
36
|
return;
|
|
35
37
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
// Runtime changes always reach the workers, but only changes that survive
|
|
39
|
+
// graph normalization (e.g. Yarn Berry's per-invocation BERRY_BIN_FOLDER
|
|
40
|
+
// does not) invalidate the computed graph.
|
|
41
|
+
const graphChangedKeys = new Set([
|
|
42
|
+
...(0, daemon_environment_1.getChangedEnvKeys)(graphEnvBefore, (0, daemon_environment_1.normalizeDaemonEnvironmentForGraph)(process.env)),
|
|
43
|
+
...(previousClientEnv
|
|
44
|
+
? (0, daemon_environment_1.getChangedEnvKeys)((0, daemon_environment_1.normalizeDaemonEnvironmentForGraph)(previousClientEnv), (0, daemon_environment_1.normalizeDaemonEnvironmentForGraph)(env))
|
|
45
|
+
: []),
|
|
46
|
+
]);
|
|
47
|
+
if (graphChangedKeys.size > 0) {
|
|
48
|
+
logger_1.serverLogger.log(`Graph recompute necessary due to env variable refresh. Changed keys: ${[
|
|
49
|
+
...graphChangedKeys,
|
|
50
|
+
].join(', ')}`);
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
logger_1.serverLogger.log(`Env variable refresh changed only runtime values (${changedEnvKeys.join(', ')}); graph identity is unchanged, keeping the cached graph.`);
|
|
54
|
+
}
|
|
55
|
+
const apply = applyEnvChange(env, graphChangedKeys.size > 0);
|
|
38
56
|
inFlightApply = apply;
|
|
39
57
|
try {
|
|
40
58
|
await apply;
|
|
@@ -45,8 +63,11 @@ async function handleClientEnv(env) {
|
|
|
45
63
|
}
|
|
46
64
|
}
|
|
47
65
|
}
|
|
48
|
-
async function applyEnvChange(env) {
|
|
66
|
+
async function applyEnvChange(env, invalidateGraph) {
|
|
49
67
|
await forwardEnvToPluginWorkers(env);
|
|
68
|
+
if (!invalidateGraph) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
50
71
|
// Discarding the cached graph makes the next request recompute under the
|
|
51
72
|
// new env, and chains any in-flight compute (started under the old env) to
|
|
52
73
|
// that successor.
|
|
Binary file
|
|
Binary file
|
|
@@ -12,6 +12,7 @@ const axios_1 = require("./utilities/axios");
|
|
|
12
12
|
const debug_logger_1 = require("./debug-logger");
|
|
13
13
|
const tar = tslib_1.__importStar(require("tar-stream"));
|
|
14
14
|
const cache_directory_1 = require("../utils/cache-directory");
|
|
15
|
+
const is_ci_1 = require("../utils/is-ci");
|
|
15
16
|
const crypto_1 = require("crypto");
|
|
16
17
|
const workspace_root_1 = require("../utils/workspace-root");
|
|
17
18
|
class NxCloudEnterpriseOutdatedError extends Error {
|
|
@@ -106,9 +107,9 @@ function getBundleInstallDefaultLocation() {
|
|
|
106
107
|
if ((0, fs_1.existsSync)(legacyPath)) {
|
|
107
108
|
return legacyPath;
|
|
108
109
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
// The bundle `require`s a bare `nx`, so it must sit where that resolves: on CI
|
|
111
|
+
// the shared per-user root is outside the checkout (NXC-4944).
|
|
112
|
+
return (0, path_1.join)((0, is_ci_1.isCI)() ? (0, cache_directory_1.cacheDirectoryForWorkspace)(workspace_root_1.workspaceRoot) : cache_directory_1.cacheDir, 'cloud');
|
|
112
113
|
}
|
|
113
114
|
const runnerBundleInstallDirectory = getBundleInstallDefaultLocation();
|
|
114
115
|
function getLatestInstalledRunnerBundle() {
|
|
@@ -42,15 +42,16 @@ type PrunedPnpmConfig = {
|
|
|
42
42
|
* file is inert, verified installable with identical module resolution on
|
|
43
43
|
* pnpm 9, 10 and 11.
|
|
44
44
|
*
|
|
45
|
-
* pnpm 11
|
|
46
|
-
* `
|
|
47
|
-
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
* pnpm <=10,
|
|
51
|
-
* `
|
|
52
|
-
*
|
|
53
|
-
* the pruned
|
|
45
|
+
* On pnpm 11+, this file carries declared `minimumReleaseAge`,
|
|
46
|
+
* `minimumReleaseAgeExclude`, `minimumReleaseAgeStrict`, build approvals,
|
|
47
|
+
* `supportedArchitectures`, and applicable `patchedDependencies` from the
|
|
48
|
+
* workspace root. Approvals and patches are scoped to the pruned lockfile.
|
|
49
|
+
*
|
|
50
|
+
* On pnpm <=10, only build approvals, `supportedArchitectures`, and
|
|
51
|
+
* `patchedDependencies` are emitted in `package.json`.
|
|
52
|
+
*
|
|
53
|
+
* Settings encoded in the pruned resolution, such as `overrides` and
|
|
54
|
+
* `packageExtensions`, are not copied (`stripPrunedLockfilePnpmConfig`).
|
|
54
55
|
*
|
|
55
56
|
* The major is the build machine's pnpm, which is all that is knowable at
|
|
56
57
|
* build time: an output built on pnpm <=10 but deployed on pnpm 11+ will not
|
|
@@ -107,15 +107,16 @@ function dropInheritedPnpmPatchedDependencies(packageJson) {
|
|
|
107
107
|
* file is inert, verified installable with identical module resolution on
|
|
108
108
|
* pnpm 9, 10 and 11.
|
|
109
109
|
*
|
|
110
|
-
* pnpm 11
|
|
111
|
-
* `
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
115
|
-
* pnpm <=10,
|
|
116
|
-
* `
|
|
117
|
-
*
|
|
118
|
-
* the pruned
|
|
110
|
+
* On pnpm 11+, this file carries declared `minimumReleaseAge`,
|
|
111
|
+
* `minimumReleaseAgeExclude`, `minimumReleaseAgeStrict`, build approvals,
|
|
112
|
+
* `supportedArchitectures`, and applicable `patchedDependencies` from the
|
|
113
|
+
* workspace root. Approvals and patches are scoped to the pruned lockfile.
|
|
114
|
+
*
|
|
115
|
+
* On pnpm <=10, only build approvals, `supportedArchitectures`, and
|
|
116
|
+
* `patchedDependencies` are emitted in `package.json`.
|
|
117
|
+
*
|
|
118
|
+
* Settings encoded in the pruned resolution, such as `overrides` and
|
|
119
|
+
* `packageExtensions`, are not copied (`stripPrunedLockfilePnpmConfig`).
|
|
119
120
|
*
|
|
120
121
|
* The major is the build machine's pnpm, which is all that is knowable at
|
|
121
122
|
* build time: an output built on pnpm <=10 but deployed on pnpm 11+ will not
|
|
@@ -129,6 +130,29 @@ function getPrunedPnpmInstallSettingsYaml(workspaceRootPath = workspace_root_1.w
|
|
|
129
130
|
// list is accepted by pnpm 9-11 without pulling any importer into the install.
|
|
130
131
|
return dump({ packages: [], ...settings });
|
|
131
132
|
}
|
|
133
|
+
/**
|
|
134
|
+
* pnpm-workspace.yaml fields carried verbatim from the workspace root to the
|
|
135
|
+
* pruned output, with no interpretation beyond "declared or not" (unlike
|
|
136
|
+
* `allowBuilds`, filtered to the pruned lockfile, and `patchedDependencies`,
|
|
137
|
+
* resolved against it):
|
|
138
|
+
* - `supportedArchitectures`.
|
|
139
|
+
* - `minimumReleaseAge`/`minimumReleaseAgeExclude`: silently dropping these
|
|
140
|
+
* falls back to pnpm's own default cutoff instead of the workspace's,
|
|
141
|
+
* which can reject lockfile entries the workspace itself allows (or vice
|
|
142
|
+
* versa).
|
|
143
|
+
* - `minimumReleaseAgeStrict`: starting with pnpm 11.0.0, a declared
|
|
144
|
+
* `minimumReleaseAge` enables strict mode unless `minimumReleaseAgeStrict:
|
|
145
|
+
* false` is also declared. Dropping an explicit `false` here would
|
|
146
|
+
* silently re-enable strict mode in the pruned output and make its
|
|
147
|
+
* install reject an immature exact dependency the source workspace
|
|
148
|
+
* accepted.
|
|
149
|
+
*/
|
|
150
|
+
const STRAIGHT_COPY_WORKSPACE_SETTINGS = [
|
|
151
|
+
'supportedArchitectures',
|
|
152
|
+
'minimumReleaseAge',
|
|
153
|
+
'minimumReleaseAgeExclude',
|
|
154
|
+
'minimumReleaseAgeStrict',
|
|
155
|
+
];
|
|
132
156
|
/**
|
|
133
157
|
* The settings `getPrunedPnpmInstallSettingsYaml` emits, before serialization,
|
|
134
158
|
* so a caller can tell which of them the workspace actually declares. Null when
|
|
@@ -155,7 +179,7 @@ function getPrunedPnpmWorkspaceSettings(workspaceRootPath, prunedLockfileContent
|
|
|
155
179
|
}
|
|
156
180
|
catch {
|
|
157
181
|
// Unreadable or malformed pnpm-workspace.yaml: skip rather than guess.
|
|
158
|
-
logger_1.logger.warn('Could not read the workspace root pnpm-workspace.yaml; the pruned output will not declare pnpm install settings (build-script approvals, supportedArchitectures, patchedDependencies).');
|
|
182
|
+
logger_1.logger.warn('Could not read the workspace root pnpm-workspace.yaml; the pruned output will not declare pnpm install settings (build-script approvals, supportedArchitectures, minimumReleaseAge, patchedDependencies).');
|
|
159
183
|
return null;
|
|
160
184
|
}
|
|
161
185
|
const settings = {};
|
|
@@ -167,8 +191,8 @@ function getPrunedPnpmWorkspaceSettings(workspaceRootPath, prunedLockfileContent
|
|
|
167
191
|
settings.allowBuilds = allowBuilds;
|
|
168
192
|
}
|
|
169
193
|
}
|
|
170
|
-
|
|
171
|
-
settings
|
|
194
|
+
for (const field of STRAIGHT_COPY_WORKSPACE_SETTINGS) {
|
|
195
|
+
assignDefined(settings, rootSettings, field);
|
|
172
196
|
}
|
|
173
197
|
const patchedDependencies = precomputed?.patchedDependencies ??
|
|
174
198
|
(prunedLockfileContent
|
|
@@ -216,7 +240,7 @@ function getPnpmMajor(workspaceRootPath) {
|
|
|
216
240
|
function getPnpmMajorOrWarn(workspaceRootPath) {
|
|
217
241
|
const pnpmMajor = getPnpmMajor(workspaceRootPath);
|
|
218
242
|
if (pnpmMajor === null) {
|
|
219
|
-
logger_1.logger.warn('Could not determine the pnpm version. The pruned output will not carry pnpm build-script approvals, supportedArchitectures, or patchedDependencies declarations; patch files still ship.');
|
|
243
|
+
logger_1.logger.warn('Could not determine the pnpm version. The pruned output will not carry pnpm build-script approvals, supportedArchitectures, minimumReleaseAge, or patchedDependencies declarations; patch files still ship.');
|
|
220
244
|
}
|
|
221
245
|
return pnpmMajor;
|
|
222
246
|
}
|