Gérer les versions de ses charts Helm peut rapidement devenir complexe. Les outils courants d'automatisation de releases imposent souvent de créer un dépôt dédié par chart, ce qui devient difficile à maintenir lorsque leur nombre augmente.
Nx est une solution élégante pour simplifier cette gestion au sein d'un monorepo.
Cette publication s'inspire des travaux d'Antoine Caron. Je vous invite à lire son article Managing Terraform Modules with Nx Monorepo.
Qu'est-ce que Nx ?
Nx est un outil de build conçu pour gérer des monorepos. À l'origine orienté vers les technologies web, il est compatible avec tous les langages et permet d'orchestrer des tâches (lint, build, test, release) sur des projets indépendants au sein d'un même dépôt.
Configuration d'un environnement Nx pour Helm
Construisons ensemble la structure d'un monorepo de charts Helm.
Création du workspace Nx
npx create-nx-workspace@latest helm-charts --preset=npm
cd helm-chartsArborescence
- helm-charts
- charts
- example-chart
- templates
- Chart.yaml
- package.json
- nx.json
- package.json
Chaque chart Helm dispose d'un dossier dédié sous charts/ et d'un fichier package.json permettant de configurer Nx.
Configuration du monorepo
Créons le fichier nx.json avec la configuration suivante :
{
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"release": {
"projects": ["charts/*"],
"projectsRelationship": "independent",
"releaseTagPattern": "{projectName}@v{version}",
"version": {
"conventionalCommits": true
},
"changelog": {
"projectChangelogs": {
"createRelease": "github",
"file": "{projectRoot}/CHANGELOG.md",
"renderOptions": {
"authors": false,
"versionTitleTemplate": "## {version} ({date})",
"commitReferences": true,
"versionTitleDate": true
}
}
},
"git": {
"commit": true,
"tag": true,
"commitMessage": "chore(release): {projectName} {version}"
}
}
}Quelques points clés :
projectsRelationship: "independent"— chaque chart a sa propre version.releaseTagPattern— les tags seront formatés en[email protected].conventionalCommits— la version est définie automatiquement grâce aux messages de commit.
Configuration par chart
Chaque chart dispose d'un package.json qui décrit ses targets Nx :
{
"name": "example-chart",
"version": "0.1.0",
"scripts": {
"post-release": "nx run example-chart:sync-chart-version"
},
"nx": {
"targets": {
"lint": {
"executor": "nx:run-commands",
"options": {
"command": "helm lint --strict .",
"cwd": "charts/example-chart"
}
},
"sync-chart-version": {
"executor": "nx:run-commands",
"options": {
"command": "node ../../scripts/sync-chart-version.mjs example-chart",
"cwd": "charts/example-chart"
}
},
"package": {
"executor": "@nx-extensions/helm:package",
"options": {
"chartFolder": "charts/example-chart",
"outputFolder": "{workspaceRoot}/dist/charts/{projectRoot}",
"remote": "oci://localhost:5000/helm-charts"
}
}
}
}
}On définit ici trois targets :
lint— valide le lint du chart avec la commandehelm lint.sync-chart-version— synchronise la version dupackage.jsonNx vers le fichierChart.yaml.package— empaquette et publie le chart via l'extension @nx-extensions/helm.
Script de synchronisation de version
Le script sync-chart-version.mjs lit la version depuis le package.json du projet Nx et l'injecte dans le Chart.yaml :
import { readFileSync, writeFileSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const chartName = process.argv[2];
const chartDir = join(dirname(fileURLToPath(import.meta.url)), '..', 'charts', chartName);
const { version } = JSON.parse(readFileSync(join(chartDir, 'package.json'), 'utf8'));
const chartPath = join(chartDir, 'Chart.yaml');
const chart = readFileSync(chartPath, 'utf8');
writeFileSync(chartPath, chart.replace(/^version: .+$/m, `version: ${version}`));Votre monorepo est prêt à accueillir vos charts Helm.
Le flux de release
Voici comment s'enchaînent les étapes lors d'une release :
- Un développeur pousse un commit sur la branche principale
- Nx détecte les projets concernés par le commit
- Pour chaque chart modifié,
nx releaseexécute :- Calcul de la nouvelle version (conventional commits)
- Mise à jour du
CHANGELOG.md - Création du tag Git (
[email protected]) - Exécution du hook
post-releasequi appellesync-chart-versionpuispackage
- Le chart est publié dans un registry OCI
Déclenchement manuel
# Release d'un chart spécifique
nx release example-chart --skip-publish
# Release de tous les charts modifiés
nx release --projects=charts/*Vous pouvez faire un test à blanc en ajoutant l'option
--dry-run.
CI/CD avec GitHub Actions
name: Nx CI
on:
push:
branches: ["main"]
jobs:
lint-release:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Install pnpm
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6.0.8
with:
version: 11
- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 24
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Run lint
run: npx nx affected -t lint
- name: Run Nx release
if: github.ref == 'refs/heads/main'
run: CI=true npx nx release --skip-publish
- name: Package and push Helm charts
if: github.ref == 'refs/heads/main'
run: npx nx run-many -t package --projects=charts/*
- name: Chart post-release tasks
if: github.ref == 'refs/heads/main'
run: |
npx nx run-many -t post-release --projects=charts/*
git add charts/
# if there are changes to commit, commit and push them
if [ -n "$(git status --porcelain)" ]; then
git commit -m "chore(post-release): sync chart version"
git push
else
echo "No changes detected. Skipping commit."
fiDépôt exemple
J'utilise moi-même cette configuration Nx pour mes charts Helm. Le dépôt christian-vdz/helm-charts contient actuellement 3 charts :
deployment-start-stop— monte ou descend le nombre de réplicas d'un déploiementpapra— déploie Papra, un gestionnaire de documentsstatistics-for-strava— déploie Statistics for Strava
Chaque chart suit le même modèle : lint → nx release (conventional commits) → synchronisation automatique de la version dans Chart.yaml et la documentation → publication OCI.
À ce jour, 39 releases ont été publiées via ce pipeline.
La documentation est générée avec hextra et accessible sur christian-vdz.github.io/helm-charts.
Conclusion
Nx permet de centraliser et d'automatiser le versionnage de vos charts Helm dans un monorepo, sans duplication d'outillage. Chaque chart garde sa propre version, les changelogs sont générés automatiquement, et la publication dans un registry OCI s'intègre nativement dans votre pipeline CI/CD.
Cette approche s'adapte aussi à d'autres types de projets (packages npm, modules Terraform, images Docker, etc.) — une fois le modèle maîtrisé, il se décline facilement.