Check out my talk at TDC 2024 with title Using NX to Manage Services Inside Monorepo:
You can also access slides directly at slides.horm.codes/tdc-2024. Fun fact, the slide repository uses Nx by itself (see here for more details).
Resources
Here are some code snippets that can be useful when using Nx…
Continuous Integration in GitHub Actions:
Workflow example:
name: CI
on:
pull_request:
env:
NODE_VERSION: 20
jobs:
lint:
name: Lint Code
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'yarn'
- run: yarn install --frozen-lockfile --prefer-offline
- run: yarn nx affected -t lint --base=origin/main --parallel=3
unit_tests:
runs-on: ubuntu-latest
name: Run unit tests
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'yarn'
- run: yarn install --frozen-lockfile --prefer-offline
- run: yarn nx affected -t test --base=origin/main
Continuous Deployment in GitHub Actions:
Workflow example:
name: CD
on:
push:
branches:
- main
env:
NODE_VERSION: 20
jobs:
deploy:
runs-on: ubuntu-latest
name: Deploy affected services to dev
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'yarn'
- run: yarn install --frozen-lockfile --prefer-offline
- name: Find last successful workflow run
uses: nrwl/nx-set-shas@v4
- run: yarn nx affected -t deploy
Publishing Libraries to GitHub Maven Registry
Nx config:
{
// ...
"release": {
"projects": [
"lib",
"api-client",
"api-rest-models"
],
"projectsRelationship": "fixed",
"version": {
"conventionalCommits": true,
"git": {
"commit": false
}
},
"changelog": {
"git": {
"commit": false
},
"workspaceChangelog": {
"createRelease": "github"
}
}
}
}
Release script:
const {
releaseChangelog,
releasePublish,
releaseVersion
} = require("nx/release");
const fs = require("fs");
const yargs = require('yargs');
const gradlePropsPath = "./gradle.properties";
(async () => {
const options = await yargs
.version(false) // don't use the default meaning of version in yargs
.option('dryRun', {
alias: 'd',
description:
'Whether or not to perform a dry-run of the release process, defaults to false',
type: 'boolean',
default: false,
})
.parseAsync();
const {
workspaceVersion,
projectsVersionData
} = await releaseVersion({ dryRun: options.dryRun });
if (typeof workspaceVersion !== "string") {
console.warn("No new version detected. Exiting...");
process.exit(0);
return;
}
await releaseChangelog({
versionData: projectsVersionData,
version: workspaceVersion,
dryRun: options.dryRun,
});
if (options.dryRun) {
console.warn("Dry-run mode enabled. Exiting...");
process.exit(0);
return
}
const publishStatus = await releasePublish({ dryRun: options.dryRun });
process.exit(publishStatus);
})();
Workflow example:
name: CD
on:
push:
branches:
- main
env:
NODE_VERSION: 20
jobs:
publish_libs:
runs-on: ubuntu-latest
name: Publish libraries
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.GITHUB_TOKEN }}
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: 'yarn'
- run: yarn install --frozen-lockfile --prefer-offline
- name: Define Git user
run: |
git config user.name github-actions
git config user.email github-actions@github.com
- run: node ./tools/scripts/release.js
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_ACTOR: ${{ github.actor }}