Skip to content

Commit fb5405e

Browse files
committed
MC-3095: Display TypeScript errors within local build process
- Display TypeScript errors whilst conducting a build
1 parent bf872ae commit fb5405e

File tree

5 files changed

+4274
-6
lines changed

5 files changed

+4274
-6
lines changed

gulpfile.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ const gulp = require('gulp'),
33
fs = require('fs'),
44
plugins = require('gulp-load-plugins')(),
55
header = require('gulp-header'),
6-
newer = require('gulp-newer');
6+
newer = require('gulp-newer'),
7+
shell = require('gulp-shell');
78

89
const config = {
910
basePath: 'app/code/Magento/PageBuilder',
@@ -14,7 +15,7 @@ const config = {
1415
};
1516

1617
const buildTask = function(inputStream, done) {
17-
return inputStream
18+
const stream = inputStream
1819
.pipe(plugins.if(config.sourceMaps, plugins.sourcemaps.init()))
1920
.pipe(plugins.babel()).on("error", function(error) {
2021
done(error);
@@ -24,14 +25,21 @@ const buildTask = function(inputStream, done) {
2425
includeContent: false,
2526
sourceRoot: './ts'
2627
})))
27-
.pipe(gulp.dest(path.join(config.basePath, config.buildPath)))
28+
.pipe(gulp.dest(path.join(config.basePath, config.buildPath)));
29+
gulp.start('errors');
30+
return stream;
2831
};
2932

3033
/**
3134
* Run an initial build than watch for changes
3235
*/
3336
gulp.task('default', ['build', 'watch']);
3437

38+
/**
39+
* Check for any new errors introduced since last build
40+
*/
41+
gulp.task('errors', shell.task("npm run-script ts:errors"));
42+
3543
/**
3644
* Build the TypeScript files into production JS
3745
*/

package.json

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
"scripts": {
66
"gulp": "gulp",
77
"gulpDebug": "node $NODE_DEBUG_OPTION ./node_modules/.bin/gulp",
8-
"test:static": "tslint --project tsconfig.json",
9-
"test:static:log": "npm run test:static -- -o ./static-error-log.xml -t junit"
8+
"test:static": "npm run ts:errors && tslint --project tsconfig.json",
9+
"test:static:log": "npm run test:static -- -o ./static-error-log.xml -t junit",
10+
"ts:errors": "tsc --noEmit | node ts-error-stopgap.js"
1011
},
1112
"devDependencies": {
1213
"@types/jquery": "1.10.27",
@@ -22,20 +23,23 @@
2223
"babel-plugin-transform-typescript": "^7.0.0-beta.3",
2324
"babel-preset-env": "^7.0.0-beta.3",
2425
"babel-preset-es6-to-magento-amd": "https://github.com/magento/babel-preset-es6-to-magento-amd.git",
26+
"chalk": "^2.4.1",
2527
"gulp": "^3.9.1",
2628
"gulp-babel": "^7.0.0",
2729
"gulp-changed": "^3.1.0",
2830
"gulp-header": "^1.8.9",
2931
"gulp-if": "^2.0.2",
3032
"gulp-load-plugins": "^1.5.0",
3133
"gulp-newer": "^1.4.0",
34+
"gulp-shell": "^0.6.5",
3235
"gulp-sourcemaps": "^2.6.1",
3336
"gulp-util": "^3.0.8",
3437
"jquery": "^3.2.1",
3538
"jquery-ui": "^1.10.4",
3639
"knockout": "^3.3.0",
3740
"mutationobserver-shim": "^0.3.2",
3841
"requirejs": "^2.3.5",
42+
"strip-ansi": "^4.0.0",
3943
"stylelint": "^8.4.0",
4044
"stylelint-config-recommended": "^2.0.1",
4145
"stylelint-order": "^0.8.0",

ts-error-stopgap.js

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/**
2+
* It should be noted that the existence of this script is far from ideal.
3+
* The goal here is to prevent any new TypeScript errors from being committed
4+
* to the code base, while giving the PageBuilder team the opportunity
5+
* to incrementally address existing compiler errors.
6+
*
7+
* A snapshot (in `ts-errors.json`) has been taken of all compiler errors
8+
* (and their respective metadata) to be checked against prior to any new
9+
* merges.
10+
*
11+
* Whenever this whole project passes a run of `tsc` without errors,
12+
* this script should be removed, and the CI process for PageBuilder
13+
* should be updated to fail the build on *any* TypeScript error.
14+
*/
15+
16+
const chalk = require('chalk');
17+
const stripANSI = require('strip-ansi');
18+
const priorStats = require('./ts-errors.json');
19+
20+
let chunks = [];
21+
22+
process.stdin.on('readable', () => {
23+
const chunk = process.stdin.read();
24+
if (chunk !== null) chunks.push(chunk);
25+
});
26+
27+
process.stdin.on('end', () => {
28+
// strip coloring and other decorations
29+
const tsOutput = stripANSI(chunks.join('')).trim();
30+
// each unique error is delimited by two line breaks
31+
const lines = tsOutput.split('\n\n');
32+
const compilerErrors = {};
33+
34+
while (lines.length) {
35+
const [rawError, rawSnippet] = lines.splice(0, 2);
36+
const [
37+
,
38+
file,
39+
line,
40+
column,
41+
errorCode,
42+
message
43+
] = rawError.match(/(.+)\((\d+),(\d+)\): error (TS\d+): (.+)/);
44+
45+
const fileErrors = compilerErrors[file] = compilerErrors[file] || [];
46+
47+
fileErrors.push({
48+
file,
49+
line,
50+
column,
51+
errorCode,
52+
message,
53+
rawError,
54+
rawSnippet
55+
});
56+
}
57+
58+
const newErrors = [];
59+
// Walk each file to do an error comparison
60+
for (const [file, errors] of Object.entries(compilerErrors)) {
61+
let newErrs = errors;
62+
// Walk each file to do an error comparison
63+
const oldFileErrors = priorStats[file];
64+
if (oldFileErrors && oldFileErrors.length > 0) {
65+
// Walk over all the tsc-reported errors in this file
66+
newErrs = errors.filter(e => {
67+
// Check if the error from this current iteration matches a previous
68+
// error from the states file on disk
69+
return !oldFileErrors.some(err => err.message === e.message);
70+
});
71+
}
72+
// Collect any newly-reported errors
73+
newErrors.push(...newErrs);
74+
}
75+
76+
if (!newErrors.length) {
77+
process.exit(0);
78+
}
79+
80+
console.log(
81+
chalk.red(`${newErrors.length} new TypeScript errors were introduced to the code base with your changes. \n`) +
82+
chalk.white.bgRed('You' , chalk.white.bgRed('must') , 'resolve all new TypeScript errors before merging a PR.')
83+
);
84+
85+
newErrors.forEach(err => {
86+
console.log(chalk.red(err.rawError + "\n"));
87+
err.rawSnippet.split("\n").forEach(raw => {
88+
console.log(" " + raw);
89+
});
90+
});
91+
92+
console.log(
93+
"\n" +
94+
chalk.red(`${newErrors.length} new TypeScript errors were introduced to the code base with your changes. \n`) +
95+
chalk.white.bgRed('You' , chalk.white.bgRed('must') , 'resolve all new TypeScript errors before merging a PR.')
96+
);
97+
});

0 commit comments

Comments
 (0)