From 0e6875e912797a82f720d5fc8a9670e88d8ead3d Mon Sep 17 00:00:00 2001 From: Alan Agius Date: Thu, 30 Jun 2022 09:00:27 +0000 Subject: [PATCH] fix(@angular-devkit/build-angular): disable glob mounting for patterns that start with a forward slash By default, a glob pattern starting with a forward slash will be "mounted" onto the system root. This causes globs to escape the workspace root. With this change we configure disable glob "mounting" and also change the root to the same setting of the `cwd`. Closes #23467 --- .../src/builders/karma/find-tests.ts | 2 ++ .../tests/options/code-coverage-exclude_spec.ts | 15 +++++++++++++++ .../builders/karma/tests/options/include_spec.ts | 4 ++++ .../build_angular/src/utils/copy-assets.ts | 11 +++++------ .../build_angular/src/webpack/utils/helpers.ts | 6 +++--- 5 files changed, 29 insertions(+), 9 deletions(-) diff --git a/packages/angular_devkit/build_angular/src/builders/karma/find-tests.ts b/packages/angular_devkit/build_angular/src/builders/karma/find-tests.ts index c74eff095d21..8c3fd18d3acc 100644 --- a/packages/angular_devkit/build_angular/src/builders/karma/find-tests.ts +++ b/packages/angular_devkit/build_angular/src/builders/karma/find-tests.ts @@ -66,6 +66,8 @@ async function findMatchingTests( return globPromise(normalizedPattern, { cwd: projectSourceRoot, + root: projectSourceRoot, + nomount: true, }); } diff --git a/packages/angular_devkit/build_angular/src/builders/karma/tests/options/code-coverage-exclude_spec.ts b/packages/angular_devkit/build_angular/src/builders/karma/tests/options/code-coverage-exclude_spec.ts index 803f8937132f..db43d5f33b46 100644 --- a/packages/angular_devkit/build_angular/src/builders/karma/tests/options/code-coverage-exclude_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/karma/tests/options/code-coverage-exclude_spec.ts @@ -37,6 +37,21 @@ describeBuilder(execute, KARMA_BUILDER_INFO, (harness) => { harness.expectFile(coveragePath).content.not.toContain('app.component.ts'); }); + it('should exclude file from coverage when set when glob starts with a forward slash', async () => { + harness.useTarget('test', { + ...BASE_OPTIONS, + codeCoverage: true, + codeCoverageExclude: ['/**/app.component.ts'], + }); + + const { result } = await harness.executeOnce(); + + expect(result?.success).toBeTrue(); + + await setTimeoutPromise(1000); + harness.expectFile(coveragePath).content.not.toContain('app.component.ts'); + }); + it('should not exclude file from coverage when set', async () => { harness.useTarget('test', { ...BASE_OPTIONS, diff --git a/packages/angular_devkit/build_angular/src/builders/karma/tests/options/include_spec.ts b/packages/angular_devkit/build_angular/src/builders/karma/tests/options/include_spec.ts index f9af40f861c8..bf0484eb28a6 100644 --- a/packages/angular_devkit/build_angular/src/builders/karma/tests/options/include_spec.ts +++ b/packages/angular_devkit/build_angular/src/builders/karma/tests/options/include_spec.ts @@ -54,6 +54,10 @@ describeBuilder(execute, KARMA_BUILDER_INFO, (harness) => { test: 'glob with spec suffix', input: ['**/*.pipe.spec.ts', '**/*.pipe.spec.ts', '**/*test.service.spec.ts'], }, + { + test: 'glob with forward slash and spec suffix', + input: ['/**/*test.service.spec.ts'], + }, ].forEach((options, index) => { it(`should work with ${options.test} (${index})`, async () => { await harness.writeFiles({ diff --git a/packages/angular_devkit/build_angular/src/utils/copy-assets.ts b/packages/angular_devkit/build_angular/src/utils/copy-assets.ts index ea23223a54f4..be8ab1799459 100644 --- a/packages/angular_devkit/build_angular/src/utils/copy-assets.ts +++ b/packages/angular_devkit/build_angular/src/utils/copy-assets.ts @@ -9,12 +9,9 @@ import * as fs from 'fs'; import glob from 'glob'; import * as path from 'path'; +import { promisify } from 'util'; -function globAsync(pattern: string, options: glob.IOptions) { - return new Promise((resolve, reject) => - glob(pattern, options, (e, m) => (e ? reject(e) : resolve(m))), - ); -} +const globPromise = promisify(glob); export async function copyAssets( entries: { @@ -33,10 +30,12 @@ export async function copyAssets( for (const entry of entries) { const cwd = path.resolve(root, entry.input); - const files = await globAsync(entry.glob, { + const files = await globPromise(entry.glob, { cwd, dot: true, nodir: true, + root: cwd, + nomount: true, ignore: entry.ignore ? defaultIgnore.concat(entry.ignore) : defaultIgnore, follow: entry.followSymlinks, }); diff --git a/packages/angular_devkit/build_angular/src/webpack/utils/helpers.ts b/packages/angular_devkit/build_angular/src/webpack/utils/helpers.ts index 16c0978bef2b..9fc774bb8369 100644 --- a/packages/angular_devkit/build_angular/src/webpack/utils/helpers.ts +++ b/packages/angular_devkit/build_angular/src/webpack/utils/helpers.ts @@ -121,15 +121,15 @@ export function assetNameTemplateFactory(hashFormat: HashFormat): (resourcePath: } export function getInstrumentationExcludedPaths( - sourceRoot: string, + root: string, excludedPaths: string[], ): Set { const excluded = new Set(); for (const excludeGlob of excludedPaths) { glob - .sync(excludeGlob, { nodir: true, cwd: sourceRoot }) - .forEach((p) => excluded.add(path.join(sourceRoot, p))); + .sync(excludeGlob, { nodir: true, cwd: root, root, nomount: true }) + .forEach((p) => excluded.add(path.join(root, p))); } return excluded;