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/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" }, 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" } } 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/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}`); } } 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'; + } }