Passer au contenu

Intégration CI/CD

L’intégration CI/CD est disponible pour les utilisateurs avec le plan Enterprise.

Vous pouvez regarder cette vidéo pour comprendre pourquoi et comment l’intégration CI/CD peut vous aider :

Graphiques de publication

Commençons par configurer le fichier de démarrage de l’application (main.ts) pour utiliser la classe GraphPublisher (exportée depuis @nestjs/devtools-integration - voir le chapitre précédent pour plus de détails), comme suit :

Configuration de GraphPublisher
async function bootstrap() {
const shouldPublishGraph = process.env.PUBLISH_GRAPH === "true";
const app = await NestFactory.create(AppModule, {
snapshot: true,
preview: shouldPublishGraph,
});
if (shouldPublishGraph) {
await app.init();
const publishOptions = { ... }; // NOTE: cet objet d'options variera en fonction du fournisseur CI/CD que vous utilisez
const graphPublisher = new GraphPublisher(app);
await graphPublisher.publish(publishOptions);
await app.close();
} else {
await app.listen(3000);
}
}

Comme nous pouvons le voir, nous utilisons ici la GraphPublisher pour publier notre graphique sérialisé dans le registre centralisé. La variable d’environnement PUBLISH_GRAPH nous permettra de contrôler si le graphique doit être publié (flux de travail CI/CD) ou non (démarrage d’application régulier). De plus, nous définissons l’attribut preview ici sur true. Avec ce drapeau activé, notre application démarre en mode aperçu - ce qui signifie que les constructeurs (et les hooks de cycle de vie) de tous les contrôleurs, des renforceurs et des fournisseurs de notre application ne seront pas exécutés. Notez que ce n’est pas nécessaire, mais cela simplifie les choses pour nous, puisque dans ce cas, nous n’avons pas vraiment à nous connecter à la base de données, etc., lorsque nous exécutons notre application dans le pipeline CI/CD.

L’objet publishOptions variera en fonction du fournisseur CI/CD que vous utilisez. Nous vous fournirons des instructions pour les fournisseurs CI/CD les plus populaires ci-dessous, dans les sections suivantes.

Une fois que le graphique est publié avec succès, vous verrez la sortie suivante dans votre vue de flux de travail :

Graphique publié dans le terminal

Chaque fois que notre graphique est publié, nous devrions voir une nouvelle entrée dans la page correspondante du projet :

Projet

Rapports

Les Devtools génèrent un rapport pour chaque build SI un instantané correspondant est déjà stocké dans le registre centralisé. Par exemple, si vous créez une PR contre la branche master pour laquelle le graphique a déjà été publié - alors l’application sera en mesure de détecter les différences et de générer un rapport. Sinon, le rapport ne sera pas généré.

Pour voir les rapports, naviguez vers la page correspondante du projet (voir organisations).

Rapport

C’est particulièrement utile pour identifier les changements qui ont pu passer inaperçus lors des revues de code. Par exemple, disons que quelqu’un a changé la portée d’un fournisseur profondément imbriqué. Ce changement pourrait ne pas être immédiatement évident pour le réviseur, mais avec les Devtools, nous pouvons facilement repérer de tels changements et nous assurer qu’ils sont intentionnels. Ou si nous supprimons une garde d’un point de terminaison spécifique, cela apparaîtra comme affecté dans le rapport. Maintenant, si nous n’avions pas d’intégration ou de tests e2e pour cette route, nous pourrions ne pas remarquer qu’elle n’est plus protégée, et au moment où nous le ferons, il pourrait être trop tard.

De même, si nous travaillons sur un grand code et que nous modifions un module pour qu’il soit global, nous verrons combien de liens ont été ajoutés au graphique, et cela - dans la plupart des cas - est un signe que nous faisons quelque chose de mal.

Prévisualisation de la construction

Pour chaque graphique publié, nous pouvons revenir en arrière dans le temps et prévisualiser à quoi il ressemblait auparavant en cliquant sur le bouton Preview. De plus, si le rapport a été généré, nous devrions voir les différences mises en évidence sur notre graphique :

  • les nœuds verts représentent des éléments ajoutés
  • les nœuds blancs clairs représentent des éléments mis à jour
  • les nœuds rouges représentent des éléments supprimés

Voir la capture d’écran ci-dessous :

Sélection de nœuds

La capacité de revenir dans le temps vous permet d’enquêter et de dépanner le problème en comparant le graphique actuel avec le précédent. Selon la façon dont vous avez configuré les choses, chaque pull request (ou même chaque commit) aura un instantané correspondant dans le registre, donc vous pouvez facilement revenir en arrière et voir ce qui a changé. Pensez aux Devtools comme à un Git, mais avec une compréhension de comment Nest construit votre graphique d’application, et avec la capacité de visualiser cela.

Intégrations : GitHub Actions

Commençons par créer un nouveau flux de travail GitHub dans le répertoire .github/workflows de notre projet et l’appelons, par exemple, publish-graph.yml. À l’intérieur de ce fichier, utilisons la définition suivante :

Définition du flux de travail GitHub
name: Devtools
on:
push:
branches:
- master
pull_request:
branches:
- '*'
jobs:
publish:
if: github.actor != 'dependabot[bot]'
name: Publier le graphique
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
node-version: '16'
cache: 'npm'
- name: Installer les dépendances
run: npm ci
- name: Configurer l'environnement (PR)
if: ${{ github.event_name == 'pull_request' }}
shell: bash
run: |
echo "COMMIT_SHA=${{ github.event.pull_request.head.sha }}" >> ${{ github.env }}
- name: Configurer l'environnement (Push)
if: ${{ github.event_name == 'push' }}
shell: bash
run: |
echo "COMMIT_SHA=${GITHUB_SHA}" >> ${{ github.env }}
- name: Publier
run: PUBLISH_GRAPH=true npm run start
env:
DEVTOOLS_API_KEY: CHANGE_THIS_TO_YOUR_API_KEY
REPOSITORY_NAME: ${{ github.event.repository.name }}
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
TARGET_SHA: ${{ github.event.pull_request.base.sha }}

Idéalement, la variable d’environnement DEVTOOLS_API_KEY devrait être récupérée depuis les Secrets GitHub, lisez-en plus ici.

Ce flux de travail s’exécutera pour chaque pull request ciblant la branche master OU en cas de commit direct sur la branche master. N’hésitez pas à ajuster cette configuration selon les besoins de votre projet. Ce qui est essentiel ici, c’est que nous fournissons les variables d’environnement nécessaires pour notre classe GraphPublisher (pour qu’elle fonctionne).

Cependant, une variable doit être mise à jour avant que nous puissions commencer à utiliser ce flux de travail - DEVTOOLS_API_KEY. Nous pouvons générer une clé API dédiée pour notre projet sur cette page.

Enfin, retournons dans le fichier main.ts et mettons à jour l’objet publishOptions que nous avions précédemment laissé vide.

Mise à jour de publishOptions
const publishOptions = {
apiKey: process.env.DEVTOOLS_API_KEY,
repository: process.env.REPOSITORY_NAME,
owner: process.env.GITHUB_REPOSITORY_OWNER,
sha: process.env.COMMIT_SHA,
target: process.env.TARGET_SHA,
trigger: process.env.GITHUB_BASE_REF ? 'pull' : 'push',
branch: process.env.BRANCH_NAME,
};

Pour la meilleure expérience développeur, assurez-vous d’intégrer l’application GitHub pour votre projet en cliquant sur le bouton “Intégrer l’application GitHub” (voir la capture d’écran ci-dessous). Notez que ce n’est pas nécessaire.

Intégration de l'application GitHub

Avec cette intégration, vous pourrez voir le statut du processus de génération d’aperçu/rapport directement dans votre pull request :

Aperçu des actions

Intégrations : Gitlab Pipelines

Commençons par créer un nouveau fichier de configuration CI Gitlab dans le répertoire racine de notre projet et l’appelons, par exemple, .gitlab-ci.yml. À l’intérieur de ce fichier, utilisons la définition suivante :

Configuration de Gitlab CI
image: node:16
stages:
- build
cache:
key:
files:
- package-lock.json
paths:
- node_modules/
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: always
- if: $CI_COMMIT_BRANCH == "master" && $CI_PIPELINE_SOURCE == "push"
when: always
- when: never
install_dependencies:
stage: build
script:
- npm ci
publish_graph:
stage: build
needs:
- install_dependencies
script: npm run start
variables:
PUBLISH_GRAPH: 'true'
DEVTOOLS_API_KEY: 'CHANGE_THIS_TO_YOUR_API_KEY'

Ce flux de travail s’exécutera pour chaque pull request ciblant la branche master OU en cas de commit direct sur la branche master. N’hésitez pas à ajuster cette configuration selon les besoins de votre projet. Ce qui est essentiel ici, c’est que nous fournissons les variables d’environnement nécessaires pour notre classe GraphPublisher (pour qu’elle fonctionne).

Cependant, il y a une variable (dans cette définition de flux de travail) qui doit être mise à jour avant que nous puissions commencer à utiliser ce flux de travail - DEVTOOLS_API_KEY. Nous pouvons générer une clé API dédiée pour notre projet sur cette page.

Enfin, retournons dans le fichier main.ts et mettons à jour l’objet publishOptions que nous avions précédemment laissé vide.

Configuration de publishOptions pour Gitlab
image: node:16
stages:
- build
cache:
key:
files:
- package-lock.json
paths:
- node_modules/
workflow:
rules:
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
when: always
- if: $CI_COMMIT_BRANCH == "master" && $CI_PIPELINE_SOURCE == "push"
when: always
- when: never
install_dependencies:
stage: build
script:
- npm ci
publish_graph:
stage: build
needs:
- install_dependencies
script: npm run start
variables:
PUBLISH_GRAPH: 'true'
DEVTOOLS_API_KEY: 'CHANGE_THIS_TO_YOUR_API_KEY'

Autres outils CI/CD

L’intégration CI/CD des outils Dev peut être utilisée avec n’importe quel outil CI/CD de votre choix (par exemple, Bitbucket Pipelines, CircleCI, etc.), donc ne vous sentez pas limité aux fournisseurs que nous avons décrits ici.

Regardez la configuration de l’objet publishOptions ci-dessous pour comprendre quelles informations sont requises pour publier le graphique pour un commit/build/PR donné.

Configuration de publishOptions pour d'autres outils CI/CD
const publishOptions = {
apiKey: process.env.DEVTOOLS_API_KEY,
repository: process.env.CI_PROJECT_NAME,
owner: process.env.CI_PROJECT_ROOT_NAMESPACE,
sha: process.env.CI_COMMIT_SHA,
target: process.env.CI_MERGE_REQUEST_DIFF_BASE_SHA,
trigger: process.env.CI_MERGE_REQUEST_DIFF_BASE_SHA ? 'pull' : 'push',
branch: process.env.CI_COMMIT_BRANCH ?? process.env.CI_MERGE_REQUEST_SOURCE_BRANCH_NAME,
};

La plupart de ces informations sont fournies par les variables d’environnement intégrées dans CI/CD (voir liste des environnements intégrés de CircleCI et variables de Bitbucket).

En ce qui concerne la configuration du pipeline pour publier des graphiques, nous vous recommandons d’utiliser les déclencheurs suivants :

  • événement push - uniquement si la branche actuelle représente un environnement de déploiement, par exemple master, main, staging, production, etc.
  • événement pull request - toujours, ou lorsque la branche cible représente un environnement de déploiement (voir ci-dessus)