feat(core): update ci-workflow generator (#21141)

This commit is contained in:
Miroslav Jonaš 2024-01-18 14:47:36 +01:00 committed by GitHub
parent c452a1f7c5
commit e8464cca9e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 284 additions and 718 deletions

View File

@ -46,7 +46,7 @@ If you have a new workspace, you can generate the CI configuration as follows:
nx generate @nx/workspace:ci-workflow --ci=github nx generate @nx/workspace:ci-workflow --ci=github
``` ```
The `--ci` flag can be `github`, `circleci` or `azure`. The `--ci` flag can be `github`, `circleci`, `azure`, `gitlab`, or `bitbucket`.
For existing workspaces you would probably want to adjust your configuration by hand. See below for examples. For existing workspaces you would probably want to adjust your configuration by hand. See below for examples.

View File

@ -1,5 +1,6 @@
import { import {
NxJsonConfiguration, NxJsonConfiguration,
PackageManager,
readJson, readJson,
Tree, Tree,
updateJson, updateJson,
@ -7,6 +8,24 @@ import {
} from '@nx/devkit'; } from '@nx/devkit';
import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing';
import { ciWorkflowGenerator } from './ci-workflow'; import { ciWorkflowGenerator } from './ci-workflow';
import { vol } from 'memfs';
jest.mock('@nx/devkit', () => ({
...jest.requireActual<any>('@nx/devkit'),
workspaceRoot: '/root',
}));
jest.mock('fs', () => {
const memFs = require('memfs').fs;
const actualFs = jest.requireActual<any>('fs');
return {
...jest.requireActual<any>('fs'),
existsSync: (p) =>
p.endsWith('yarn.lock') || p.endsWith('pnpm-lock.yaml')
? memFs.existsSync(p)
: actualFs.existsSync(p),
};
});
describe('CI Workflow generator', () => { describe('CI Workflow generator', () => {
let tree: Tree; let tree: Tree;
@ -15,15 +34,22 @@ describe('CI Workflow generator', () => {
tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' });
}); });
['npm', 'yarn', 'pnpm'].forEach((packageManager) => { afterEach(() => {
vol.reset();
});
['npm', 'yarn', 'pnpm'].forEach((packageManager: PackageManager) => {
describe(`with ${packageManager}`, () => { describe(`with ${packageManager}`, () => {
beforeEach(() => { beforeEach(() => {
jest.mock('@nx/devkit', () => ({ let fileSys;
...jest.requireActual<any>('@nx/devkit'), if (packageManager === 'yarn') {
detectPackageManager: jest fileSys = { 'yarn.lock': '' };
.fn() } else if (packageManager === 'pnpm') {
.mockImplementation(() => packageManager), fileSys = { 'pnpm-lock.yaml': '' };
})); } else {
fileSys = { 'package-lock.json': '' };
}
vol.fromJSON(fileSys, '');
}); });
it('should generate github CI config', async () => { it('should generate github CI config', async () => {

View File

@ -7,6 +7,7 @@ import {
NxJsonConfiguration, NxJsonConfiguration,
formatFiles, formatFiles,
writeJson, writeJson,
detectPackageManager,
} from '@nx/devkit'; } from '@nx/devkit';
import { deduceDefaultBase } from '../../utilities/default-base'; import { deduceDefaultBase } from '../../utilities/default-base';
import { join } from 'path'; import { join } from 'path';
@ -42,6 +43,7 @@ interface Substitutes {
mainBranch: string; mainBranch: string;
workflowName: string; workflowName: string;
workflowFileName: string; workflowFileName: string;
packageManager: string;
packageManagerInstall: string; packageManagerInstall: string;
packageManagerPrefix: string; packageManagerPrefix: string;
tmpl: ''; tmpl: '';
@ -51,11 +53,13 @@ function normalizeOptions(options: Schema): Substitutes {
const { name: workflowName, fileName: workflowFileName } = names( const { name: workflowName, fileName: workflowFileName } = names(
options.name options.name
); );
const packageManager = detectPackageManager();
const { exec: packageManagerPrefix, ciInstall: packageManagerInstall } = const { exec: packageManagerPrefix, ciInstall: packageManagerInstall } =
getPackageManagerCommand(); getPackageManagerCommand(packageManager);
return { return {
workflowName, workflowName,
workflowFileName, workflowFileName,
packageManager,
packageManagerInstall, packageManagerInstall,
packageManagerPrefix, packageManagerPrefix,
mainBranch: deduceDefaultBase(), mainBranch: deduceDefaultBase(),

View File

@ -7,7 +7,6 @@ pr:
variables: variables:
CI: 'true' CI: 'true'
NX_CLOUD_DISTRIBUTED_EXECUTION: 'true'
${{ if eq(variables['Build.Reason'], 'PullRequest') }}: ${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
NX_BRANCH: $(System.PullRequest.PullRequestNumber) NX_BRANCH: $(System.PullRequest.PullRequestNumber)
TARGET_BRANCH: $[replace(variables['System.PullRequest.TargetBranch'],'refs/heads/','origin/')] TARGET_BRANCH: $[replace(variables['System.PullRequest.TargetBranch'],'refs/heads/','origin/')]
@ -18,41 +17,15 @@ variables:
HEAD_SHA: $(git rev-parse HEAD) HEAD_SHA: $(git rev-parse HEAD)
jobs: jobs:
- job: agents
strategy:
parallel: 3
displayName: Nx Cloud Agent
pool:
vmImage: 'ubuntu-latest'
steps:
<% if(packageManagerPrefix == 'pnpm exec'){ %>
- script: npm install --prefix=$HOME/.local -g pnpm@8.2.0
displayName: Install PNPM
<% } %>- script: <%= packageManagerInstall %>
displayName: NPM Install Dependencies
- script: npx nx-cloud start-agent
displayName: Start Nx-Cloud agent
- job: main - job: main
displayName: Nx Cloud Main
pool: pool:
vmImage: 'ubuntu-latest' vmImage: 'ubuntu-latest'
steps: steps:
<% if(packageManagerPrefix == 'pnpm exec'){ %> <% if(packageManager == 'pnpm'){ %>
- script: npm install --prefix=$HOME/.local -g pnpm@8.2.0 - script: npm install --prefix=$HOME/.local -g pnpm@8
displayName: Install PNPM displayName: Install PNPM
<% } %>- script: <%= packageManagerInstall %> <% } %>- script: <%= packageManagerInstall %>
displayName: NPM Install Dependencies # uncomment to enable task distribution
- script: <%= packageManagerPrefix %> nx-cloud start-ci-run --stop-agents-after="build" --agent-count=3 # - script: <%= packageManagerPrefix %> nx-cloud start-ci-run --distributes-on="5 linux-medium"
displayName: Start CI run - script: <%= packageManagerPrefix %> nx-cloud record -- nx format:check --base=$(BASE_SHA) --head=$(HEAD_SHA)
- script: <%= packageManagerPrefix %> nx-cloud record -- <%= packageManagerPrefix %> nx format:check --base=$(BASE_SHA) --head=$(HEAD_SHA) - script: <%= packageManagerPrefix %> nx affected --base=$(BASE_SHA) --head=$(HEAD_SHA) -t=lint,test,build --parallel=3
displayName: Check format
- script: <%= packageManagerPrefix %> nx affected --base=$(BASE_SHA) --head=$(HEAD_SHA) --target=lint --parallel=3
displayName: Run lint
- script: <%= packageManagerPrefix %> nx affected --base=$(BASE_SHA) --head=$(HEAD_SHA) --target=test --parallel=3 --ci --code-coverage
displayName: Run test
- script: <%= packageManagerPrefix %> nx affected --base=$(BASE_SHA) --head=$(HEAD_SHA) --target=build --parallel=3
displayName: Run build
- script: <%= packageManagerPrefix %> nx-cloud stop-all-agents
condition: always()
displayName: Stop all Nx-Cloud agents

View File

@ -1,20 +1,8 @@
image: node:16.18 image: node:20
clone: clone:
depth: full depth: full
definitions:
steps:
- step: &agent
name: Agent
script:
- export NX_BRANCH=$BITBUCKET_PR_ID
<% if(packageManagerPrefix == 'pnpm exec'){ %>
- npm install --prefix=$HOME/.local -g pnpm@8.2.0
<% } %>
- <%= packageManagerInstall %>
- <%= packageManagerPrefix %> nx-cloud start-agent
pipelines: pipelines:
pull-requests: pull-requests:
'**': '**':
@ -23,14 +11,11 @@ pipelines:
name: <%= workflowName %> name: <%= workflowName %>
script: script:
- export NX_BRANCH=$BITBUCKET_PR_ID - export NX_BRANCH=$BITBUCKET_PR_ID
<% if(packageManagerPrefix == 'pnpm exec'){ %> <% if(packageManager == 'pnpm'){ %>
- npm install --prefix=$HOME/.local -g pnpm@8.2.0 - npm install --prefix=$HOME/.local -g pnpm@8
<% } %> <% } %>
- <%= packageManagerInstall %> - <%= packageManagerInstall %>
- <%= packageManagerPrefix %> nx-cloud start-ci-run --stop-agents-after="build" --agent-count=3 # uncomment to enable task distribution
- <%= packageManagerPrefix %> nx-cloud record -- <%= packageManagerPrefix %> nx format:check # - <%= packageManagerPrefix %> nx-cloud start-ci-run --distributes-on="5 linux-medium"
- <%= packageManagerPrefix %> nx affected --target=lint & <%= packageManagerPrefix %> nx affected --target=test & <%= packageManagerPrefix %> nx affected --target=build - <%= packageManagerPrefix %> nx-cloud record -- nx format:check
- <%= packageManagerPrefix %> nx-cloud stop-all-agents - <%= packageManagerPrefix %> nx affected -t=lint,test,build --parallel=3
- step: *agent
- step: *agent
- step: *agent

View File

@ -1,73 +1,29 @@
version: 2.1 version: 2.1
orbs: orbs:
nx: nrwl/nx@1.6.1 nx: nrwl/nx@1.6.2
jobs: jobs:
agent:
docker:
- image: cimg/node:lts-browsers
parameters:
ordinal:
type: integer
steps:
- checkout
<% if(packageManagerPrefix == 'pnpm exec'){ %>
- run:
name: Install PNPM
command: npm install --prefix=$HOME/.local -g pnpm@8.2.0
<% } %>- run:
name: Install dependencies
command: <%= packageManagerInstall %>
- run:
name: Start the agent << parameters.ordinal >>
command: <%= packageManagerPrefix %> nx-cloud start-agent
no_output_timeout: 60m
main: main:
docker: docker:
- image: cimg/node:lts-browsers - image: cimg/node:lts-browsers
environment:
NX_CLOUD_DISTRIBUTED_EXECUTION: 'true'
steps: steps:
- checkout - checkout
<% if(packageManagerPrefix == 'pnpm exec'){ %> <% if(packageManager == 'pnpm'){ %>
- run: - run:
name: Install PNPM name: Install PNPM
command: npm install --prefix=$HOME/.local -g pnpm@8.2.0 command: npm install --prefix=$HOME/.local -g pnpm@8
<% } %>- run: <% } %>- run: <%= packageManagerInstall %>
name: Install dependencies
command: <%= packageManagerInstall %>
- nx/set-shas: - nx/set-shas:
main-branch-name: '<%= mainBranch %>' main-branch-name: '<%= mainBranch %>'
- run: # uncomment to enable task distribution
name: Initialize the Nx Cloud distributed CI run # - run: <%= packageManagerPrefix %> nx-cloud start-ci-run --distributes-on="5 linux-medium"
command: <%= packageManagerPrefix %> nx-cloud start-ci-run --stop-agents-after="build" --agent-count=3 - run: <%= packageManagerPrefix %> nx-cloud record -- nx format:check --base=$NX_BASE --head=$NX_HEAD
- run: - run: <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD -t=lint,test,build --parallel=3
name: Check format
command: <%= packageManagerPrefix %> nx-cloud record -- <%= packageManagerPrefix %> nx format:check --base=$NX_BASE --head=$NX_HEAD
- run:
name: Run lint
command: <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD --target=lint --parallel=3
- run:
name: Run test
command: <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD --target=test --parallel=3 --ci --code-coverage
- run:
name: Run build
command: <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD --target=build --parallel=3
- run:
name: Stop all agents
command: <%= packageManagerPrefix %> nx-cloud stop-all-agents
when: always
workflows: workflows:
version: 2 version: 2
<%= workflowFileName %>: <%= workflowFileName %>:
jobs: jobs:
- agent: - main
name: Nx Cloud Agent << matrix.ordinal >>
matrix:
parameters:
ordinal: [1, 2, 3]
- main:
name: Nx Cloud Main

View File

@ -6,29 +6,31 @@ on:
- <%= mainBranch %> - <%= mainBranch %>
pull_request: pull_request:
# Needed for nx-set-shas within nx-cloud-main.yml, when run on the <%= mainBranch %> branch
permissions: permissions:
actions: read actions: read
contents: read contents: read
jobs: jobs:
main: main:
name: Nx Cloud - Main Job runs-on: ubuntu-latest
uses: nrwl/ci/.github/workflows/nx-cloud-main.yml@v0.13.1 steps:
with: - uses: actions/checkout@v4
main-branch-name: <%= mainBranch %> with:
number-of-agents: 3 fetch-depth: 0
init-commands: | <% if(packageManager == 'pnpm'){ %>
<%= packageManagerPrefix %> nx-cloud start-ci-run --stop-agents-after="build" --agent-count=3 - uses: pnpm/action-setup@v2
parallel-commands: | with:
<%= packageManagerPrefix %> nx-cloud record -- <%= packageManagerPrefix %> nx format:check version: 8
parallel-commands-on-agents: | <% } %># Cache node_modules
<%= packageManagerPrefix %> nx affected --target=lint --parallel=3 - uses: actions/setup-node@v3
<%= packageManagerPrefix %> nx affected --target=test --parallel=3 --ci --code-coverage with:
<%= packageManagerPrefix %> nx affected --target=build --parallel=3 node-version: 20
cache: '<%= packageManager %>'
- run: <%= packageManagerInstall %>
- uses: nrwl/nx-set-shas@v4
agents: # uncomment to enable task distribution
name: Nx Cloud - Agents # - run: <%= packageManagerPrefix %> nx-cloud start-ci-run --distributes-on="5 linux-medium"
uses: nrwl/ci/.github/workflows/nx-cloud-agents.yml@v0.13.1
with: - run: <%= packageManagerPrefix %> nx-cloud record -- nx format:check
number-of-agents: 3 - run: <%= packageManagerPrefix %> nx affected -t=lint,test,build --parallel=3

View File

@ -1,47 +1,21 @@
image: node:18 image: node:20
variables: variables:
CI: 'true' CI: 'true'
# Creating template for DTE agents # Main job
.dte-agent: <%= workflowName %>:
interruptible: true
script:
<% if(packageManagerPrefix == 'pnpm exec'){ %>
- npm install --prefix=$HOME/.local -g pnpm@8.2.0
<% } %>
- <%= packageManagerInstall %>
- <%= packageManagerPrefix %> nx-cloud start-agent
# Creating template for a job running DTE (orchestrator)
.base-pipeline:
interruptible: true interruptible: true
only: only:
- main - main
- merge_requests - merge_requests
before_script: script:
<% if(packageManagerPrefix == 'pnpm exec'){ %> <% if(packageManager == 'pnpm'){ %>
- npm install --prefix=$HOME/.local -g pnpm@8.2.0 - npm install --prefix=$HOME/.local -g pnpm@8
<% } %> <% } %>
- <%= packageManagerInstall %> - <%= packageManagerInstall %>
- NX_HEAD=$CI_COMMIT_SHA - NX_HEAD=$CI_COMMIT_SHA
- NX_BASE=${CI_MERGE_REQUEST_DIFF_BASE_SHA:-$CI_COMMIT_BEFORE_SHA} - NX_BASE=${CI_MERGE_REQUEST_DIFF_BASE_SHA:-$CI_COMMIT_BEFORE_SHA}
# uncomment to enable task distribution
# Main job running DTE # - <%= packageManagerPrefix %> nx-cloud start-ci-run --distributes-on="5 linux-medium"
<%= workflowName %>: - <%= packageManagerPrefix %> nx-cloud record -- nx format:check --base=$NX_BASE --head=$NX_HEAD
stage: affected - <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD -t=lint,test,build --parallel=3
extends: .base-pipeline
script:
- <%= packageManagerPrefix %> nx-cloud start-ci-run --stop-agents-after="build"
- <%= packageManagerPrefix %> nx-cloud record -- <%= packageManagerPrefix %> nx format:check --base=$NX_BASE --head=$NX_HEAD
- <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD --target=lint --parallel=3 & <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD --target=test --parallel=3 --ci --code-coverage & <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD --target=e2e --parallel=3 --ci --code-coverage & <%= packageManagerPrefix %> nx affected --base=$NX_BASE --head=$NX_HEAD --target=build --parallel=3
# Create as many agents as you want
nx-dte-agent1:
extends: .dte-agent
stage: affected
nx-dte-agent2:
extends: .dte-agent
stage: affected
nx-dte-agent3:
extends: .dte-agent
stage: affected