From 3a86fcf0867c6d69a75aff80e57820b06316f682 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Mon, 16 May 2022 11:57:37 -0400 Subject: [PATCH 1/4] ci: use current minimum Node.js v16 version to test snapshot builds Node.js 16.10 is currently the minimum version of v16 supported by the Angular CLI and is now used when executing the Angular snapshot E2E test suite to ensure that the latest snapshots of Angular continue to function at this Node.js version. Node.js v16 is the version currently used to develop the Angular CLI. The npm 7+ workaround of installing npm 6 is also removed to more closely track the behavior of Node.js 16.10 as well as any other Node.js version used during testing. --- .circleci/config.yml | 3 +- .../legacy-cli/e2e/setup/010-local-publish.ts | 31 ++++++++++------ .../misc/invalid-schematic-dependencies.ts | 37 +++++++++---------- .../e2e/tests/misc/third-party-decorators.ts | 4 +- tests/legacy-cli/e2e/utils/packages.ts | 17 +++++++-- 5 files changed, 56 insertions(+), 36 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index cb8424b40ecc..f2874f819f59 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -204,10 +204,8 @@ jobs: - browser-tools/install-chrome - run: name: Initialize Environment - # npm 7 currently does not properly publish the packages locally command: | ./.circleci/env.sh - sudo npm install --global npm@6 - run: name: Execute CLI E2E Tests command: | @@ -354,6 +352,7 @@ workflows: - build - e2e-cli: name: e2e-cli-ng-snapshots + nodeversion: '16.10' snapshots: true requires: - build diff --git a/tests/legacy-cli/e2e/setup/010-local-publish.ts b/tests/legacy-cli/e2e/setup/010-local-publish.ts index d6a761a2b60d..2a7d31c547ba 100644 --- a/tests/legacy-cli/e2e/setup/010-local-publish.ts +++ b/tests/legacy-cli/e2e/setup/010-local-publish.ts @@ -1,18 +1,27 @@ import { getGlobalVariable } from '../utils/env'; -import { npm } from '../utils/process'; +import { execWithEnv } from '../utils/process'; import { isPrereleaseCli } from '../utils/project'; export default async function () { const testRegistry = getGlobalVariable('package-registry'); - await npm( - 'run', - 'admin', - '--', - 'publish', - '--no-versionCheck', - '--no-branchCheck', - `--registry=${testRegistry}`, - '--tag', - isPrereleaseCli() ? 'next' : 'latest', + await execWithEnv( + 'npm', + [ + 'run', + 'admin', + '--', + 'publish', + '--no-versionCheck', + '--no-branchCheck', + `--registry=${testRegistry}`, + '--tag', + isPrereleaseCli() ? 'next' : 'latest', + ], + { + ...process.env, + // Also set an auth token value for the local test registry which is required by npm 7+ + // even though it is never actually used. + 'NPM_CONFIG__AUTH': 'e2e-testing', + }, ); } diff --git a/tests/legacy-cli/e2e/tests/misc/invalid-schematic-dependencies.ts b/tests/legacy-cli/e2e/tests/misc/invalid-schematic-dependencies.ts index 4b8c05f04737..23b56464a745 100644 --- a/tests/legacy-cli/e2e/tests/misc/invalid-schematic-dependencies.ts +++ b/tests/legacy-cli/e2e/tests/misc/invalid-schematic-dependencies.ts @@ -1,29 +1,14 @@ import { expectFileToMatch } from '../../utils/fs'; -import { ng, silentNpm } from '../../utils/process'; +import { execWithEnv, ng, silentNpm } from '../../utils/process'; import { installPackage, uninstallPackage } from '../../utils/packages'; import { isPrereleaseCli } from '../../utils/project'; export default async function () { // Must publish old version to local registry to allow install. This is especially important // for release commits as npm will try to request tooling packages that are not on the npm registry yet - const { stdout: stdoutPack1 } = await silentNpm( - 'pack', - '@schematics/angular@7', - '--registry=https://registry.npmjs.org', - ); - await silentNpm('publish', stdoutPack1.trim(), '--tag=outdated'); - const { stdout: stdoutPack2 } = await silentNpm( - 'pack', - '@angular-devkit/core@7', - '--registry=https://registry.npmjs.org', - ); - await silentNpm('publish', stdoutPack2.trim(), '--tag=outdated'); - const { stdout: stdoutPack3 } = await silentNpm( - 'pack', - '@angular-devkit/schematics@7', - '--registry=https://registry.npmjs.org', - ); - await silentNpm('publish', stdoutPack3.trim(), '--tag=outdated'); + await publishOutdated('@schematics/angular@7'); + await publishOutdated('@angular-devkit/core@7'); + await publishOutdated('@angular-devkit/schematics@7'); // Install outdated and incompatible version await installPackage('@schematics/angular@7'); @@ -36,3 +21,17 @@ export default async function () { // Not doing so can cause adding material to fail if an incompatible cdk is present await uninstallPackage('@angular/cdk'); } + +async function publishOutdated(npmSpecifier: string): Promise { + const { stdout: stdoutPack } = await silentNpm( + 'pack', + npmSpecifier, + '--registry=https://registry.npmjs.org', + ); + await execWithEnv('npm', ['publish', stdoutPack.trim(), '--tag=outdated'], { + ...process.env, + // Also set an auth token value for the local test registry which is required by npm 7+ + // even though it is never actually used. + 'NPM_CONFIG__AUTH': 'e2e-testing', + }); +} diff --git a/tests/legacy-cli/e2e/tests/misc/third-party-decorators.ts b/tests/legacy-cli/e2e/tests/misc/third-party-decorators.ts index 7fa1e23d0471..f57580ff2b5e 100644 --- a/tests/legacy-cli/e2e/tests/misc/third-party-decorators.ts +++ b/tests/legacy-cli/e2e/tests/misc/third-party-decorators.ts @@ -15,7 +15,9 @@ export default async function () { packageJson['devDependencies']['typescript'] = '~4.6.2'; }); - await installWorkspacePackages(); + // Force is need to prevent npm 7+ from failing due to potential peer dependency resolution range errors. + // This is especially common when testing snapshot builds for new prereleases. + await installWorkspacePackages({ force: true }); // Create an app that uses ngrx decorators and has e2e tests. await writeMultipleFiles({ diff --git a/tests/legacy-cli/e2e/utils/packages.ts b/tests/legacy-cli/e2e/utils/packages.ts index 2f7fdef6f271..cc294acfcfa8 100644 --- a/tests/legacy-cli/e2e/utils/packages.ts +++ b/tests/legacy-cli/e2e/utils/packages.ts @@ -1,5 +1,4 @@ import { getGlobalVariable } from './env'; -import { writeFile } from './fs'; import { ProcessOutput, npm, silentNpm, silentYarn } from './process'; export function getActivePackageManager(): 'npm' | 'yarn' { @@ -11,10 +10,14 @@ export function getActivePackageManager(): 'npm' | 'yarn' { return value || 'npm'; } -export async function installWorkspacePackages(): Promise { +export async function installWorkspacePackages(options?: { force?: boolean }): Promise { switch (getActivePackageManager()) { case 'npm': - await silentNpm('install'); + const npmArgs = ['install']; + if (options?.force) { + npmArgs.push('--force'); + } + await silentNpm(...npmArgs); break; case 'yarn': await silentYarn(); @@ -47,6 +50,7 @@ export async function setRegistry(useTestRegistry: boolean): Promise { : 'https://registry.npmjs.org'; const isCI = getGlobalVariable('ci'); + const isSnapshotBuild = getGlobalVariable('argv')['ng-snapshots']; // Ensure local test registry is used when outside a project if (isCI) { @@ -56,4 +60,11 @@ export async function setRegistry(useTestRegistry: boolean): Promise { // Yarn supports both `NPM_CONFIG_REGISTRY` and `YARN_REGISTRY`. process.env['NPM_CONFIG_REGISTRY'] = url; } + + // Snapshot builds may contain versions that are not yet released (e.g., RC phase main branch). + // In this case peer dependency ranges may not resolve causing npm 7+ to fail during tests. + // To support this case, legacy peer dependency mode is enabled for snapshot builds. + if (isSnapshotBuild) { + process.env['NPM_CONFIG_legacy_peer_deps'] = 'true'; + } } From bac74ba7c4cae05bc9c3d13e3a1d9f0823cb3e17 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Mon, 16 May 2022 16:54:10 -0400 Subject: [PATCH 2/4] build: update peer dependencies to support unreleased 14.1.x prerelease snapshots --- packages/angular_devkit/build_angular/package.json | 8 ++++---- packages/ngtools/webpack/package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/angular_devkit/build_angular/package.json b/packages/angular_devkit/build_angular/package.json index ddd5a70a8b0f..5549f1aaa973 100644 --- a/packages/angular_devkit/build_angular/package.json +++ b/packages/angular_devkit/build_angular/package.json @@ -73,11 +73,11 @@ "esbuild": "0.14.38" }, "peerDependencies": { - "@angular/compiler-cli": "^14.0.0 || ^14.0.0-next", - "@angular/localize": "^14.0.0 || ^14.0.0-next", - "@angular/service-worker": "^14.0.0 || ^14.0.0-next", + "@angular/compiler-cli": "^14.0.0 || ^14.0.0-next || ^14.1.0-next", + "@angular/localize": "^14.0.0 || ^14.0.0-next || ^14.1.0-next", + "@angular/service-worker": "^14.0.0 || ^14.0.0-next || ^14.1.0-next", "karma": "^6.3.0", - "ng-packagr": "^14.0.0 || ^14.0.0-next", + "ng-packagr": "^14.0.0 || ^14.0.0-next || ^14.1.0-next", "protractor": "^7.0.0", "tailwindcss": "^2.0.0 || ^3.0.0", "typescript": ">=4.6.2 <4.8" diff --git a/packages/ngtools/webpack/package.json b/packages/ngtools/webpack/package.json index a20981ceaaaa..7379aedac1f6 100644 --- a/packages/ngtools/webpack/package.json +++ b/packages/ngtools/webpack/package.json @@ -22,7 +22,7 @@ "homepage": "https://github.com/angular/angular-cli/tree/main/packages/ngtools/webpack", "dependencies": {}, "peerDependencies": { - "@angular/compiler-cli": "^14.0.0 || ^14.0.0-next", + "@angular/compiler-cli": "^14.0.0 || ^14.0.0-next || ^14.1.0-next", "typescript": ">=4.6.2 <4.8", "webpack": "^5.54.0" }, From 18a3de262ef567248706f49b6becdf2181e95b1e Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Mon, 16 May 2022 19:07:10 -0400 Subject: [PATCH 3/4] build: update Angular snapshots --- tests/legacy-cli/e2e/ng-snapshot/package.json | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/legacy-cli/e2e/ng-snapshot/package.json b/tests/legacy-cli/e2e/ng-snapshot/package.json index 3f4e43cd5f21..d226f7a9e1b6 100644 --- a/tests/legacy-cli/e2e/ng-snapshot/package.json +++ b/tests/legacy-cli/e2e/ng-snapshot/package.json @@ -2,21 +2,21 @@ "description": "snapshot versions of Angular for e2e testing", "private": true, "dependencies": { - "@angular/animations": "github:angular/animations-builds#c51039c79459d89d9c1cb37d03650f1c27f4c73a", - "@angular/cdk": "github:angular/cdk-builds#e313adc4ec0a6b4ce4a9e54fcb6940da897dba7b", - "@angular/common": "github:angular/common-builds#4a574ecd7f4f926aedf37caf5c236d972a70cd58", - "@angular/compiler": "github:angular/compiler-builds#84d5a262885fb9b45cfae764ce87bbb316156408", - "@angular/compiler-cli": "github:angular/compiler-cli-builds#ddf20b9e25eeda3c8663050a8cb4da56f69c1e88", - "@angular/core": "github:angular/core-builds#4f83abb0614bddb4782d901c72b33660b6c6a260", - "@angular/forms": "github:angular/forms-builds#76abdfe1f2b9dcf5c609a46deeaac2565ba6e5a8", - "@angular/language-service": "github:angular/language-service-builds#e8e1e1bfd69c6bc793de5925fe012eb9102e80f5", - "@angular/localize": "github:angular/localize-builds#7c7412067e7ab47e2b9db5f8931b5d8666bc7c94", - "@angular/material": "github:angular/material-builds#3c9831b30dbe1d3b8b4a0bb540775e5b5a1e91b9", - "@angular/material-moment-adapter": "github:angular/material-moment-adapter-builds#428f8b7bf3219900a4582e2c522ba6c2ebbc9dae", - "@angular/platform-browser": "github:angular/platform-browser-builds#1ca47c1990ec000ce7fe8a6c44c06025f27ca145", - "@angular/platform-browser-dynamic": "github:angular/platform-browser-dynamic-builds#eee37a0728324b9aed7df56dc79861a9805a2dde", - "@angular/platform-server": "github:angular/platform-server-builds#ea262a7296b6eb039f6a16b63db53d7517c013c0", - "@angular/router": "github:angular/router-builds#4f1b9c07933efaa658d4edf1871076f64f94f0d8", - "@angular/service-worker": "github:angular/service-worker-builds#4f0881bc26e1b4b4bb17d36c6ba563b79eb80027" + "@angular/animations": "github:angular/animations-builds#901309992e6f3614130e136c0e3f67fa30537d33", + "@angular/cdk": "github:angular/cdk-builds#e647c3afecf4c41f8b2347325ade9425753d1fcd", + "@angular/common": "github:angular/common-builds#803ef76ef02fa36a9fe8ae7618925ab449ebe85b", + "@angular/compiler": "github:angular/compiler-builds#15a712a1b81f241e2ca52d0ba315371967552c19", + "@angular/compiler-cli": "github:angular/compiler-cli-builds#633bfed62ac5b1cae5dacf9128a52f032df31545", + "@angular/core": "github:angular/core-builds#0b0b0988007554e4dad15d1a5d0a3bcd56417c2f", + "@angular/forms": "github:angular/forms-builds#64233866e5ae0aaed85c4bdfcddb49972a05d728", + "@angular/language-service": "github:angular/language-service-builds#08589e1bfdb0c804e5d2391a81860c1a3c1d0ff7", + "@angular/localize": "github:angular/localize-builds#d57ea1221af85a0f22df38113de0928ff8f9a38b", + "@angular/material": "github:angular/material-builds#92599d199359f885c473fbc4f42c72a595149793", + "@angular/material-moment-adapter": "github:angular/material-moment-adapter-builds#1b8aa537b485122cc0121d5d2f436edf0d45523c", + "@angular/platform-browser": "github:angular/platform-browser-builds#9934c441a9689f23bbc3da34590eb56d46a58608", + "@angular/platform-browser-dynamic": "github:angular/platform-browser-dynamic-builds#d036997c6e0ce768dbe6a69b803debbe564002d8", + "@angular/platform-server": "github:angular/platform-server-builds#27fbfe1811342e70bf0e8337158c2d35376df7f9", + "@angular/router": "github:angular/router-builds#9c27232aff16fd8fe9d4f5be1bde51a041b3f9e1", + "@angular/service-worker": "github:angular/service-worker-builds#d0103132b2d0d355c148a749a10b5dbdc9e4f8ce" } } From d3798863958f7acc115f641fee8698956c413437 Mon Sep 17 00:00:00 2001 From: Charles Lyding <19598772+clydin@users.noreply.github.com> Date: Tue, 17 May 2022 11:18:08 -0400 Subject: [PATCH 4/4] test: ensure npm 7 E2E test reset global version back to the actual initial version The `misc/npm-7` E2E test previously assumed the initial version of npm was 6.x and would then always install 6.x after the test was complete. With newer Node.js versions this assumption is no longer true. The test now records the initial version present prior to starting the test and restores that recorded version at completion. --- tests/legacy-cli/e2e/tests/misc/npm-7.ts | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tests/legacy-cli/e2e/tests/misc/npm-7.ts b/tests/legacy-cli/e2e/tests/misc/npm-7.ts index 1692096638a4..09b1f988b2a4 100644 --- a/tests/legacy-cli/e2e/tests/misc/npm-7.ts +++ b/tests/legacy-cli/e2e/tests/misc/npm-7.ts @@ -1,3 +1,6 @@ +import * as assert from 'assert'; +import { execSync } from 'child_process'; +import { valid as validSemVer } from 'semver'; import { rimraf } from '../../utils/fs'; import { getActivePackageManager } from '../../utils/packages'; import { ng, npm } from '../../utils/process'; @@ -17,6 +20,23 @@ export default async function () { return; } + // Get current package manager version to restore after tests + const initialVersionText = execSync('npm --version', { + encoding: 'utf8', + stdio: ['ignore', 'pipe', 'ignore'], + env: { + ...process.env, + // NPM updater notifier will prevent the child process from closing until it timeouts after 3 minutes. + NO_UPDATE_NOTIFIER: '1', + NPM_CONFIG_UPDATE_NOTIFIER: 'false', + }, + }).trim(); + const initialVersion = validSemVer(initialVersionText); + assert.ok( + initialVersion, + `Invalid npm version string returned from "npm --version" [${initialVersionText}]`, + ); + const currentDirectory = process.cwd(); const extraArgs = []; @@ -89,7 +109,7 @@ export default async function () { // Change directory back process.chdir(currentDirectory); - // Reset version back to 6.x - await npm('install', '--global', 'npm@6'); + // Reset version back to initial version + await npm('install', '--global', `npm@${initialVersion}`); } }