chore(core): add unit tests for not connected to nx cloud (#26885)

<!-- 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 -->

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

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

Fixes #
This commit is contained in:
Emily Xiong 2024-07-12 10:25:55 -07:00 committed by GitHub
parent adacd983b7
commit aa7c5dc3ea
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 1612 additions and 353 deletions

View File

@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`ci-workflow generator circleci pipeline should match snapshot 1`] = `
exports[`ci-workflow generator connected to nxCloud circleci pipeline should match snapshot 1`] = `
"version: 2.1
orbs:
@ -25,6 +25,7 @@ jobs:
- nx/set-shas:
main-branch-name: 'main'
# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected
- run: ./nx affected --base=$NX_BASE --head=$NX_HEAD -t test build
workflows:
@ -36,7 +37,7 @@ workflows:
"
`;
exports[`ci-workflow generator github pipeline should match snapshot 1`] = `
exports[`ci-workflow generator connected to nxCloud github pipeline should match snapshot 1`] = `
"name: CI
on:
@ -74,6 +75,89 @@ jobs:
- uses: nrwl/nx-set-shas@v4
# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected
- run: ./nx affected -t test build
"
`;
exports[`ci-workflow generator not connected to nxCloud circleci pipeline should match snapshot 1`] = `
"version: 2.1
orbs:
nx: nrwl/nx@1.6.2
jobs:
main:
environment:
# Configure the JVM and Gradle to avoid OOM errors
_JAVA_OPTIONS: '-Xmx3g'
GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.workers.max=2'
docker:
- image: cimg/openjdk:17.0-node
steps:
- checkout
# This enables task distribution via Nx Cloud
# Run this command as early as possible, before dependencies are installed
# Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun
# Connect your workspace by running "nx connect" and uncomment this
# - run: npx nx-cloud start-ci-run --distribute-on="5 linux-medium-jvm" --stop-agents-after="build"
- nx/set-shas:
main-branch-name: 'main'
# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected
- run: ./nx affected --base=$NX_BASE --head=$NX_HEAD -t test build
workflows:
version: 2
ci:
jobs:
- main
"
`;
exports[`ci-workflow generator not connected to nxCloud github pipeline should match snapshot 1`] = `
"name: CI
on:
push:
branches:
- main
pull_request:
permissions:
actions: read
contents: read
jobs:
main:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
# This enables task distribution via Nx Cloud
# Run this command as early as possible, before dependencies are installed
# Learn more at https://nx.dev/ci/reference/nx-cloud-cli#npx-nxcloud-startcirun
# Connect your workspace by running "nx connect" and uncomment this
# - run: npx nx-cloud start-ci-run --distribute-on="5 linux-medium-jvm" --stop-agents-after="build"
- name: Set up JDK 17 for x64
uses: actions/setup-java@v4
with:
java-version: '17'
distribution: 'temurin'
architecture: x64
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- uses: nrwl/nx-set-shas@v4
# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected
- run: ./nx affected -t test build
"
`;

View File

@ -25,7 +25,7 @@ jobs:
main-branch-name: '<%= mainBranch %>'
<% for (const command of commands) { %>
- run: <%= command %><% } %>
<% if (command.command) { %>- run: <%= command.command %><% } else if (command.comment) { %><%= command.comment %><% } else {%>- run: <%= command %><% } %><% } %>
workflows:
version: 2

View File

@ -39,4 +39,4 @@ jobs:
- uses: nrwl/nx-set-shas@v4
<% for (const command of commands) { %>
- run: <%= command %><% } %>
<% if (command.command) { %>- run: <%= command.command %><% } else if (command.comment) { %><%= command.comment %><% } else {%>- run: <%= command %><% } %><% } %>

View File

@ -8,21 +8,45 @@ describe('ci-workflow generator', () => {
beforeEach(() => {
tree = createTreeWithEmptyWorkspace();
const nxJson = readNxJson(tree);
nxJson.nxCloudAccessToken = 'test';
updateNxJson(tree, nxJson);
});
describe.each([
['github', '.github/workflows/ci.yml'],
['circleci', '.circleci/config.yml'],
] as const)(`%s pipeline`, (ciProvider, output) => {
it('should match snapshot', async () => {
await ciWorkflowGenerator(tree, {
name: 'CI',
ci: ciProvider,
['connected to nxCloud', true],
['not connected to nxCloud', false],
] as const)(`%s`, (_, connectedToCloud) => {
let nxCloudAccessToken: string;
beforeEach(() => {
if (connectedToCloud) {
const nxJson = readNxJson(tree);
nxJson.nxCloudAccessToken = 'test';
updateNxJson(tree, nxJson);
} else {
nxCloudAccessToken = process.env.NX_CLOUD_ACCESS_TOKEN;
delete process.env.NX_CLOUD_ACCESS_TOKEN;
}
});
afterEach(() => {
if (connectedToCloud) {
const nxJson = readNxJson(tree);
delete nxJson.nxCloudAccessToken;
updateNxJson(tree, nxJson);
} else {
process.env.NX_CLOUD_ACCESS_TOKEN = nxCloudAccessToken;
}
});
describe.each([
['github', '.github/workflows/ci.yml'],
['circleci', '.circleci/config.yml'],
] as const)(`%s pipeline`, (ciProvider, output) => {
it('should match snapshot', async () => {
await ciWorkflowGenerator(tree, {
name: 'CI',
ci: ciProvider,
});
expect(tree.read(output, 'utf-8')).toMatchSnapshot();
});
expect(tree.read(output, 'utf-8')).toMatchSnapshot();
});
});
});

View File

@ -11,22 +11,36 @@ import { join } from 'path';
import { getNxCloudUrl, isNxCloudUsed } from 'nx/src/utils/nx-cloud-utils';
import { deduceDefaultBase } from 'nx/src/utils/default-base';
function getCiCommands(ci: Schema['ci'], mainBranch: string): string[] {
function getCiCommands(ci: Schema['ci']): Command[] {
switch (ci) {
case 'circleci': {
return [`./nx affected --base=$NX_BASE --head=$NX_HEAD -t test build`];
return [
{
comment: `# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected`,
},
{
command: `./nx affected --base=$NX_BASE --head=$NX_HEAD -t test build`,
},
];
}
default: {
return [`./nx affected -t test build`];
return [
{
comment: `# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected`,
},
{ command: `./nx affected -t test build` },
];
}
}
}
export type Command = { command: string } | { comment: string } | string;
export interface Schema {
name: string;
ci: 'github' | 'circleci';
packageManager?: null;
commands?: string[];
commands?: Command[];
}
export async function ciWorkflowGenerator(tree: Tree, schema: Schema) {
@ -43,7 +57,7 @@ interface Substitutes {
workflowFileName: string;
packageManager: string;
packageManagerPrefix: string;
commands: string[];
commands: Command[];
nxCloudHost: string;
connectedToCloud: boolean;
}
@ -64,7 +78,7 @@ function getTemplateData(tree: Tree, options: Schema): Substitutes {
const mainBranch = deduceDefaultBase();
const commands = options.commands ?? getCiCommands(options.ci, mainBranch);
const commands = options.commands ?? getCiCommands(options.ci);
const connectedToCloud = isNxCloudUsed(readNxJson(tree));

View File

@ -35,103 +35,130 @@ describe('CI Workflow generator', () => {
beforeEach(() => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
const nxJson = readNxJson(tree);
nxJson.nxCloudAccessToken = 'test';
updateNxJson(tree, nxJson);
});
afterEach(() => {
vol.reset();
});
['npm', 'yarn', 'pnpm', 'bun'].forEach((packageManager: PackageManager) => {
describe(`with ${packageManager}`, () => {
beforeEach(() => {
let fileSys;
if (packageManager === 'bun') {
fileSys = { 'bun.lockb': '' };
} else if (packageManager === 'yarn') {
fileSys = { 'yarn.lock': '' };
} else if (packageManager === 'pnpm') {
fileSys = { 'pnpm-lock.yaml': '' };
} else {
fileSys = { 'package-lock.json': '' };
}
vol.fromJSON(fileSys, '');
});
describe.each([
['connected to nxCloud', true],
['not connected to nxCloud', false],
] as const)(`%s`, (_, connectedToCloud) => {
let nxCloudAccessToken: string;
it('should generate github CI config', async () => {
await ciWorkflowGenerator(tree, { ci: 'github', name: 'CI' });
expect(
tree.read('.github/workflows/ci.yml', 'utf-8')
).toMatchSnapshot();
});
it('should generate circleci CI config', async () => {
await ciWorkflowGenerator(tree, { ci: 'circleci', name: 'CI' });
expect(tree.read('.circleci/config.yml', 'utf-8')).toMatchSnapshot();
});
it('should generate azure CI config', async () => {
await ciWorkflowGenerator(tree, { ci: 'azure', name: 'CI' });
expect(tree.read('azure-pipelines.yml', 'utf-8')).toMatchSnapshot();
});
it('should generate github CI config with custom name', async () => {
await ciWorkflowGenerator(tree, {
ci: 'github',
name: 'My custom-workflow',
});
expect(
tree.read('.github/workflows/my-custom-workflow.yml', 'utf-8')
).toMatchSnapshot();
});
it('should generate bitbucket pipelines config', async () => {
await ciWorkflowGenerator(tree, {
ci: 'bitbucket-pipelines',
name: 'CI',
});
expect(tree.read('bitbucket-pipelines.yml', 'utf-8')).toMatchSnapshot();
});
it('should prefix nx.json affected defaultBase with origin/ if ci is bitbucket-pipelines', async () => {
const nxJson = readJson(tree, 'nx.json');
nxJson.affected.defaultBase = 'my-branch';
writeJson(tree, 'nx.json', nxJson);
await ciWorkflowGenerator(tree, {
ci: 'bitbucket-pipelines',
name: 'CI',
});
expect(readJson(tree, 'nx.json').affected.defaultBase).toEqual(
'origin/my-branch'
);
});
it('should prefix nx.json base with origin/ if ci is bitbucket-pipelines', async () => {
beforeEach(() => {
if (connectedToCloud) {
const nxJson = readNxJson(tree);
nxJson.defaultBase = 'my-branch';
writeJson(tree, 'nx.json', nxJson);
nxJson.nxCloudAccessToken = 'test';
updateNxJson(tree, nxJson);
} else {
nxCloudAccessToken = process.env.NX_CLOUD_ACCESS_TOKEN;
delete process.env.NX_CLOUD_ACCESS_TOKEN;
}
});
await ciWorkflowGenerator(tree, {
ci: 'bitbucket-pipelines',
name: 'CI',
afterEach(() => {
if (connectedToCloud) {
const nxJson = readNxJson(tree);
delete nxJson.nxCloudAccessToken;
updateNxJson(tree, nxJson);
} else {
process.env.NX_CLOUD_ACCESS_TOKEN = nxCloudAccessToken;
}
});
['npm', 'yarn', 'pnpm', 'bun'].forEach((packageManager: PackageManager) => {
describe(`with ${packageManager}`, () => {
beforeEach(() => {
let fileSys;
if (packageManager === 'bun') {
fileSys = { 'bun.lockb': '' };
} else if (packageManager === 'yarn') {
fileSys = { 'yarn.lock': '' };
} else if (packageManager === 'pnpm') {
fileSys = { 'pnpm-lock.yaml': '' };
} else {
fileSys = { 'package-lock.json': '' };
}
vol.fromJSON(fileSys, '');
});
expect(readNxJson(tree).defaultBase).toEqual('origin/my-branch');
});
it('should generate github CI config', async () => {
await ciWorkflowGenerator(tree, { ci: 'github', name: 'CI' });
it('should generate gitlab config', async () => {
await ciWorkflowGenerator(tree, { ci: 'gitlab', name: 'CI' });
expect(
tree.read('.github/workflows/ci.yml', 'utf-8')
).toMatchSnapshot();
});
expect(tree.read('.gitlab-ci.yml', 'utf-8')).toMatchSnapshot();
it('should generate circleci CI config', async () => {
await ciWorkflowGenerator(tree, { ci: 'circleci', name: 'CI' });
expect(tree.read('.circleci/config.yml', 'utf-8')).toMatchSnapshot();
});
it('should generate azure CI config', async () => {
await ciWorkflowGenerator(tree, { ci: 'azure', name: 'CI' });
expect(tree.read('azure-pipelines.yml', 'utf-8')).toMatchSnapshot();
});
it('should generate github CI config with custom name', async () => {
await ciWorkflowGenerator(tree, {
ci: 'github',
name: 'My custom-workflow',
});
expect(
tree.read('.github/workflows/my-custom-workflow.yml', 'utf-8')
).toMatchSnapshot();
});
it('should generate bitbucket pipelines config', async () => {
await ciWorkflowGenerator(tree, {
ci: 'bitbucket-pipelines',
name: 'CI',
});
expect(
tree.read('bitbucket-pipelines.yml', 'utf-8')
).toMatchSnapshot();
});
it('should prefix nx.json affected defaultBase with origin/ if ci is bitbucket-pipelines', async () => {
const nxJson = readJson(tree, 'nx.json');
nxJson.affected.defaultBase = 'my-branch';
writeJson(tree, 'nx.json', nxJson);
await ciWorkflowGenerator(tree, {
ci: 'bitbucket-pipelines',
name: 'CI',
});
expect(readJson(tree, 'nx.json').affected.defaultBase).toEqual(
'origin/my-branch'
);
});
it('should prefix nx.json base with origin/ if ci is bitbucket-pipelines', async () => {
const nxJson = readNxJson(tree);
nxJson.defaultBase = 'my-branch';
writeJson(tree, 'nx.json', nxJson);
await ciWorkflowGenerator(tree, {
ci: 'bitbucket-pipelines',
name: 'CI',
});
expect(readNxJson(tree).defaultBase).toEqual('origin/my-branch');
});
it('should generate gitlab config', async () => {
await ciWorkflowGenerator(tree, { ci: 'gitlab', name: 'CI' });
expect(tree.read('.gitlab-ci.yml', 'utf-8')).toMatchSnapshot();
});
});
});
});

View File

@ -65,5 +65,6 @@ jobs:
# Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud
# - script: <%= packageManagerPrefix %> nx-cloud record -- echo Hello World
# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected
- script: <%= packageManagerPrefix %> nx affected --base=$(BASE_SHA) --head=$(HEAD_SHA) lint test build<% if(hasE2E){ %>
- script: <%= packageManagerPrefix %> nx affected --base=$(BASE_SHA) --head=$(HEAD_SHA) --parallel 1 e2e-ci<% } %>

View File

@ -29,6 +29,7 @@ pipelines:
- <%= packageManagerInstall %>
- <%= packageManagerPrefix %> nx-cloud record -- nx format:check
# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected
- <%= packageManagerPrefix %> nx affected --base=origin/<%= mainBranch %> -t lint test build<% if(hasE2E){ %>
- <%= packageManagerPrefix %> nx affected --base=origin/<%= mainBranch %> --parallel 1 -t e2e-ci<% } %>
@ -55,4 +56,5 @@ pipelines:
# Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud
# - <%= packageManagerPrefix %> nx-cloud record -- echo Hello World
# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected
- <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasE2E){ %> e2e-ci<% } %> --base=HEAD~1

View File

@ -34,6 +34,7 @@ jobs:
# Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud
# - run: <%= packageManagerPrefix %> nx-cloud record -- echo Hello World
# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected
- run: <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD -t lint test build<% if(hasE2E){ %>
- run: <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD --parallel 1 -t e2e-ci<% } %>

View File

@ -47,5 +47,6 @@ jobs:
# Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud
# - run: <%= packageManagerPrefix %> nx-cloud record -- echo Hello World
# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected
- run: <%= packageManagerPrefix %> nx affected -t lint test build<% if(hasE2E){ %>
- run: <%= packageManagerPrefix %> nx affected --parallel 1 -t e2e-ci<% } %>

View File

@ -28,5 +28,6 @@ variables:
# Prepend any command with "nx-cloud record --" to record its logs to Nx Cloud
# - <%= packageManagerPrefix %> nx-cloud record -- echo Hello World
# Nx Affected runs only tasks affected by the changes in this PR/commit. Learn more: https://nx.dev/ci/features/affected
- <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD -t lint test build<% if(hasE2E){ %>
- <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD --parallel 1 -t e2e-ci<% } %>