diff --git a/packages/angular/cli/commands/update-impl.ts b/packages/angular/cli/commands/update-impl.ts index ef916346ce55..1cded7d0842c 100644 --- a/packages/angular/cli/commands/update-impl.ts +++ b/packages/angular/cli/commands/update-impl.ts @@ -612,35 +612,40 @@ export class UpdateCommand extends Command { 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 < 9 && toBeInstalledMajorVersion >= 12) { - const updateVersions: Record = { - 1: 6, - 6: 7, - 7: 8, - 8: 9, - }; - - 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()); } diff --git a/tests/legacy-cli/e2e/tests/update/update-multiple-versions.ts b/tests/legacy-cli/e2e/tests/update/update-multiple-versions.ts new file mode 100644 index 000000000000..9d59214e57a0 --- /dev/null +++ b/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('8.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); + } +}