Check out my talk at JavaZone 2024 with title Using NX for Monorepo with Gradle Services:
You can also access slides directly at slides.horm.codes/javazone-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 with Gradle…
Continuous Integration in GitHub Actions:
Workflow example:
name: CI
on:
pull_request:
env:
JDK_VERSION: 19
JDK_DISTRIBUTION: temurin
NODE_VERSION: 20
jobs:
lint:
name: Lint Code
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up JDK
uses: actions/setup-java@v4
with:
distribution: ${{ env.JDK_DISTRIBUTION }}
java-version: ${{ env.JDK_VERSION }}
- name: Setup Gradle Cache
uses: gradle/actions/setup-gradle@v4
- 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: Set up JDK
uses: actions/setup-java@v4
with:
distribution: ${{ env.JDK_DISTRIBUTION }}
java-version: ${{ env.JDK_VERSION }}
- name: Setup Gradle Cache
uses: gradle/actions/setup-gradle@v4
- 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:
JDK_VERSION: 19
JDK_DISTRIBUTION: corretto
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: Set up JDK
uses: actions/setup-java@v4
with:
distribution: ${{ env.JDK_DISTRIBUTION }}
java-version: ${{ env.JDK_VERSION }}
- name: Setup Gradle Cache
uses: gradle/actions/setup-gradle@v3
- 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 updateGradleVersion(`v${workspaceVersion}`);
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);
})();
async function updateGradleVersion(newVersion) {
try {
fs.writeFileSync(gradlePropsPath, `version=${newVersion}`, "utf8");
console.log(`gradle.properties file created with version ${newVersion}`);
} catch (err) {
console.error("Error updating gradle.properties file:", err);
}
}
Workflow example:
name: CD
on:
push:
branches:
- main
env:
JDK_VERSION: 19
JDK_DISTRIBUTION: corretto
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: Set up JDK
uses: actions/setup-java@v4
with:
distribution: ${{ env.JDK_DISTRIBUTION }}
java-version: ${{ env.JDK_VERSION }}
- name: Setup Gradle Cache
uses: gradle/actions/setup-gradle@v3
- 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 }}