From ac4c109bebac3ea3d562f000c46a98d61b1bd148 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Mon, 22 Mar 2021 10:54:21 -0400 Subject: [PATCH] fix(@angular-devkit/build-angular): ensure output directory is present before writing stats JSON If an error occurs during a build, it is possible that the output path directory may not be present and then cause the stats JSON file write to fail. Fixes: #20349 --- .../src/webpack/configs/common.ts | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/webpack/configs/common.ts b/packages/angular_devkit/build_angular/src/webpack/configs/common.ts index 9b8e4a6f51c1..a9b0a842d746 100644 --- a/packages/angular_devkit/build_angular/src/webpack/configs/common.ts +++ b/packages/angular_devkit/build_angular/src/webpack/configs/common.ts @@ -10,7 +10,7 @@ import { buildOptimizerLoaderPath, } from '@angular-devkit/build-optimizer'; import * as CopyWebpackPlugin from 'copy-webpack-plugin'; -import { createWriteStream, existsSync } from 'fs'; +import { createWriteStream, existsSync, promises as fsPromises } from 'fs'; import * as path from 'path'; import { ScriptTarget } from 'typescript'; import { @@ -34,6 +34,7 @@ import { } from '../../utils/environment-options'; import { findAllNodeModules } from '../../utils/find-up'; import { Spinner } from '../../utils/spinner'; +import { addError } from '../../utils/webpack-diagnostics'; import { isWebpackFiveOrHigher, withWebpackFourOrFive } from '../../utils/webpack-version'; import { DedupeModuleResolvePlugin, @@ -294,12 +295,21 @@ export function getCommonConfig(wco: WebpackConfigOptions): Configuration { const data = stats.toJson('verbose'); const statsOutputPath = path.join(stats.compilation.outputOptions.path, 'stats.json'); - return new Promise((resolve, reject) => - stringifyStream(data) - .pipe(createWriteStream(statsOutputPath)) - .on('close', resolve) - .on('error', reject), - ); + try { + await fsPromises.mkdir(path.dirname(statsOutputPath), { recursive: true }); + + await new Promise((resolve, reject) => + stringifyStream(data) + .pipe(createWriteStream(statsOutputPath)) + .on('close', resolve) + .on('error', reject), + ); + } catch (error) { + addError( + stats.compilation, + `Unable to write stats file: ${error.message || 'unknown error'}`, + ); + } }); } })(),