From da1504fec4bfe026ff56be34bd0555425e419301 Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Fri, 3 Mar 2023 13:55:27 +0000 Subject: [PATCH] build: fix AIO local e2e examples picking up incorrect dependencies (#49293) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Whenever we run example tests using the local framework packages, the e2e tests will have the local framework packages symlinked in the `node_modules`. This works well in general, but due to NodeJS by default resolving symlinks to the target location, NodeJS will end up looking for transitive dependencies in the `bazel-bin` instead of in the example `node_modules` folder. This means that we end up incorrectly resolving older versions of `@angular/core` that end up existing in the main project dependencies. This causes errors like: ``` Error: ../../home/circleci/.cache/bazel/_bazel_circleci/9ce5c2144ecf75d11717c0aa41e45a8d/execroot/angular/bazel-out/k8-fastbuild/bin/packages/common/npm_package/http/testing/index.d.ts:12:21 - error TS2307: Cannot find module '@angular/common/http' or its corresponding type declarations. 12 import * as i1 from '@angular/common/http'; ~~~~~~~~~~~~~~~~~~~~~~ Error: ../../home/circleci/.cache/bazel/_bazel_circleci/9ce5c2144ecf75d11717c0aa41e45a8d/execroot/angular/bazel-out/k8-fastbuild/bin/packages/common/npm_package/index.d.ts:1630:18 - error TS2707: Generic type 'ɵɵDirectiveDeclaration' requires between 6 and 8 type arguments. 1630 static ɵdir: i0.ɵɵDirectiveDeclaration; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` We can fix this by properly ensuring that NodeJS does not resolve symlinks, but rather preserves them. In the error above, the e2e tests end up accidentally resolving `@angular/core` v14 that comes from `@angular/benchpress`. Angular Benchpress is installed via `@angular/build-tooling` in the project root. PR Close #49293 --- aio/tools/examples/example-sandbox.mjs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/aio/tools/examples/example-sandbox.mjs b/aio/tools/examples/example-sandbox.mjs index 99227e04152..dc83014ea4d 100644 --- a/aio/tools/examples/example-sandbox.mjs +++ b/aio/tools/examples/example-sandbox.mjs @@ -132,11 +132,13 @@ function pointBinSymlinksToLocalPackages(linkedNodeModules, exampleDepsNodeModul }); } -// When local packages are symlinked in, node has trouble resolving some peer deps. Setting -// preserveSymlinks in relevant files fixes this. This isn't required without local packages -// because in the worst case we would leak into the original Bazel repository and it would -// still find a node_modules folder for resolution. Add the preserveSymlinks options to various -// files that are used by the cli and systemjs tests (and sometimes both). +/** + * When local packages are symlinked in, node will by default resolve local packages to + * their output location in the `bazel-bin`. This will then cause transitive dependencies + * to be incorrectly resolved from `bazel-bin`, instead of from within the example sandbox. + * + * Setting `preserveSymlinks` in relevant files fixes this. + */ function preserveSymlinksWhenUsingLocalPackages(LOCAL_PACKAGES, appDir) { if (Object.keys(LOCAL_PACKAGES).length === 0) { return; @@ -145,19 +147,16 @@ function preserveSymlinksWhenUsingLocalPackages(LOCAL_PACKAGES, appDir) { // Set preserveSymlinks in angular.json const angularJsonPath = path.join(appDir, 'angular.json'); if (fs.existsSync(angularJsonPath)) { - const angularJson = jsonc.load(angularJsonPath, { - encoding: 'utf-8' - }); + const angularJson = jsonc.load(angularJsonPath, {encoding: 'utf-8'}); angularJson.projects['angular.io-example'].architect.build.options.preserveSymlinks = true; + angularJson.projects['angular.io-example'].architect.test.options.preserveSymlinks = true; fs.writeFileSync(angularJsonPath, JSON.stringify(angularJson, undefined, 2)); } // Set preserveSymlinks in any tsconfig.json files const tsConfigPaths = globbySync([path.join(appDir, 'tsconfig*.json')]); for (const tsConfigPath of tsConfigPaths) { - const tsConfig = jsonc.load(tsConfigPath, { - encoding: 'utf-8' - }); + const tsConfig = jsonc.load(tsConfigPath, {encoding: 'utf-8'}); const isRootConfig = !tsConfig.extends; if (isRootConfig) { tsConfig.compilerOptions.preserveSymlinks = true; @@ -167,9 +166,7 @@ function preserveSymlinksWhenUsingLocalPackages(LOCAL_PACKAGES, appDir) { // Call rollup with --preserveSymlinks const packageJsonPath = path.join(appDir, 'package.json'); - const packageJson = jsonc.load(packageJsonPath, { - encoding: 'utf-8' - }); + const packageJson = jsonc.load(packageJsonPath, {encoding: 'utf-8'}); if ('rollup' in packageJson.dependencies || 'rollup' in packageJson.devDependencies) { packageJson.scripts.rollup = 'rollup --preserveSymlinks'; fs.writeFileSync(packageJsonPath, JSON.stringify(packageJson, undefined, 2));