chore(repo): make local-registry continuous (#30789)

<!-- Please make sure you have read the submission guidelines before
posting an PR -->
<!--
https://github.com/nrwl/nx/blob/master/CONTRIBUTING.md#-submitting-a-pr
-->

<!-- Please make sure that your commit message follows our format -->
<!-- Example: `fix(nx): must begin with lowercase` -->

<!-- If this is a particularly complex change or feature addition, you
can request a dedicated Nx release for this pull request branch. Mention
someone from the Nx team or the `@nrwl/nx-pipelines-reviewers` and they
will confirm if the PR warrants its own release for testing purposes,
and generate it for you if appropriate. -->

## Current Behavior
<!-- This is the behavior we have today -->

No continuous tasks are used in CI.

## Expected Behavior
<!-- This is the behavior we should expect with the changes in this PR
-->

The local-registry is a continuous task and it is used in CI.

## Related Issue(s)
<!-- Please link the issue being fixed so it gets closed when this is
merged. -->

Fixes #
This commit is contained in:
Jason Jean 2025-04-28 20:45:34 -04:00 committed by GitHub
parent a3a17531d0
commit cf4a1f35e9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 112 additions and 33 deletions

View File

@ -27,6 +27,8 @@ jobs:
NX_E2E_RUN_E2E: 'true' NX_E2E_RUN_E2E: 'true'
NX_CI_EXECUTION_ENV: 'linux' NX_CI_EXECUTION_ENV: 'linux'
NX_CLOUD_NO_TIMEOUTS: 'true' 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' NX_CLOUD_USE_NEW_STREAM_OUTPUT: 'true'
steps: steps:
@ -106,7 +108,7 @@ jobs:
main-macos: main-macos:
runs-on: macos-latest runs-on: macos-latest
env: env:
NX_E2E_CI_CACHE_KEY: e2e-github-macos NX_E2E_CI_CACHE_KEY: e2e-github-macos
NX_PERF_LOGGING: 'false' NX_PERF_LOGGING: 'false'

View File

@ -1,6 +1,14 @@
distribute-on: distribute-on:
default: auto linux-medium, 1 linux-extra-large default: auto linux-medium, 1 linux-extra-large
assignment-rules: assignment-rules:
- targets:
- e2e-ci**
run-on:
- agent: linux-medium
parallelism: 1
- agent: linux-extra-large
parallelism: 1
- projects: - projects:
- nx-dev - nx-dev
targets: targets:

View File

@ -1,8 +1,7 @@
import { Config } from '@jest/types'; import { Config } from '@jest/types';
import { startLocalRegistry } from '@nx/js/plugins/jest/local-registry';
import { existsSync, removeSync } from 'fs-extra'; import { existsSync, removeSync } from 'fs-extra';
import * as isCI from 'is-ci'; 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 { join } from 'node:path';
import { registerTsConfigPaths } from '../../packages/nx/src/plugins/js/utils/register'; import { registerTsConfigPaths } from '../../packages/nx/src/plugins/js/utils/register';
import { runLocalRelease } from '../../scripts/local-registry/populate-storage'; import { runLocalRelease } from '../../scripts/local-registry/populate-storage';
@ -19,18 +18,54 @@ export default async function (globalConfig: Config.ConfigGlobals) {
const requiresLocalRelease = const requiresLocalRelease =
!process.env.NX_TASK_TARGET_TARGET?.startsWith('e2e-ci'); !process.env.NX_TASK_TARGET_TARGET?.startsWith('e2e-ci');
global.e2eTeardown = await startLocalRegistry({ const listenAddress = 'localhost';
localRegistryTarget: '@nx/nx-source:local-registry', const port = process.env.NX_LOCAL_REGISTRY_PORT ?? '4873';
verbose: isVerbose, const registry = `http://${listenAddress}:${port}`;
clearStorage: requiresLocalRelease, 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 * Set the published version based on what has previously been loaded into the
* verdaccio storage. * verdaccio storage.
*/ */
if (!requiresLocalRelease) { if (!requiresLocalRelease) {
const publishedVersion = await getPublishedVersion(); let publishedVersion = await getPublishedVersion();
console.log(`Testing Published version: Nx ${publishedVersion}`);
if (publishedVersion) { if (publishedVersion) {
process.env.PUBLISHED_VERSION = publishedVersion; process.env.PUBLISHED_VERSION = publishedVersion;
} }
@ -60,6 +95,9 @@ export default async function (globalConfig: Config.ConfigGlobals) {
} }
function getPublishedVersion(): Promise<string | undefined> { function getPublishedVersion(): Promise<string | undefined> {
execSync(`npm config get registry`, {
stdio: 'inherit',
});
return new Promise((resolve) => { return new Promise((resolve) => {
// Resolve the published nx version from verdaccio // Resolve the published nx version from verdaccio
exec( exec(
@ -76,3 +114,10 @@ function getPublishedVersion(): Promise<string | undefined> {
); );
}); });
} }
async function assertLocalRegistryIsRunning(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
}

14
nx.json
View File

@ -149,13 +149,17 @@
}, },
"e2e-ci--**/**": { "e2e-ci--**/**": {
"inputs": ["e2eInputs", "^production"], "inputs": ["e2eInputs", "^production"],
"parallelism": false, "dependsOn": [
"dependsOn": ["@nx/nx-source:populate-local-registry-storage"] "@nx/nx-source:populate-local-registry-storage",
"@nx/nx-source:local-registry"
]
}, },
"e2e-macos-ci--**/*": { "e2e-macos-ci--**/*": {
"inputs": ["e2eInputs", "^production"], "inputs": ["e2eInputs", "^production"],
"parallelism": false, "dependsOn": [
"dependsOn": ["@nx/nx-source:populate-local-registry-storage"] "@nx/nx-source:populate-local-registry-storage",
"@nx/nx-source:local-registry"
]
}, },
"e2e-base": { "e2e-base": {
"inputs": ["default", "^production"] "inputs": ["default", "^production"]
@ -254,7 +258,7 @@
"nxCloudId": "62d013ea0852fe0a2df74438", "nxCloudId": "62d013ea0852fe0a2df74438",
"nxCloudUrl": "https://staging.nx.app", "nxCloudUrl": "https://staging.nx.app",
"parallel": 1, "parallel": 1,
"bust": 7, "bust": 1,
"defaultBase": "master", "defaultBase": "master",
"conformance": { "conformance": {
"rules": [ "rules": [

View File

@ -7,7 +7,8 @@
"options": { "options": {
"port": 4873, "port": 4873,
"config": ".verdaccio/config.yml", "config": ".verdaccio/config.yml",
"storage": "build/local-registry/storage" "storage": "build/local-registry/storage",
"clear": false
} }
}, },
"populate-local-registry-storage": { "populate-local-registry-storage": {
@ -16,9 +17,11 @@
{ {
"input": "production", "input": "production",
"projects": ["tag:npm:public"] "projects": ["tag:npm:public"]
} },
"{workspaceRoot}/scripts/local-registry"
], ],
"dependsOn": [ "dependsOn": [
"local-registry",
{ {
"target": "build", "target": "build",
"projects": ["tag:npm:public"] "projects": ["tag:npm:public"]

View File

@ -1,33 +1,43 @@
// @ts-check // @ts-check
const { exec, execSync } = require('node:child_process');
const { startLocalRegistry } = require('@nx/js/plugins/jest/local-registry');
const { exec } = require('node:child_process');
const { const {
LARGE_BUFFER, LARGE_BUFFER,
} = require('nx/src/executors/run-commands/run-commands.impl'); } = require('nx/src/executors/run-commands/run-commands.impl');
async function populateLocalRegistryStorage() { 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 { try {
const publishVersion = process.env.PUBLISHED_VERSION ?? 'major'; const publishVersion = process.env.PUBLISHED_VERSION ?? 'major';
const isVerbose = process.env.NX_VERBOSE_LOGGING === 'true'; 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'); console.log('Publishing packages to local registry to populate storage');
await runLocalRelease(publishVersion, isVerbose); await runLocalRelease(publishVersion, isVerbose);
registryTeardown();
console.log('Killed local registry process');
} catch (err) { } 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); console.error('Error:', err);
process.exit(1); process.exit(1);
} }
@ -60,3 +70,10 @@ function runLocalRelease(publishVersion, isVerbose) {
}); });
} }
exports.runLocalRelease = runLocalRelease; exports.runLocalRelease = runLocalRelease;
async function assertLocalRegistryIsRunning(url) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
}