Skip to content

Commit

Permalink
fix(@angular/cli): error when updating Angular packages across multi-…
Browse files Browse the repository at this point in the history
…major migrations

With this change we show an error message when users try to update `@angular/` and `@nguniversal/` packages across multiple major versions.

(cherry picked from commit 57d7eb5)
  • Loading branch information
alan-agius4 authored and filipesilva committed Oct 26, 2021
1 parent 964a73f commit 5ad1457
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 144 deletions.
52 changes: 28 additions & 24 deletions packages/angular/cli/commands/update-impl.ts
Expand Up @@ -607,36 +607,40 @@ export class UpdateCommand extends Command<UpdateCommandSchema> {
return 1;
}

if (node.package?.name === '@angular/cli') {
// Migrations for non LTS versions of Angular CLI are no longer included in @schematics/angular v12.
if (manifest.version === node.package?.version) {
this.logger.info(`Package '${packageName}' is already up to date.`);
continue;
}

if (node.package && /^@(?:angular|nguniversal)\//.test(node.package.name)) {
const { name, version } = node.package;
const toBeInstalledMajorVersion = +manifest.version.split('.')[0];
const currentMajorVersion = +node.package.version.split('.')[0];
if (currentMajorVersion < 10 && toBeInstalledMajorVersion >= 12) {
const updateVersions: Record<number, number> = {
1: 6,
6: 7,
7: 8,
8: 9,
9: 10,
};

const updateTo = updateVersions[currentMajorVersion];
this.logger.error(
'Updating multiple major versions at once is not recommended. ' +
`Run 'ng update @angular/cli@${updateTo}' in your workspace directory ` +
`to update to latest '${updateTo}.x' version of '@angular/cli'.\n\n` +
'For more information about the update process, see https://update.angular.io/.',
);
const currentMajorVersion = +version.split('.')[0];

if (toBeInstalledMajorVersion - currentMajorVersion > 1) {
// Only allow updating a single version at a time.
if (currentMajorVersion < 6) {
// Before version 6, the major versions were not always sequential.
// Example @angular/core skipped version 3, @angular/cli skipped versions 2-5.
this.logger.error(
`Updating multiple major versions of '${name}' at once is not supported. Please migrate each major version individually.\n` +
`For more information about the update process, see https://update.angular.io/.`,
);
} else {
const nextMajorVersionFromCurrent = currentMajorVersion + 1;

this.logger.error(
`Updating multiple major versions of '${name}' at once is not supported. Please migrate each major version individually.\n` +
`Run 'ng update ${name}@${nextMajorVersionFromCurrent}' in your workspace directory ` +
`to update to latest '${nextMajorVersionFromCurrent}.x' version of '${name}'.\n\n` +
`For more information about the update process, see https://update.angular.io/?v=${currentMajorVersion}.0-${nextMajorVersionFromCurrent}.0`,
);
}

return 1;
}
}

if (manifest.version === node.package?.version) {
this.logger.info(`Package '${packageName}' is already up to date.`);
continue;
}

packagesToUpdate.push(requestIdentifier.toString());
}

Expand Down
120 changes: 0 additions & 120 deletions packages/schematics/angular/migrations/migration-collection.json
@@ -1,125 +1,5 @@
{
"schematics": {
"lazy-loading-syntax": {
"version": "9.0.0-next.6",
"factory": "./update-12/update-lazy-module-paths",
"description": "Lazy loading syntax migration. Update lazy loading syntax to use dynamic imports."
},
"tslint-version-6": {
"version": "10.0.0-beta.0",
"factory": "./update-10/update-tslint",
"description": "Update tslint to version 6 and adjust rules to maintain existing behavior."
},
"rename-browserslist-config": {
"version": "10.0.0-beta.0",
"factory": "./update-10/rename-browserslist-config",
"description": "Update Browserslist configuration file name to '.browserslistrc' from deprecated 'browserslist'."
},
"remove-es5-browser-support-option": {
"version": "10.0.0-beta.2",
"factory": "./update-10/remove-es5-browser-support",
"description": "Remove deprecated 'es5BrowserSupport' browser builder option. The inclusion for ES5 polyfills will be determined from the browsers listed in the browserslist configuration."
},
"schematic-options-10": {
"version": "10.0.0-beta.2",
"factory": "./update-10/schematic-options",
"description": "Replace deprecated and removed 'styleext' and 'spec' Angular schematic options with 'style' and 'skipTests', respectively."
},
"update-angular-config": {
"version": "10.0.0-beta.6",
"factory": "./update-10/update-angular-config",
"description": "Remove deprecated options from 'angular.json' that are no longer present in v10."
},
"tslint-add-deprecation-rule": {
"version": "10.0.0-beta.7",
"factory": "./update-10/add-deprecation-rule-tslint",
"description": "Add the tslint deprecation rule to tslint JSON configuration files."
},
"update-libraries-tslib": {
"version": "10.0.0-beta.7",
"factory": "./update-10/update-libraries-tslib",
"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"
},
"update-workspace-dependencies": {
"version": "10.0.0-rc.2",
"factory": "./update-10/update-dependencies",
"description": "Update workspace dependencies to match a new v10 project."
},
"update-module-and-target-compiler-options": {
"version": "10.0.1",
"factory": "./update-10/update-module-and-target-compiler-options",
"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"
},
"remove-solution-style-tsconfig": {
"version": "10.1.0-next.5",
"factory": "./update-10/remove-solution-style-tsconfig",
"description": "Removing \"Solution Style\" TypeScript configuration file support."
},
"replace-ng-packagr-builder": {
"version": "11.0.0-next.0",
"factory": "./update-11/replace-ng-packagr-builder",
"description": "Replace deprecated library builder '@angular-devkit/build-ng-packagr'."
},
"add-declaration-map-compiler-option": {
"version": "11.0.0-next.2",
"factory": "./update-11/add-declaration-map-compiler-option",
"description": "Add 'declarationMap' compiler options for non production library builds."
},
"update-angular-config-v11": {
"version": "11.0.0-next.8",
"factory": "./update-11/update-angular-config",
"description": "Remove deprecated options from 'angular.json' that are no longer present in v11."
},
"update-workspace-dependencies-v11": {
"version": "11.0.0",
"factory": "./update-11/update-dependencies",
"description": "Update workspace dependencies to match a new v11 project."
},
"update-angular-config-v12": {
"version": "12.0.0-next.0",
"factory": "./update-12/update-angular-config",
"description": "Remove deprecated options from 'angular.json' that are no longer present in v12."
},
"update-zonejs": {
"version": "12.0.0-next.1",
"factory": "./update-12/update-zonejs",
"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"
},
"remove-emit-decorator-metadata": {
"version": "12.0.0-next.2",
"factory": "./update-12/remove-emit-decorator-metadata",
"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"
},
"lazy-loading-string-syntax": {
"version": "12.0.0-next.4",
"factory": "./update-12/update-lazy-module-paths",
"description": "Lazy loading syntax migration. Update lazy loading string syntax to use dynamic imports."
},
"remove-deprecated-i18n-options": {
"version": "12.0.0-next.7",
"factory": "./update-12/update-i18n",
"description": "Remove deprecated ViewEngine-based i18n build and extract options. Options present in the configuration will be converted to use non-deprecated options."
},
"update-web-workers-webpack-5": {
"version": "12.0.0-next.7",
"factory": "./update-12/update-web-workers",
"description": "Updates Web Worker consumer usage to use the new syntax supported directly by Webpack 5."
},
"schematic-options-12": {
"version": "12.0.1",
"factory": "./update-12/schematic-options",
"description": "Remove invalid 'skipTests' option in '@schematics/angular:module' Angular schematic options."
},
"replace-deprecated-prod-flag": {
"version": "12.1.0",
"factory": "./update-12/replace-prod-flag",
"description": "Replace the deprecated '--prod' in package.json scripts."
},
"production-by-default": {
"version": "9999.0.0",
"factory": "./update-12/production-default-config",
"description": "Optional migration to update Angular CLI workspace configurations to 'production' mode by default."
},
"schematic-options-13": {
"version": "13.0.0",
"factory": "./update-13/schematic-options",
Expand Down
35 changes: 35 additions & 0 deletions tests/legacy-cli/e2e/tests/update/update-multiple-versions.ts
@@ -0,0 +1,35 @@
import { createProjectFromAsset } from '../../utils/assets';
import { installWorkspacePackages, setRegistry } from '../../utils/packages';
import { ng } from '../../utils/process';
import { isPrereleaseCli } from '../../utils/project';
import { expectToFail } from '../../utils/utils';

export default async function () {
try {
await createProjectFromAsset('9.0-project', true, true);
await setRegistry(false);
await installWorkspacePackages();

await setRegistry(true);
const extraArgs = ['--force'];
if (isPrereleaseCli()) {
extraArgs.push('--next');
}

const { message } = await expectToFail(() =>
ng('update', '@angular/cli', '--force', ...extraArgs),
);
if (
!message.includes(
`Updating multiple major versions of '@angular/cli' at once is not supported`,
)
) {
console.error(message);
throw new Error(
`Expected error message to include "Updating multiple major versions of '@angular/cli' at once is not supported" but didn't.`,
);
}
} finally {
await setRegistry(true);
}
}

0 comments on commit 5ad1457

Please sign in to comment.