mirror of
https://github.com/angular/angular-cli.git
synced 2025-05-17 02:54:21 +08:00
feat(@angular/cli): verify Angular version is supported
This commit is contained in:
parent
bab9eb6b06
commit
5ec27db6bc
@ -95,7 +95,7 @@
|
|||||||
"@types/minimist": "^1.2.0",
|
"@types/minimist": "^1.2.0",
|
||||||
"@types/node": "10.9.4",
|
"@types/node": "10.9.4",
|
||||||
"@types/request": "^2.47.1",
|
"@types/request": "^2.47.1",
|
||||||
"@types/semver": "^5.5.0",
|
"@types/semver": "^6.0.0",
|
||||||
"@types/source-map": "0.5.2",
|
"@types/source-map": "0.5.2",
|
||||||
"@types/webpack": "^4.4.11",
|
"@types/webpack": "^4.4.11",
|
||||||
"@types/webpack-dev-server": "^3.1.0",
|
"@types/webpack-dev-server": "^3.1.0",
|
||||||
@ -122,7 +122,7 @@
|
|||||||
"pidtree": "^0.3.0",
|
"pidtree": "^0.3.0",
|
||||||
"pidusage": "^2.0.17",
|
"pidusage": "^2.0.17",
|
||||||
"rxjs": "~6.4.0",
|
"rxjs": "~6.4.0",
|
||||||
"semver": "^5.3.0",
|
"semver": "6.0.0",
|
||||||
"source-map": "^0.5.6",
|
"source-map": "^0.5.6",
|
||||||
"source-map-support": "^0.5.0",
|
"source-map-support": "^0.5.0",
|
||||||
"spdx-satisfies": "^4.0.0",
|
"spdx-satisfies": "^4.0.0",
|
||||||
|
@ -8,16 +8,12 @@
|
|||||||
import { analytics } from '@angular-devkit/core';
|
import { analytics } from '@angular-devkit/core';
|
||||||
import { ArchitectCommand, ArchitectCommandOptions } from '../models/architect-command';
|
import { ArchitectCommand, ArchitectCommandOptions } from '../models/architect-command';
|
||||||
import { Arguments } from '../models/interface';
|
import { Arguments } from '../models/interface';
|
||||||
import { Version } from '../upgrade/version';
|
|
||||||
import { Schema as BuildCommandSchema } from './build';
|
import { Schema as BuildCommandSchema } from './build';
|
||||||
|
|
||||||
export class BuildCommand extends ArchitectCommand<BuildCommandSchema> {
|
export class BuildCommand extends ArchitectCommand<BuildCommandSchema> {
|
||||||
public readonly target = 'build';
|
public readonly target = 'build';
|
||||||
|
|
||||||
public async run(options: ArchitectCommandOptions & Arguments) {
|
public async run(options: ArchitectCommandOptions & Arguments) {
|
||||||
// Check Angular version.
|
|
||||||
Version.assertCompatibleAngularVersion(this.workspace.root);
|
|
||||||
|
|
||||||
return this.runArchitectTarget(options);
|
return this.runArchitectTarget(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,6 @@
|
|||||||
import { analytics } from '@angular-devkit/core';
|
import { analytics } from '@angular-devkit/core';
|
||||||
import { ArchitectCommand, ArchitectCommandOptions } from '../models/architect-command';
|
import { ArchitectCommand, ArchitectCommandOptions } from '../models/architect-command';
|
||||||
import { Arguments } from '../models/interface';
|
import { Arguments } from '../models/interface';
|
||||||
import { Version } from '../upgrade/version';
|
|
||||||
import { Schema as BuildCommandSchema } from './build';
|
import { Schema as BuildCommandSchema } from './build';
|
||||||
import { Schema as ServeCommandSchema } from './serve';
|
import { Schema as ServeCommandSchema } from './serve';
|
||||||
|
|
||||||
@ -16,9 +15,6 @@ export class ServeCommand extends ArchitectCommand<ServeCommandSchema> {
|
|||||||
public readonly target = 'serve';
|
public readonly target = 'serve';
|
||||||
|
|
||||||
public validate(_options: ArchitectCommandOptions & Arguments) {
|
public validate(_options: ArchitectCommandOptions & Arguments) {
|
||||||
// Check Angular versions.
|
|
||||||
Version.assertCompatibleAngularVersion(this.workspace.root);
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ import { Architect, Target } from '@angular-devkit/architect';
|
|||||||
import { WorkspaceNodeModulesArchitectHost } from '@angular-devkit/architect/node';
|
import { WorkspaceNodeModulesArchitectHost } from '@angular-devkit/architect/node';
|
||||||
import { experimental, json, schema, tags } from '@angular-devkit/core';
|
import { experimental, json, schema, tags } from '@angular-devkit/core';
|
||||||
import { NodeJsSyncHost } from '@angular-devkit/core/node';
|
import { NodeJsSyncHost } from '@angular-devkit/core/node';
|
||||||
|
import { Version } from '../upgrade/version';
|
||||||
import { BepJsonWriter } from '../utilities/bep';
|
import { BepJsonWriter } from '../utilities/bep';
|
||||||
import { parseJsonSchemaToOptions } from '../utilities/json-schema';
|
import { parseJsonSchemaToOptions } from '../utilities/json-schema';
|
||||||
import { isPackageNameSafeForAnalytics } from './analytics';
|
import { isPackageNameSafeForAnalytics } from './analytics';
|
||||||
@ -274,6 +275,9 @@ export abstract class ArchitectCommand<
|
|||||||
protected async runArchitectTarget(
|
protected async runArchitectTarget(
|
||||||
options: ArchitectCommandOptions & Arguments,
|
options: ArchitectCommandOptions & Arguments,
|
||||||
): Promise<number> {
|
): Promise<number> {
|
||||||
|
// Check Angular version.
|
||||||
|
Version.assertCompatibleAngularVersion(this.workspace.root);
|
||||||
|
|
||||||
const extra = options['--'] || [];
|
const extra = options['--'] || [];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
import { tags, terminal } from '@angular-devkit/core';
|
import { tags, terminal } from '@angular-devkit/core';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
import { SemVer } from 'semver';
|
import { SemVer, satisfies } from 'semver';
|
||||||
|
|
||||||
|
|
||||||
export class Version {
|
export class Version {
|
||||||
@ -26,6 +26,12 @@ export class Version {
|
|||||||
isGreaterThanOrEqualTo(other: SemVer) {
|
isGreaterThanOrEqualTo(other: SemVer) {
|
||||||
return this._semver !== null && this._semver.compare(other) >= 0;
|
return this._semver !== null && this._semver.compare(other) >= 0;
|
||||||
}
|
}
|
||||||
|
satisfies(other: string) {
|
||||||
|
// This comparison includes pre-releases (like betas and rcs), and considers them to be
|
||||||
|
// before the release proper.
|
||||||
|
// e.g. '9.0.0-beta.1' will satisfy '>=7.0.0 <9.0.0', but '9.0.0' will not.
|
||||||
|
return this._semver !== null && satisfies(this._semver, other, { includePrerelease: true });
|
||||||
|
}
|
||||||
|
|
||||||
get major() { return this._semver ? this._semver.major : 0; }
|
get major() { return this._semver ? this._semver.major : 0; }
|
||||||
get minor() { return this._semver ? this._semver.minor : 0; }
|
get minor() { return this._semver ? this._semver.minor : 0; }
|
||||||
@ -36,11 +42,12 @@ export class Version {
|
|||||||
toString() { return this._version; }
|
toString() { return this._version; }
|
||||||
|
|
||||||
static assertCompatibleAngularVersion(projectRoot: string) {
|
static assertCompatibleAngularVersion(projectRoot: string) {
|
||||||
|
let angularCliPkgJson;
|
||||||
let angularPkgJson;
|
let angularPkgJson;
|
||||||
let rxjsPkgJson;
|
let rxjsPkgJson;
|
||||||
|
const resolveOptions = { paths: [projectRoot] };
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resolveOptions = { paths: [projectRoot] };
|
|
||||||
const angularPackagePath = require.resolve('@angular/core/package.json', resolveOptions);
|
const angularPackagePath = require.resolve('@angular/core/package.json', resolveOptions);
|
||||||
const rxjsPackagePath = require.resolve('rxjs/package.json', resolveOptions);
|
const rxjsPackagePath = require.resolve('rxjs/package.json', resolveOptions);
|
||||||
|
|
||||||
@ -61,6 +68,26 @@ export class Version {
|
|||||||
process.exit(2);
|
process.exit(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const angularCliPkgPath = require.resolve('@angular/cli/package.json', resolveOptions);
|
||||||
|
angularCliPkgJson = require(angularCliPkgPath);
|
||||||
|
if (!(angularCliPkgJson && angularCliPkgJson['version'])) {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(terminal.bold(terminal.red(tags.stripIndents`
|
||||||
|
Cannot determine versions of "@angular/cli".
|
||||||
|
This likely means your local installation is broken. Please reinstall your packages.
|
||||||
|
`)));
|
||||||
|
process.exit(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
const cliMajor = new Version(angularCliPkgJson['version']).major;
|
||||||
|
// e.g. CLI 8.0 supports '>=8.0.0 <9.0.0', including pre-releases (betas, rcs, snapshots)
|
||||||
|
// of both 8 and 9.
|
||||||
|
const supportedAngularSemver = `^${cliMajor}.0.0-beta || ` +
|
||||||
|
`>=${cliMajor}.0.0 <${cliMajor + 1}.0.0`;
|
||||||
|
|
||||||
const angularVersion = new Version(angularPkgJson['version']);
|
const angularVersion = new Version(angularPkgJson['version']);
|
||||||
const rxjsVersion = new Version(rxjsPkgJson['version']);
|
const rxjsVersion = new Version(rxjsPkgJson['version']);
|
||||||
|
|
||||||
@ -70,9 +97,10 @@ export class Version {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!angularVersion.isGreaterThanOrEqualTo(new SemVer('5.0.0'))) {
|
if (!angularVersion.satisfies(supportedAngularSemver)) {
|
||||||
console.error(terminal.bold(terminal.red(tags.stripIndents`
|
console.error(terminal.bold(terminal.red(tags.stripIndents`
|
||||||
This version of CLI is only compatible with Angular version 5.0.0 or higher.
|
This version of CLI is only compatible with Angular versions ${supportedAngularSemver},
|
||||||
|
but Angular version ${angularVersion} was found instead.
|
||||||
|
|
||||||
Please visit the link below to find instructions on how to update Angular.
|
Please visit the link below to find instructions on how to update Angular.
|
||||||
https://angular-update-guide.firebaseapp.com/
|
https://angular-update-guide.firebaseapp.com/
|
||||||
@ -84,7 +112,7 @@ export class Version {
|
|||||||
&& !rxjsVersion.isGreaterThanOrEqualTo(new SemVer('6.0.0-beta.0'))
|
&& !rxjsVersion.isGreaterThanOrEqualTo(new SemVer('6.0.0-beta.0'))
|
||||||
) {
|
) {
|
||||||
console.error(terminal.bold(terminal.red(tags.stripIndents`
|
console.error(terminal.bold(terminal.red(tags.stripIndents`
|
||||||
This project uses version ${rxjsVersion} of RxJs, which is not supported by Angular v6.
|
This project uses version ${rxjsVersion} of RxJs, which is not supported by Angular v6+.
|
||||||
The official RxJs version that is supported is 5.6.0-forward-compat.0 and greater.
|
The official RxJs version that is supported is 5.6.0-forward-compat.0 and greater.
|
||||||
|
|
||||||
Please visit the link below to find instructions on how to update RxJs.
|
Please visit the link below to find instructions on how to update RxJs.
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
import { HttpModule } from '@angular/http';
|
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
|
|
||||||
@ -12,7 +11,6 @@ import { AppComponent } from './app.component';
|
|||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
FormsModule,
|
FormsModule,
|
||||||
HttpModule
|
|
||||||
],
|
],
|
||||||
providers: [],
|
providers: [],
|
||||||
bootstrap: [AppComponent]
|
bootstrap: [AppComponent]
|
||||||
|
@ -7,7 +7,7 @@ import { expectToFail } from '../../utils/utils';
|
|||||||
|
|
||||||
|
|
||||||
export default async function () {
|
export default async function () {
|
||||||
const extraUpdateArgs = await isPrereleaseCli() ? ['--next'] : [];
|
const extraUpdateArgs = await isPrereleaseCli() ? ['--next', '--force'] : [];
|
||||||
|
|
||||||
await createProjectFromAsset('1.0-project');
|
await createProjectFromAsset('1.0-project');
|
||||||
await useCIChrome('.');
|
await useCIChrome('.');
|
||||||
|
@ -5,7 +5,7 @@ import { expectToFail } from '../../utils/utils';
|
|||||||
|
|
||||||
|
|
||||||
export default async function () {
|
export default async function () {
|
||||||
const extraUpdateArgs = await isPrereleaseCli() ? ['--next'] : [];
|
const extraUpdateArgs = await isPrereleaseCli() ? ['--next', '--force'] : [];
|
||||||
|
|
||||||
await createProjectFromAsset('1.7-project');
|
await createProjectFromAsset('1.7-project');
|
||||||
await expectToFail(() => ng('build'));
|
await expectToFail(() => ng('build'));
|
||||||
|
@ -7,7 +7,7 @@ import { expectToFail } from '../../utils/utils';
|
|||||||
|
|
||||||
|
|
||||||
export default async function () {
|
export default async function () {
|
||||||
const extraUpdateArgs = await isPrereleaseCli() ? ['--next'] : [];
|
const extraUpdateArgs = await isPrereleaseCli() ? ['--next', '--force'] : [];
|
||||||
|
|
||||||
await createProjectFromAsset('1.7-project');
|
await createProjectFromAsset('1.7-project');
|
||||||
await useCIChrome('.');
|
await useCIChrome('.');
|
||||||
|
38
tests/legacy-cli/e2e/tests/misc/supported-angular.ts
Normal file
38
tests/legacy-cli/e2e/tests/misc/supported-angular.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
import { SemVer } from 'semver';
|
||||||
|
import { getGlobalVariable } from '../../utils/env';
|
||||||
|
import { readFile, writeFile } from '../../utils/fs';
|
||||||
|
import { ng } from '../../utils/process';
|
||||||
|
import { expectToFail } from '../../utils/utils';
|
||||||
|
|
||||||
|
|
||||||
|
export default async function () {
|
||||||
|
if (getGlobalVariable('argv')['ng-snapshots'] || getGlobalVariable('argv')['ivy']) {
|
||||||
|
// Don't run this test in snapshots or Ivy test jobs.
|
||||||
|
// The snapshots job won't work correctly because it doesn't use semver for Angular, and the
|
||||||
|
// Ivy job will fail because Ivy wasn't stable in 7.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const angularCliPkgJson = JSON.parse(await readFile('node_modules/@angular/cli/package.json'));
|
||||||
|
const cliMajor = new SemVer(angularCliPkgJson.version as string).major;
|
||||||
|
const angularCorePkgPath = 'node_modules/@angular/core/package.json';
|
||||||
|
const originalAngularCorePkgJson = await readFile(angularCorePkgPath);
|
||||||
|
|
||||||
|
// Fake version by writing over the @angular/core version, since that's what the CLI checks.
|
||||||
|
const fakeCoreVersion = async (newMajor: number) => {
|
||||||
|
const tmpPkgJson = JSON.parse(originalAngularCorePkgJson);
|
||||||
|
tmpPkgJson.version = `${newMajor}.0.0`;
|
||||||
|
await writeFile(angularCorePkgPath, JSON.stringify(tmpPkgJson));
|
||||||
|
};
|
||||||
|
|
||||||
|
// Major should succeed, but we don't need to test it here since it's tested everywhere else.
|
||||||
|
// Major+1 and -1 should fail architect commands, but allow other commands.
|
||||||
|
await fakeCoreVersion(cliMajor + 1);
|
||||||
|
await expectToFail(() => ng('build'), 'Should fail Major+1');
|
||||||
|
await ng('version');
|
||||||
|
await fakeCoreVersion(cliMajor - 1);
|
||||||
|
await ng('version');
|
||||||
|
|
||||||
|
// Restore the original core package.json.
|
||||||
|
await writeFile(angularCorePkgPath, originalAngularCorePkgJson);
|
||||||
|
}
|
@ -548,10 +548,10 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.12.tgz#6affe5aed1ba379175075a889adbe2bc3aa62159"
|
resolved "https://registry.yarnpkg.com/@types/selenium-webdriver/-/selenium-webdriver-3.0.12.tgz#6affe5aed1ba379175075a889adbe2bc3aa62159"
|
||||||
integrity sha512-hYn+eoOehVUIdMwp5h34ZsGAO1ydja10GDup4BwyoFCdcH5MQ35nQq+AInSaBMEMopD5hEooFCyKo2Pajbe1ag==
|
integrity sha512-hYn+eoOehVUIdMwp5h34ZsGAO1ydja10GDup4BwyoFCdcH5MQ35nQq+AInSaBMEMopD5hEooFCyKo2Pajbe1ag==
|
||||||
|
|
||||||
"@types/semver@^5.5.0":
|
"@types/semver@^6.0.0":
|
||||||
version "5.5.0"
|
version "6.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-5.5.0.tgz#146c2a29ee7d3bae4bf2fcb274636e264c813c45"
|
resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.0.0.tgz#86ba89f02a414e39c68d02b351872e4ed31bd773"
|
||||||
integrity sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==
|
integrity sha512-OO0srjOGH99a4LUN2its3+r6CBYcplhJ466yLqs+zvAWgphCpS8hYZEZ797tRDP/QKcqTdb/YCN6ifASoAWkrQ==
|
||||||
|
|
||||||
"@types/serve-static@*":
|
"@types/serve-static@*":
|
||||||
version "1.13.2"
|
version "1.13.2"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user