diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0118372974..0882e66ee3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,6 +27,8 @@ jobs: NX_E2E_RUN_E2E: 'true' NX_CI_EXECUTION_ENV: 'linux' NX_CLOUD_NO_TIMEOUTS: 'true' + NX_ALLOW_NON_CACHEABLE_DTE: 'true' + NX_CLOUD_USE_NEW_TASK_APIS: 'true' NX_CLOUD_USE_NEW_STREAM_OUTPUT: 'true' steps: @@ -106,7 +108,7 @@ jobs: main-macos: runs-on: macos-latest - + env: NX_E2E_CI_CACHE_KEY: e2e-github-macos NX_PERF_LOGGING: 'false' diff --git a/.nx/workflows/dynamic-changesets.yaml b/.nx/workflows/dynamic-changesets.yaml index 099a5b3e8f..3fdb76d18c 100644 --- a/.nx/workflows/dynamic-changesets.yaml +++ b/.nx/workflows/dynamic-changesets.yaml @@ -1,6 +1,14 @@ distribute-on: default: auto linux-medium, 1 linux-extra-large assignment-rules: + - targets: + - e2e-ci** + run-on: + - agent: linux-medium + parallelism: 1 + - agent: linux-extra-large + parallelism: 1 + - projects: - nx-dev targets: diff --git a/e2e/utils/global-setup.ts b/e2e/utils/global-setup.ts index 7fd221da3c..39aa17f136 100644 --- a/e2e/utils/global-setup.ts +++ b/e2e/utils/global-setup.ts @@ -1,8 +1,7 @@ import { Config } from '@jest/types'; -import { startLocalRegistry } from '@nx/js/plugins/jest/local-registry'; import { existsSync, removeSync } from 'fs-extra'; import * as isCI from 'is-ci'; -import { exec } from 'node:child_process'; +import { exec, execSync } from 'node:child_process'; import { join } from 'node:path'; import { registerTsConfigPaths } from '../../packages/nx/src/plugins/js/utils/register'; import { runLocalRelease } from '../../scripts/local-registry/populate-storage'; @@ -19,18 +18,54 @@ export default async function (globalConfig: Config.ConfigGlobals) { const requiresLocalRelease = !process.env.NX_TASK_TARGET_TARGET?.startsWith('e2e-ci'); - global.e2eTeardown = await startLocalRegistry({ - localRegistryTarget: '@nx/nx-source:local-registry', - verbose: isVerbose, - clearStorage: requiresLocalRelease, - }); + const listenAddress = 'localhost'; + const port = process.env.NX_LOCAL_REGISTRY_PORT ?? '4873'; + const registry = `http://${listenAddress}:${port}`; + const authToken = 'secretVerdaccioToken'; + + while (true) { + await new Promise((resolve) => setTimeout(resolve, 250)); + try { + await assertLocalRegistryIsRunning(registry); + break; + } catch { + console.log(`Waiting for Local registry to start on ${registry}...`); + } + } + + process.env.npm_config_registry = registry; + execSync( + `npm config set //${listenAddress}:${port}/:_authToken "${authToken}" --ws=false`, + { + windowsHide: false, + } + ); + + // bun + process.env.BUN_CONFIG_REGISTRY = registry; + process.env.BUN_CONFIG_TOKEN = authToken; + // yarnv1 + process.env.YARN_REGISTRY = registry; + // yarnv2 + process.env.YARN_NPM_REGISTRY_SERVER = registry; + process.env.YARN_UNSAFE_HTTP_WHITELIST = listenAddress; + + global.e2eTeardown = () => { + execSync( + `npm config delete //${listenAddress}:${port}/:_authToken --ws=false`, + { + windowsHide: false, + } + ); + }; /** * Set the published version based on what has previously been loaded into the * verdaccio storage. */ if (!requiresLocalRelease) { - const publishedVersion = await getPublishedVersion(); + let publishedVersion = await getPublishedVersion(); + console.log(`Testing Published version: Nx ${publishedVersion}`); if (publishedVersion) { process.env.PUBLISHED_VERSION = publishedVersion; } @@ -60,6 +95,9 @@ export default async function (globalConfig: Config.ConfigGlobals) { } function getPublishedVersion(): Promise { + execSync(`npm config get registry`, { + stdio: 'inherit', + }); return new Promise((resolve) => { // Resolve the published nx version from verdaccio exec( @@ -76,3 +114,10 @@ function getPublishedVersion(): Promise { ); }); } + +async function assertLocalRegistryIsRunning(url) { + const response = await fetch(url); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } +} diff --git a/nx.json b/nx.json index 66b8b2462b..fb2f74db00 100644 --- a/nx.json +++ b/nx.json @@ -149,13 +149,17 @@ }, "e2e-ci--**/**": { "inputs": ["e2eInputs", "^production"], - "parallelism": false, - "dependsOn": ["@nx/nx-source:populate-local-registry-storage"] + "dependsOn": [ + "@nx/nx-source:populate-local-registry-storage", + "@nx/nx-source:local-registry" + ] }, "e2e-macos-ci--**/*": { "inputs": ["e2eInputs", "^production"], - "parallelism": false, - "dependsOn": ["@nx/nx-source:populate-local-registry-storage"] + "dependsOn": [ + "@nx/nx-source:populate-local-registry-storage", + "@nx/nx-source:local-registry" + ] }, "e2e-base": { "inputs": ["default", "^production"] @@ -254,7 +258,7 @@ "nxCloudId": "62d013ea0852fe0a2df74438", "nxCloudUrl": "https://staging.nx.app", "parallel": 1, - "bust": 7, + "bust": 1, "defaultBase": "master", "conformance": { "rules": [ diff --git a/project.json b/project.json index 903e07497c..417546756f 100644 --- a/project.json +++ b/project.json @@ -7,7 +7,8 @@ "options": { "port": 4873, "config": ".verdaccio/config.yml", - "storage": "build/local-registry/storage" + "storage": "build/local-registry/storage", + "clear": false } }, "populate-local-registry-storage": { @@ -16,9 +17,11 @@ { "input": "production", "projects": ["tag:npm:public"] - } + }, + "{workspaceRoot}/scripts/local-registry" ], "dependsOn": [ + "local-registry", { "target": "build", "projects": ["tag:npm:public"] diff --git a/scripts/local-registry/populate-storage.js b/scripts/local-registry/populate-storage.js index e6e163877b..5dd90812fe 100644 --- a/scripts/local-registry/populate-storage.js +++ b/scripts/local-registry/populate-storage.js @@ -1,33 +1,43 @@ // @ts-check - -const { startLocalRegistry } = require('@nx/js/plugins/jest/local-registry'); -const { exec } = require('node:child_process'); +const { exec, execSync } = require('node:child_process'); const { LARGE_BUFFER, } = require('nx/src/executors/run-commands/run-commands.impl'); async function populateLocalRegistryStorage() { - let registryTeardown; + const listenAddress = 'localhost'; + const port = process.env.NX_LOCAL_REGISTRY_PORT ?? '4873'; + const registry = `http://${listenAddress}:${port}`; + const authToken = 'secretVerdaccioToken'; + + while (true) { + await new Promise((resolve) => setTimeout(resolve, 250)); + try { + await assertLocalRegistryIsRunning(registry); + break; + } catch { + console.log(`Waiting for Local registry to start on ${registry}...`); + } + } + + process.env.npm_config_registry = registry; + + // bun + process.env.BUN_CONFIG_REGISTRY = registry; + process.env.BUN_CONFIG_TOKEN = authToken; + // yarnv1 + process.env.YARN_REGISTRY = registry; + // yarnv2 + process.env.YARN_NPM_REGISTRY_SERVER = registry; + process.env.YARN_UNSAFE_HTTP_WHITELIST = listenAddress; + try { const publishVersion = process.env.PUBLISHED_VERSION ?? 'major'; const isVerbose = process.env.NX_VERBOSE_LOGGING === 'true'; - registryTeardown = await startLocalRegistry({ - localRegistryTarget: '@nx/nx-source:local-registry', - verbose: isVerbose, - clearStorage: true, - }); console.log('Publishing packages to local registry to populate storage'); await runLocalRelease(publishVersion, isVerbose); - - registryTeardown(); - console.log('Killed local registry process'); } catch (err) { - // Clean up registry if possible after setup related errors - if (typeof registryTeardown === 'function') { - registryTeardown(); - console.log('Killed local registry process due to an error during setup'); - } console.error('Error:', err); process.exit(1); } @@ -60,3 +70,10 @@ function runLocalRelease(publishVersion, isVerbose) { }); } exports.runLocalRelease = runLocalRelease; + +async function assertLocalRegistryIsRunning(url) { + const response = await fetch(url); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } +}