mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
build: fail build for prerender errors in lifecycle hooks (#5459)
* Currently the build won't fail if an error is thrown inside a lifecycle hook, because `platform-server` writes it to STDERR, but still exits with a 0 code. These changes set up the Universal testing task to fail for these cases as well. This should prevent issues like #5455 in the future. * Stops logging the entire rendered document after the prerender task is done. This makes the log a bit easier to look through.
This commit is contained in:
committed by
mmalerba
parent
0675568d03
commit
79fb7582dd
@@ -5,6 +5,7 @@ import {enableProdMode} from '@angular/core';
|
||||
import {renderModuleFactory} from '@angular/platform-server';
|
||||
import {join} from 'path';
|
||||
import {readFileSync} from 'fs-extra';
|
||||
import {log} from 'gulp-util';
|
||||
import {KitchenSinkServerModuleNgFactory} from './kitchen-sink/kitchen-sink.ngfactory';
|
||||
|
||||
enableProdMode();
|
||||
@@ -14,7 +15,7 @@ const result = renderModuleFactory(KitchenSinkServerModuleNgFactory, {
|
||||
});
|
||||
|
||||
result
|
||||
.then(html => console.log(html))
|
||||
.then(() => log('Prerender done.'))
|
||||
// If rendering the module factory fails, exit the process with an error code because otherwise
|
||||
// the CI task will not recognize the failure and will show as "success". The error message
|
||||
// will be printed automatically by the `renderModuleFactory` method.
|
||||
|
||||
@@ -25,7 +25,10 @@ const prerenderOutFile = join(outDir, 'prerender.js');
|
||||
task('universal:test-prerender', ['universal:build'], execTask(
|
||||
// Runs node with the tsconfig-paths module to alias the @angular/material dependency.
|
||||
'node', ['-r', 'tsconfig-paths/register', prerenderOutFile], {
|
||||
env: {TS_NODE_PROJECT: tsconfigPrerenderPath}
|
||||
env: {TS_NODE_PROJECT: tsconfigPrerenderPath},
|
||||
// Errors in lifecycle hooks will write to STDERR, but won't exit the process with an
|
||||
// error code, however we still want to catch those cases in the CI.
|
||||
failOnStderr: true
|
||||
}
|
||||
));
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@ export interface ExecTaskOptions {
|
||||
errMessage?: string;
|
||||
// Environment variables being passed to the child process.
|
||||
env?: any;
|
||||
// Whether the task should fail if the process writes to STDERR.
|
||||
failOnStderr?: boolean;
|
||||
}
|
||||
|
||||
/** Create a task that executes a binary as if from the command line. */
|
||||
@@ -56,24 +58,23 @@ export function execTask(binPath: string, args: string[], options: ExecTaskOptio
|
||||
return (done: (err?: string) => void) => {
|
||||
const env = Object.assign({}, process.env, options.env);
|
||||
const childProcess = child_process.spawn(binPath, args, {env});
|
||||
const stderrData: string[] = [];
|
||||
|
||||
if (!options.silentStdout && !options.silent) {
|
||||
childProcess.stdout.on('data', (data: string) => process.stdout.write(data));
|
||||
}
|
||||
|
||||
if (!options.silent) {
|
||||
childProcess.stderr.on('data', (data: string) => process.stderr.write(data));
|
||||
if (!options.silent || options.failOnStderr) {
|
||||
childProcess.stderr.on('data', (data: string) => {
|
||||
options.failOnStderr ? stderrData.push(data) : process.stderr.write(data);
|
||||
});
|
||||
}
|
||||
|
||||
childProcess.on('close', (code: number) => {
|
||||
if (code != 0) {
|
||||
if (options.errMessage === undefined) {
|
||||
done('Process failed with code ' + code);
|
||||
} else {
|
||||
done(options.errMessage);
|
||||
}
|
||||
if (options.failOnStderr && stderrData.length) {
|
||||
done(stderrData.join('\n'));
|
||||
} else {
|
||||
done();
|
||||
code != 0 ? done(options.errMessage || `Process failed with code ${code}`) : done();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user