Skip to content

Commit 678619f

Browse files
authored
fix(core): restore migrations used by nx repair (#33124)
## Current Behavior Some migrations used by `nx repair` are missing ## Expected Behavior Migrations used by `nx repair` are only removed when deemed applicable. This reverts a portion of commit a637f9e. ## Related Issue(s) <!-- Please link the issue being fixed so it gets closed when this is merged. --> Fixes #
1 parent 6d86945 commit 678619f

11 files changed

+977
-0
lines changed

packages/nx/migrations.json

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,42 @@
11
{
22
"generators": {
3+
"16.0.0-remove-nrwl-cli": {
4+
"cli": "nx",
5+
"version": "16.0.0-beta.0",
6+
"description": "Remove @nrwl/cli.",
7+
"implementation": "./src/migrations/update-16-0-0/remove-nrwl-cli"
8+
},
9+
"16.0.0-tokens-for-depends-on": {
10+
"cli": "nx",
11+
"version": "16.0.0-beta.9",
12+
"description": "Replace `dependsOn.projects` and `inputs` definitions with new configuration format.",
13+
"implementation": "./src/migrations/update-16-0-0/update-depends-on-to-tokens"
14+
},
15+
"16.0.0-update-nx-cloud-runner": {
16+
"cli": "nx",
17+
"version": "16.0.0-beta.0",
18+
"description": "Replace @nrwl/nx-cloud with nx-cloud",
19+
"implementation": "./src/migrations/update-16-0-0/update-nx-cloud-runner"
20+
},
21+
"16.2.0-remove-output-path-from-run-commands": {
22+
"cli": "nx",
23+
"version": "16.2.0-beta.0",
24+
"description": "Remove outputPath from run commands",
25+
"implementation": "./src/migrations/update-16-2-0/remove-run-commands-output-path"
26+
},
27+
"16.6.0-prefix-outputs": {
28+
"cli": "nx",
29+
"version": "16.6.0-beta.6",
30+
"description": "Prefix outputs with {workspaceRoot}/{projectRoot} if needed",
31+
"implementation": "./src/migrations/update-15-0-0/prefix-outputs"
32+
},
33+
"16.8.0-escape-dollar-sign-env": {
34+
"cli": "nx",
35+
"version": "16.8.0-beta.3",
36+
"description": "Escape $ in env variables",
37+
"implementation": "./src/migrations/update-16-8-0/escape-dollar-sign-env-variables",
38+
"x-repair-skip": true
39+
},
340
"17.0.0-move-cache-directory": {
441
"cli": "nx",
542
"version": "17.0.0-beta.1",
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
import { createTreeWithEmptyWorkspace } from '../../generators/testing-utils/create-tree-with-empty-workspace';
2+
import type { Tree } from '../../generators/tree';
3+
import {
4+
addProjectConfiguration,
5+
readNxJson,
6+
readProjectConfiguration,
7+
updateNxJson,
8+
} from '../../generators/utils/project-configuration';
9+
import { readJson, writeJson } from '../../generators/utils/json';
10+
import prefixOutputs from './prefix-outputs';
11+
import { validateOutputs } from '../../tasks-runner/utils';
12+
13+
describe('15.0.0 migration (prefix-outputs)', () => {
14+
let tree: Tree;
15+
16+
beforeEach(() => {
17+
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
18+
});
19+
20+
it('should prefix project outputs', async () => {
21+
addProjectConfiguration(tree, 'proj', {
22+
root: 'proj',
23+
targets: {
24+
build: {
25+
executor: 'nx:run-commands',
26+
outputs: [
27+
'dist',
28+
'dist/{projectRoot}',
29+
'dist/{projectRoot}/**/*.js',
30+
'proj/coverage',
31+
'./test-results',
32+
'{projectRoot}/build',
33+
'{options.outputDirectory}',
34+
],
35+
options: {},
36+
},
37+
},
38+
});
39+
40+
await prefixOutputs(tree);
41+
42+
const updated = readProjectConfiguration(tree, 'proj');
43+
44+
expect(updated.targets.build.outputs).toEqual([
45+
'{workspaceRoot}/dist',
46+
'{workspaceRoot}/dist/{projectRoot}',
47+
'{workspaceRoot}/dist/{projectRoot}/**/*.js',
48+
'{projectRoot}/coverage',
49+
'{projectRoot}/test-results',
50+
'{projectRoot}/build',
51+
'{options.outputDirectory}',
52+
]);
53+
54+
expect(() => validateOutputs(updated.targets.build.outputs)).not.toThrow();
55+
});
56+
57+
it('should prefix target default outputs', async () => {
58+
const nxJson = readNxJson(tree);
59+
updateNxJson(tree, {
60+
...nxJson,
61+
targetDefaults: {
62+
build: {
63+
outputs: ['dist', '{projectRoot}/build', '{options.outputPath}'],
64+
},
65+
},
66+
});
67+
68+
await prefixOutputs(tree);
69+
70+
const updated = readNxJson(tree);
71+
72+
expect(updated.targetDefaults).toMatchInlineSnapshot(`
73+
{
74+
"build": {
75+
"outputs": [
76+
"{workspaceRoot}/dist",
77+
"{projectRoot}/build",
78+
"{options.outputPath}",
79+
],
80+
},
81+
}
82+
`);
83+
});
84+
85+
it('should migrate package.json projects', async () => {
86+
writeJson(tree, 'proj/package.json', {
87+
name: 'proj',
88+
scripts: {
89+
build: 'echo',
90+
},
91+
nx: {
92+
targets: {
93+
build: {
94+
outputs: ['dist/proj', 'proj/build'],
95+
},
96+
},
97+
},
98+
});
99+
tree.delete('workspace.json');
100+
101+
await prefixOutputs(tree);
102+
103+
expect(readJson(tree, 'proj/package.json').nx.targets.build).toEqual({
104+
outputs: ['{workspaceRoot}/dist/proj', '{projectRoot}/build'],
105+
});
106+
});
107+
108+
it('should not error for package.json projects', async () => {
109+
writeJson(tree, 'proj/package.json', {
110+
name: 'proj',
111+
scripts: {
112+
build: 'echo',
113+
},
114+
});
115+
tree.delete('workspace.json');
116+
117+
await prefixOutputs(tree);
118+
});
119+
120+
it('should handle negated outputs', async () => {
121+
const nxJson = readNxJson(tree);
122+
updateNxJson(tree, {
123+
...nxJson,
124+
targetDefaults: {
125+
build: {
126+
outputs: ['!dist', '{projectRoot}/build', '{options.outputPath}'],
127+
},
128+
},
129+
});
130+
131+
await prefixOutputs(tree);
132+
133+
const updated = readNxJson(tree);
134+
135+
expect(updated.targetDefaults).toMatchInlineSnapshot(`
136+
{
137+
"build": {
138+
"outputs": [
139+
"!{workspaceRoot}/dist",
140+
"{projectRoot}/build",
141+
"{options.outputPath}",
142+
],
143+
},
144+
}
145+
`);
146+
});
147+
});
148+
149+
describe('15.0.0 migration (prefix-outputs) (v1)', () => {
150+
let tree: Tree;
151+
152+
beforeEach(() => {
153+
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
154+
});
155+
156+
it('should prefix project outputs', async () => {
157+
addProjectConfiguration(tree, 'proj', {
158+
root: 'proj',
159+
targets: {
160+
build: {
161+
executor: 'nx:run-commands',
162+
outputs: [
163+
'dist',
164+
'dist/{projectRoot}',
165+
'dist/{projectRoot}/**/*.js',
166+
'proj/coverage',
167+
'./test-results',
168+
'{projectRoot}/build',
169+
'{options.outputDirectory}',
170+
],
171+
options: {},
172+
},
173+
},
174+
});
175+
176+
await prefixOutputs(tree);
177+
178+
const updated = readProjectConfiguration(tree, 'proj');
179+
180+
expect(updated.targets.build.outputs).toEqual([
181+
'{workspaceRoot}/dist',
182+
'{workspaceRoot}/dist/{projectRoot}',
183+
'{workspaceRoot}/dist/{projectRoot}/**/*.js',
184+
'{projectRoot}/coverage',
185+
'{projectRoot}/test-results',
186+
'{projectRoot}/build',
187+
'{options.outputDirectory}',
188+
]);
189+
190+
expect(() => validateOutputs(updated.targets.build.outputs)).not.toThrow();
191+
});
192+
});
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { Tree } from '../../generators/tree';
2+
import { formatChangedFilesWithPrettierIfAvailable } from '../../generators/internal-utils/format-changed-files-with-prettier-if-available';
3+
import {
4+
getProjects,
5+
updateProjectConfiguration,
6+
} from '../../generators/utils/project-configuration';
7+
import { readNxJson, updateNxJson } from '../../generators/utils/nx-json';
8+
import { joinPathFragments } from '../../utils/path';
9+
import { join } from 'path';
10+
import {
11+
transformLegacyOutputs,
12+
validateOutputs,
13+
} from '../../tasks-runner/utils';
14+
import { updateJson } from '../../generators/utils/json';
15+
import { PackageJson } from '../../utils/package-json';
16+
17+
export default async function (tree: Tree) {
18+
// If the workspace doesn't have a nx.json, don't make any changes
19+
if (!tree.exists('nx.json')) {
20+
return;
21+
}
22+
23+
const nxJson = readNxJson(tree);
24+
25+
for (const [projectName, project] of getProjects(tree)) {
26+
for (const [_, target] of Object.entries(project.targets ?? {})) {
27+
if (!target.outputs) {
28+
continue;
29+
}
30+
31+
target.outputs = transformLegacyOutputs(project.root, target.outputs);
32+
}
33+
try {
34+
updateProjectConfiguration(tree, projectName, project);
35+
} catch {
36+
if (tree.exists(join(project.root, 'package.json'))) {
37+
updateJson<PackageJson>(
38+
tree,
39+
join(project.root, 'package.json'),
40+
(json) => {
41+
for (const target of Object.values(json.nx?.targets ?? {})) {
42+
if (target.outputs) {
43+
target.outputs = transformLegacyOutputs(
44+
project.root,
45+
target.outputs
46+
);
47+
}
48+
}
49+
50+
return json;
51+
}
52+
);
53+
}
54+
}
55+
}
56+
57+
if (nxJson.targetDefaults) {
58+
for (const [_, target] of Object.entries(nxJson.targetDefaults)) {
59+
if (!target.outputs) {
60+
continue;
61+
}
62+
target.outputs = transformLegacyOutputs('{projectRoot}', target.outputs);
63+
}
64+
65+
updateNxJson(tree, nxJson);
66+
}
67+
68+
await formatChangedFilesWithPrettierIfAvailable(tree);
69+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Tree } from '../../generators/tree';
2+
import { formatChangedFilesWithPrettierIfAvailable } from '../../generators/internal-utils/format-changed-files-with-prettier-if-available';
3+
import { updateJson } from '../../generators/utils/json';
4+
5+
export default async function (tree: Tree) {
6+
updateJson(tree, 'package.json', (json) => {
7+
for (const deps of [json.dependencies, json.devDependencies]) {
8+
if (deps) {
9+
delete deps['@nrwl/cli'];
10+
}
11+
}
12+
13+
return json;
14+
});
15+
16+
await formatChangedFilesWithPrettierIfAvailable(tree);
17+
}

0 commit comments

Comments
 (0)