CI/CD pour NestJS avec GitHub Actions
Pourquoi CI/CD pour NestJS avec GitHub Actions ?
Au quotidien, un développeur peut avoir besoin de tester et d'automatiser la livraison continue de son code pour plusieurs raisons :
- Amélioration de la qualité du logiciel : En automatisant les tests, vous pouvez détecter rapidement les erreurs potentielles avant que le code ne passe à l'étape de déploiement.
- Accélération du temps de développement : Avec des pipelines d'intégration continue et de livraison continue en place, les tests et les déploiements sont effectués automatiquement après chaque commit, ce qui accélère le processus de développement.
- Réduction des erreurs humaines : Les développeurs peuvent se concentrer sur l'écriture du code et non sur la gestion manuelle des tests et des déploiements.
Un cas d'utilisation concret pourrait être un équipe qui travaille sur une application de gestion de tâches. Chaque fois qu'un nouveau commit est fait dans le référentiel Git, les tests doivent être exécutés pour s'assurer que rien n'a cassé et que l'application reste fonctionnelle.
Prerequis
Pour suivre ce tutoriel, vous aurez besoin des éléments suivants :
- Connaissances en NestJS
- Un compte GitHub
- Node.js 12.0 ou supérieure
- npm ou yarn pour gérer les dépendances
- Git pour versionner le code
Concepts fondamentaux
1. Workflow
Un workflow est un processus automatisé qui exécute des étapes définies par l'utilisateur. Chaque workflow est défini dans un fichier YAML et se trouve à la racine de votre dépôt.
## .github/workflows/nodejs.yml
name: Node.js CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x, 14.x, 16.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js $matrix.node-version
uses: actions/setup-node@v2
with:
node-version: $matrix.node-version
- run: npm ci
- run: npm run build --if-present
2. Job
Un job est une série d'étapes à exécuter. Chaque job peut être exécuté sur un environnement différent.
## .github/workflows/nodejs.yml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm ci
- run: npm test
3. Steps
Un step est une étape spécifique à exécuter dans un job. Chaque step peut être une commande shell, une action GitHub ou un script personnalisé.
## .github/workflows/nodejs.yml
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Run tests
run: npm test
4. Actions
Les actions sont des scripts préconçus qui peuvent être réutilisés dans différents workflows.
## .github/workflows/nodejs.yml
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14'
5. Matrix
La matrix permet d'exécuter des jobs sur plusieurs configurations différentes.
## .github/workflows/nodejs.yml
strategy:
matrix:
node-version: [12.x, 14.x, 16.x]
Mise en pratique : projet fil rouge
Nous allons créer un gestionnaire de tâches simple avec NestJS. Voici les étapes pour mettre en place le CI/CD avec GitHub Actions.
Étape 1 : Création du projet NestJS
## Installer NestJS CLI
npm install -g @nestjs/cli
## Créer un nouveau projet
nest new task-manager
cd task-manager
Étape 2 : Ajout d'une fonctionnalité de création de tâche
Modifier le fichier src/task/task.service.ts :
// src/task/task.service.ts
import { Injectable } from '@nestjs/common';
import { Task } from './task.entity';
@Injectable()
export class TaskService {
private tasks: Task[] = [];
create(task: Task): Task {
this.tasks.push(task);
return task;
}
findAll(): Task[] {
return this.tasks;
}
}
Modifier le fichier src/task/task.controller.ts :
// src/task/task.controller.ts
import { Controller, Post, Body } from '@nestjs/common';
import { TaskService } from './task.service';
import { Task } from './task.entity';
@Controller('tasks')
export class TaskController {
constructor(private readonly taskService: TaskService) {}
@Post()
create(@Body() task: Task): Task {
return this.taskService.create(task);
}
@Get()
findAll(): Task[] {
return this.taskService.findAll();
}
}
Modifier le fichier src/task/task.entity.ts :
// src/task/task.entity.ts
export interface Task {
id?: number;
title: string;
description: string;
completed: boolean;
}
Étape 3 : Ajout des tests
Ajouter un test pour la fonctionnalité de création de tâche dans le fichier src/task/task.service.spec.ts :
// src/task/task.service.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { TaskService } from './task.service';
describe('TaskService', () => {
let service: TaskService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [TaskService],
}).compile();
service = module.get<TaskService>(TaskService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
it('should create a task', () => {
const task = { title: 'Test Task', description: 'This is a test task.', completed: false };
expect(service.create(task)).toEqual(task);
});
});
Étape 4 : Configuration du workflow GitHub Actions
Créer un fichier .github/workflows/nodejs.yml avec le contenu suivant :
## .github/workflows/nodejs.yml
name: Node.js CI
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [12.x, 14.x, 16.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js $matrix.node-version
uses: actions/setup-node@v2
with:
node-version: $matrix.node-version
- run: npm ci
- run: npm run build --if-present
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm ci
- run: npm test
Étape 5 : Exécution du workflow
Push les modifications sur GitHub et observez le pipeline en cours d'exécution dans l'onglet Actions de votre dépôt GitHub.
Erreurs frequentes et debugging
1. Problème avec npm install
Erreur :
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
npm ERR!
npm ERR! Found: @nestjs/common@8.0.0
npm ERR! node_modules/@nestjs/common
npm ERR! @nestjs/common@"^8.0.0" from the root project
npm ERR!
npm ERR! Could not resolve dependencies:
npm ERR! peer @nestjs/core@^7.0.0 from @nestjs/platform-express@7.6.3
npm ERR! node_modules/@nestjs/platform-express
npm ERR! @nestjs/platform-express@"^7.6.3" from the root project
Correction :
## Mettre à jour NestJS CLI et dépendances
npm install -g @nestjs/cli
rm -rf package-lock.json node_modules
npm cache clean --force
npm install
2. Problème avec les tests
Erreur :
FAIL src/task/task.service.spec.ts
● TaskService › should create a task
Expected value to equal:
{ title: 'Test Task', description: 'This is a test task.', completed: false }
Received:
undefined
Correction :
// src/task/task.service.ts
create(task: Task): Task {
this.tasks.push({ ...task, id: this.tasks.length + 1 });
return { ...task, id: this.tasks.length };
}
3. Problème avec le workflow
Erreur :
Error: Node.js version '12.x' not found
Correction :
## .github/workflows/nodejs.yml
strategy:
matrix:
node-version: [14.x, 16.x]
Pour aller plus loin
1. Intégration avec des services externes
Vous pouvez intégrer votre application avec des services tiers comme une base de données ou un service d'authentification pour tester l'application dans un environnement simulé.
2. Déploiement sur AWS
Configurez le déploiement continu vers AWS Elastic Beanstalk en utilisant GitHub Actions et le CLI AWS.
3. Utilisation de Secrets GitHub Actions
Stockez des informations sensibles comme les clés d'API ou les identifiants d'accès dans les secrets GitHub Actions pour une meilleure sécurité.
Défi pratique :
Créez un gestionnaire de blog simple avec NestJS et configurez le CI/CD pour l'automatiser. Vous pouvez ajouter des fonctionnalités comme la création d'article, la mise à jour d'article et la récupération de tous les articles. N'oubliez pas de configurer les tests et le workflow GitHub Actions pour vous assurer que tout fonctionne correctement.