Skip to content

Commit d60d374

Browse files
committed
fix(@angular/cli): error when updating Angular packages across multi-major migrations
With this change we show an error message when users try to update `@angular/` and `@nguniversal/` packages across multiple major versions.
1 parent 0ccc8d3 commit d60d374

File tree

3 files changed

+63
-144
lines changed

3 files changed

+63
-144
lines changed

packages/angular/cli/commands/update-impl.ts

+28-24
Original file line numberDiff line numberDiff line change
@@ -607,36 +607,40 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
607607
return 1;
608608
}
609609

610-
if (node.package?.name === '@angular/cli') {
611-
// Migrations for non LTS versions of Angular CLI are no longer included in @schematics/angular v12.
610+
if (manifest.version === node.package?.version) {
611+
this.logger.info(`Package '${packageName}' is already up to date.`);
612+
continue;
613+
}
614+
615+
if (node.package && /^@(?:angular|nguniversal)\//.test(node.package.name)) {
616+
const { name, version } = node.package;
612617
const toBeInstalledMajorVersion = +manifest.version.split('.')[0];
613-
const currentMajorVersion = +node.package.version.split('.')[0];
614-
if (currentMajorVersion < 10 && toBeInstalledMajorVersion >= 12) {
615-
const updateVersions: Record<number, number> = {
616-
1: 6,
617-
6: 7,
618-
7: 8,
619-
8: 9,
620-
9: 10,
621-
};
622-
623-
const updateTo = updateVersions[currentMajorVersion];
624-
this.logger.error(
625-
'Updating multiple major versions at once is not recommended. ' +
626-
`Run 'ng update @angular/cli@${updateTo}' in your workspace directory ` +
627-
`to update to latest '${updateTo}.x' version of '@angular/cli'.\n\n` +
628-
'For more information about the update process, see https://update.angular.io/.',
629-
);
618+
const currentMajorVersion = +version.split('.')[0];
619+
620+
if (toBeInstalledMajorVersion - currentMajorVersion > 1) {
621+
// Only allow updating a single version at a time.
622+
if (currentMajorVersion < 6) {
623+
// Before version 6, the major versions were not always sequential.
624+
// Example @angular/core skipped version 3, @angular/cli skipped versions 2-5.
625+
this.logger.error(
626+
`Updating multiple major versions of '${name}' at once is not supported. Please migrate each major version individually.\n` +
627+
`For more information about the update process, see https://update.angular.io/.`,
628+
);
629+
} else {
630+
const nextMajorVersionFromCurrent = currentMajorVersion + 1;
631+
632+
this.logger.error(
633+
`Updating multiple major versions of '${name}' at once is not supported. Please migrate each major version individually.\n` +
634+
`Run 'ng update ${name}@${nextMajorVersionFromCurrent}' in your workspace directory ` +
635+
`to update to latest '${nextMajorVersionFromCurrent}.x' version of '${name}'.\n\n` +
636+
`For more information about the update process, see https://update.angular.io/?v=${currentMajorVersion}.0-${nextMajorVersionFromCurrent}.0`,
637+
);
638+
}
630639

631640
return 1;
632641
}
633642
}
634643

635-
if (manifest.version === node.package?.version) {
636-
this.logger.info(`Package '${packageName}' is already up to date.`);
637-
continue;
638-
}
639-
640644
packagesToUpdate.push(requestIdentifier.toString());
641645
}
642646

packages/schematics/angular/migrations/migration-collection.json

-120
Original file line numberDiff line numberDiff line change
@@ -1,125 +1,5 @@
11
{
22
"schematics": {
3-
"lazy-loading-syntax": {
4-
"version": "9.0.0-next.6",
5-
"factory": "./update-12/update-lazy-module-paths",
6-
"description": "Lazy loading syntax migration. Update lazy loading syntax to use dynamic imports."
7-
},
8-
"tslint-version-6": {
9-
"version": "10.0.0-beta.0",
10-
"factory": "./update-10/update-tslint",
11-
"description": "Update tslint to version 6 and adjust rules to maintain existing behavior."
12-
},
13-
"rename-browserslist-config": {
14-
"version": "10.0.0-beta.0",
15-
"factory": "./update-10/rename-browserslist-config",
16-
"description": "Update Browserslist configuration file name to '.browserslistrc' from deprecated 'browserslist'."
17-
},
18-
"remove-es5-browser-support-option": {
19-
"version": "10.0.0-beta.2",
20-
"factory": "./update-10/remove-es5-browser-support",
21-
"description": "Remove deprecated 'es5BrowserSupport' browser builder option. The inclusion for ES5 polyfills will be determined from the browsers listed in the browserslist configuration."
22-
},
23-
"schematic-options-10": {
24-
"version": "10.0.0-beta.2",
25-
"factory": "./update-10/schematic-options",
26-
"description": "Replace deprecated and removed 'styleext' and 'spec' Angular schematic options with 'style' and 'skipTests', respectively."
27-
},
28-
"update-angular-config": {
29-
"version": "10.0.0-beta.6",
30-
"factory": "./update-10/update-angular-config",
31-
"description": "Remove deprecated options from 'angular.json' that are no longer present in v10."
32-
},
33-
"tslint-add-deprecation-rule": {
34-
"version": "10.0.0-beta.7",
35-
"factory": "./update-10/add-deprecation-rule-tslint",
36-
"description": "Add the tslint deprecation rule to tslint JSON configuration files."
37-
},
38-
"update-libraries-tslib": {
39-
"version": "10.0.0-beta.7",
40-
"factory": "./update-10/update-libraries-tslib",
41-
"description": "Update library projects to use tslib version 2 as a direct dependency. Read more about this here: https://v10.angular.io/guide/migration-update-libraries-tslib"
42-
},
43-
"update-workspace-dependencies": {
44-
"version": "10.0.0-rc.2",
45-
"factory": "./update-10/update-dependencies",
46-
"description": "Update workspace dependencies to match a new v10 project."
47-
},
48-
"update-module-and-target-compiler-options": {
49-
"version": "10.0.1",
50-
"factory": "./update-10/update-module-and-target-compiler-options",
51-
"description": "Update 'module' and 'target' TypeScript compiler options. Read more about this here: https://v10.angular.io/guide/migration-update-module-and-target-compiler-options"
52-
},
53-
"remove-solution-style-tsconfig": {
54-
"version": "10.1.0-next.5",
55-
"factory": "./update-10/remove-solution-style-tsconfig",
56-
"description": "Removing \"Solution Style\" TypeScript configuration file support."
57-
},
58-
"replace-ng-packagr-builder": {
59-
"version": "11.0.0-next.0",
60-
"factory": "./update-11/replace-ng-packagr-builder",
61-
"description": "Replace deprecated library builder '@angular-devkit/build-ng-packagr'."
62-
},
63-
"add-declaration-map-compiler-option": {
64-
"version": "11.0.0-next.2",
65-
"factory": "./update-11/add-declaration-map-compiler-option",
66-
"description": "Add 'declarationMap' compiler options for non production library builds."
67-
},
68-
"update-angular-config-v11": {
69-
"version": "11.0.0-next.8",
70-
"factory": "./update-11/update-angular-config",
71-
"description": "Remove deprecated options from 'angular.json' that are no longer present in v11."
72-
},
73-
"update-workspace-dependencies-v11": {
74-
"version": "11.0.0",
75-
"factory": "./update-11/update-dependencies",
76-
"description": "Update workspace dependencies to match a new v11 project."
77-
},
78-
"update-angular-config-v12": {
79-
"version": "12.0.0-next.0",
80-
"factory": "./update-12/update-angular-config",
81-
"description": "Remove deprecated options from 'angular.json' that are no longer present in v12."
82-
},
83-
"update-zonejs": {
84-
"version": "12.0.0-next.1",
85-
"factory": "./update-12/update-zonejs",
86-
"description": "Update 'zone.js' to version 0.11.x. Read more about this here: https://github.com/angular/angular/blob/master/packages/zone.js/CHANGELOG.md#breaking-changes-since-zonejs-v0111"
87-
},
88-
"remove-emit-decorator-metadata": {
89-
"version": "12.0.0-next.2",
90-
"factory": "./update-12/remove-emit-decorator-metadata",
91-
"description": "Remove 'emitDecoratorMetadata' TypeScript compiler option. Decorator metadata is no longer needed by Angular. Read more about this here: https://www.typescriptlang.org/docs/handbook/decorators.html#metadata"
92-
},
93-
"lazy-loading-string-syntax": {
94-
"version": "12.0.0-next.4",
95-
"factory": "./update-12/update-lazy-module-paths",
96-
"description": "Lazy loading syntax migration. Update lazy loading string syntax to use dynamic imports."
97-
},
98-
"remove-deprecated-i18n-options": {
99-
"version": "12.0.0-next.7",
100-
"factory": "./update-12/update-i18n",
101-
"description": "Remove deprecated ViewEngine-based i18n build and extract options. Options present in the configuration will be converted to use non-deprecated options."
102-
},
103-
"update-web-workers-webpack-5": {
104-
"version": "12.0.0-next.7",
105-
"factory": "./update-12/update-web-workers",
106-
"description": "Updates Web Worker consumer usage to use the new syntax supported directly by Webpack 5."
107-
},
108-
"schematic-options-12": {
109-
"version": "12.0.1",
110-
"factory": "./update-12/schematic-options",
111-
"description": "Remove invalid 'skipTests' option in '@schematics/angular:module' Angular schematic options."
112-
},
113-
"replace-deprecated-prod-flag": {
114-
"version": "12.1.0",
115-
"factory": "./update-12/replace-prod-flag",
116-
"description": "Replace the deprecated '--prod' in package.json scripts."
117-
},
118-
"production-by-default": {
119-
"version": "9999.0.0",
120-
"factory": "./update-12/production-default-config",
121-
"description": "Optional migration to update Angular CLI workspace configurations to 'production' mode by default."
122-
},
1233
"schematic-options-13": {
1244
"version": "13.0.0",
1255
"factory": "./update-13/schematic-options",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { createProjectFromAsset } from '../../utils/assets';
2+
import { installWorkspacePackages, setRegistry } from '../../utils/packages';
3+
import { ng } from '../../utils/process';
4+
import { isPrereleaseCli } from '../../utils/project';
5+
import { expectToFail } from '../../utils/utils';
6+
7+
export default async function () {
8+
try {
9+
await createProjectFromAsset('9.0-project', true, true);
10+
await setRegistry(false);
11+
await installWorkspacePackages();
12+
13+
await setRegistry(true);
14+
const extraArgs = ['--force'];
15+
if (isPrereleaseCli()) {
16+
extraArgs.push('--next');
17+
}
18+
19+
const { message } = await expectToFail(() =>
20+
ng('update', '@angular/cli', '--force', ...extraArgs),
21+
);
22+
if (
23+
!message.includes(
24+
`Updating multiple major versions of '@angular/cli' at once is not supported`,
25+
)
26+
) {
27+
console.error(message);
28+
throw new Error(
29+
`Expected error message to include "Updating multiple major versions of '@angular/cli' at once is not supported" but didn't.`,
30+
);
31+
}
32+
} finally {
33+
await setRegistry(true);
34+
}
35+
}

0 commit comments

Comments
 (0)