Skip to content

Commit

Permalink
fix(@angular/cli): verify Angular/TS version combos
Browse files Browse the repository at this point in the history
  • Loading branch information
filipesilva committed Sep 7, 2017
1 parent d1adc8c commit ca344b1
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 5 deletions.
3 changes: 2 additions & 1 deletion packages/@angular/cli/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,9 @@ const BuildCommand = Command.extend({
]),

run: function (commandOptions: BuildTaskOptions) {
// Check angular version.
// Check Angular and TypeScript versions.
Version.assertAngularVersionIs2_3_1OrHigher(this.project.root);
Version.assertTypescriptVersion(this.project.root);

// Default vendor chunk to false when build optimizer is on.
if (commandOptions.vendorChunk === undefined) {
Expand Down
2 changes: 2 additions & 0 deletions packages/@angular/cli/commands/serve.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,9 @@ const ServeCommand = Command.extend({
run: function (commandOptions: ServeTaskOptions) {
const ServeTask = require('../tasks/serve').default;

// Check Angular and TypeScript versions.
Version.assertAngularVersionIs2_3_1OrHigher(this.project.root);
Version.assertTypescriptVersion(this.project.root);

// Default vendor chunk to false when build optimizer is on.
if (commandOptions.vendorChunk === undefined) {
Expand Down
5 changes: 5 additions & 0 deletions packages/@angular/cli/lib/config/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,11 @@
"description": "Show a warning when the global version is newer than the local one.",
"type": "boolean",
"default": true
},
"typescriptMismatch": {
"description": "Show a warning when the TypeScript version is incompatible",
"type": "boolean",
"default": true
}
}
}
Expand Down
48 changes: 46 additions & 2 deletions packages/@angular/cli/upgrade/version.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {SemVer} from 'semver';
import {SemVer, satisfies} from 'semver';
import {bold, red, yellow} from 'chalk';
import {stripIndents} from 'common-tags';
import {stripIndents, stripIndent} from 'common-tags';
import {readFileSync, existsSync} from 'fs';
import * as path from 'path';

Expand Down Expand Up @@ -143,6 +143,50 @@ export class Version {
}
}

static assertTypescriptVersion(projectRoot: string) {
if (!CliConfig.fromGlobal().get('warnings.typescriptMismatch')) {
return;
}
let compilerVersion: string, tsVersion: string;
try {
compilerVersion = requireProjectModule(projectRoot, '@angular/compiler-cli').VERSION.full;
tsVersion = requireProjectModule(projectRoot, 'typescript').version;
} catch (_) {
console.error(bold(red(stripIndents`
Versions of @angular/compiler-cli and typescript could not be determined.
The most common reason for this is a broken npm install.
Please make sure your package.json contains both @angular/compiler-cli and typescript in
devDependencies, then delete node_modules and package-lock.json (if you have one) and
run npm install again.
`)));
process.exit(2);
}

const versionCombos = [
{ compiler: '>=2.3.1 <3.0.0', typescript: '>=2.0.2 <2.3.0' },
{ compiler: '>=4.0.0 <5.0.0', typescript: '>=2.1.0 <2.4.0' },
{ compiler: '>=5.0.0 <6.0.0', typescript: '>=2.4.0 <2.6.0' }
];

const currentCombo = versionCombos.find((combo) => satisfies(compilerVersion, combo.compiler));

if (currentCombo && !satisfies(tsVersion, currentCombo.typescript)) {
// First line of warning looks weird being split in two, disable tslint for it.
console.log((yellow('\n' + stripIndent`
@angular/compiler-cli@${compilerVersion} requires typescript@'${
currentCombo.typescript}' but ${tsVersion} was found instead.
Using this version can result in undefined behaviour and difficult to debug problems.
Please run the following command to install a compatible version of TypeScript.
npm install typescript@'${currentCombo.typescript}'
To disable this warning run "ng set --global warnings.typescriptMismatch=false".
` + '\n')));
}
}

static isPreWebpack(): boolean {
// CliConfig is a bit stricter with the schema, so we need to be a little looser with it.
const version = Version.fromProject();
Expand Down
41 changes: 41 additions & 0 deletions tests/e2e/tests/misc/typescript-warning.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { ng, npm } from '../../utils/process';
import { getGlobalVariable } from '../../utils/env';


export default function () {
// typescript@2.5 is not part of the officially supported range in latest stable.
// Update as needed.
let unsupportedTsVersion = '2.5';

// Skip this in Appveyor tests.
if (getGlobalVariable('argv').nightly) {
unsupportedTsVersion = '2.3';
}

return Promise.resolve()
.then(() => npm('uninstall', 'typescript', '--no-save'))
.then(() => ng('build'))
.catch((err) => {
if (!err.message.match('Versions of @angular/compiler-cli and typescript could not')) {
throw new Error('Expected to have missing dependency error in output.');
}
})
.then(() => npm('install', `typescript@${unsupportedTsVersion}`, '--no-save'))
.then(() => ng('build'))
.then((output) => {
if (!output.stdout.match('Using this version can result in undefined behaviour')) {
throw new Error('Expected to have typescript version mismatch warning in output.');
}
})
.then(() => ng('set', '--global', 'warnings.typescriptMismatch=false'))
.then(() => ng('build'))
.then((output) => {
if (output.stdout.match('Using this version can result in undefined behaviour')) {
throw new Error('Expected to not have typescript version mismatch warning in output.');
}
})
// Cleanup
.then(() => npm('install'))
.then(() => ng('set', '--global', 'warnings.typescriptMismatch=true'));
}

4 changes: 2 additions & 2 deletions tests/e2e/utils/process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ function _exec(options: ExecOptions, cmd: string, args: string[]): Promise<Proce
_processes = _processes.filter(p => p !== childProcess);

if (!error) {
resolve({ stdout });
resolve({ stdout, stderr });
} else {
err.message += `${error}...\n\nSTDOUT:\n${stdout}\n`;
err.message += `${error}...\n\nSTDOUT:\n${stdout}\n\nSTDERR:\n${stderr}\n`;
reject(err);
}
});
Expand Down

0 comments on commit ca344b1

Please sign in to comment.