CI/CD avancé pour les projets JavaScript avec GitHub Actions
L'automatisation de la construction, des tests et du déploiement (CI/CD) est une partie essentielle du développement moderne en JavaScript. Si vous maîtrisez déjà les pipelines de base de GitHub Actions, il est temps de passer au niveau supérieur. Dans cet article, nous aborderons les techniques avancées : mise en cache des dépendances, builds matriciels, exécution parallèle des tâches, gestion sécurisée des secrets et déploiement automatique sur VPS et Docker. Tous les exemples sont orientés vers les projets Node.js.
1. Optimisation du temps de build : mise en cache et déclenchements conditionnels
L'un des principaux problèmes des pipelines de base est l'installation longue de node_modules à chaque exécution. GitHub Actions permet de mettre en cache les dépendances, ce qui réduit le temps d'exécution de 2 à 4 fois.
Utilisez l'action actions/cache pour mettre en cache node_modules ou ~/.npm :
name: CI Pipelineon: [push, pull_request]
jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20'
- name: Cache node_modules uses: actions/cache@v3 id: npm-cache with: path: node_modules key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} restore-keys: | ${{ runner.os }}-node-
- name: Install dependencies if: steps.npm-cache.outputs.cache-hit != 'true' run: npm ciConseils avancés :
- Utilisez
hashFiles('package-lock.json')pour une invalidation précise du cache lors des modifications des dépendances. - Pour les monorepos, mettez en cache chaque package séparément avec
path: packages/*/node_modules. - Ajoutez des déclenchements conditionnels (
if: github.ref == 'refs/heads/main') pour que les tâches lourdes (par exemple, la construction de la version de production) ne s'exécutent que lors des pushes sur la branche main.
2. Builds matriciels et tâches parallèles
La stratégie matricielle permet d'exécuter un même workflow avec différents paramètres. C'est indispensable pour tester sur plusieurs versions de Node.js ou systèmes d'exploitation.
jobs: test: strategy: matrix: node-version: [18, 20, 22] os: [ubuntu-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 - name: Use Node.js ${{ matrix.node-version }} uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} - run: npm ci - run: npm testPour l'exécution parallèle de tâches indépendantes (par exemple, linting, tests unitaires, tests d'intégration), utilisez des jobs séparés. Ils s'exécutent simultanément sans se bloquer mutuellement :
jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm ci - run: npm run lint
unit-tests: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm ci - run: npm run test:unit
integration-tests: needs: [lint, unit-tests] # attend la fin de lint et unit runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: npm ci - run: npm run test:integrationImportant : Utilisez needs pour définir l'ordre d'exécution des tâches dépendantes. Cela permet d'économiser du temps et des ressources.
3. Déploiement avancé : Docker et VPS avec utilisation d'artefacts
Après des tests réussis, il est nécessaire de déployer l'application. Examinons deux scénarios populaires : le déploiement dans une image Docker et sur un VPS.
3.1. Construction et publication d'une image Docker
jobs: build-and-push: needs: [test] runs-on: ub