Fermer

novembre 16, 2020

Création d'un flux de travail de test d'intégration continue à l'aide d'actions GitHub


À propos de l'auteur

Fiyinfoluwa Akinsiku est un développeur backend issu d'un milieu microbiologique. Elle est continuellement étonnée des nombreuses façons dont la technologie fait la vie…
En savoir plus sur
Fiyinfoluwa

À l'aide de ce didacticiel, vous pouvez apprendre à créer un flux de travail d'intégration continue pour votre API REST Node JS à l'aide d'actions GitHub, ainsi qu'à signaler la couverture de test avec des combinaisons.

En contribuant aux projets sur des plates-formes de contrôle de version comme GitHub et Bitbucket, la convention est qu'il existe la branche principale contenant la base de code fonctionnelle. Ensuite, il existe d'autres branches dans lesquelles plusieurs développeurs peuvent travailler sur des copies du main pour soit ajouter une nouvelle fonctionnalité, corriger un bogue, etc. Cela a beaucoup de sens car il devient plus facile de surveiller le type d'effet que les modifications entrantes auront sur le code existant. S'il y a une erreur, elle peut facilement être tracée et corrigée avant d'intégrer les modifications dans la branche principale. Il peut être long de parcourir chaque ligne de code manuellement à la recherche d'erreurs ou de bogues, même pour un petit projet. C'est là que l'intégration continue entre en jeu.

Qu'est-ce que l'intégration continue (CI)?

«L'intégration continue (CI) consiste à automatiser l'intégration des changements de code de plusieurs contributeurs dans un seul projet logiciel.»

– Atlassian.com

L'idée générale derrière l'intégration continue (CI) est de s'assurer que les modifications apportées au projet ne «cassent pas la construction», c'est-à-dire ruinent la base de code existante. La mise en œuvre d'une intégration continue dans votre projet, en fonction de la façon dont vous configurez votre flux de travail, créerait une compilation chaque fois que quelqu'un apporterait des modifications au référentiel.

Alors, qu'est-ce qu'une construction?

Une compilation – dans ce contexte – est le compilation du code source dans un format exécutable. Si cela réussit, cela signifie que les modifications entrantes n'auront pas d'impact négatif sur la base de code et qu'elles sont prêtes à fonctionner. Cependant, si la génération échoue, les modifications devront être réévaluées. C'est pourquoi il est conseillé d'apporter des modifications à un projet en travaillant sur une copie du projet sur une branche différente avant de l'incorporer dans la base de code principale. De cette façon, si la construction échoue, il sera plus facile de déterminer d'où vient l'erreur, et cela n'affecte pas non plus votre code source principal.

«Plus vous détectez les défauts tôt, moins ils sont à réparer. »

– David Farley, Livraison continue: des versions logicielles fiables grâce à l'automatisation de la construction, des tests et du déploiement

Plusieurs outils sont disponibles pour vous aider à créer une intégration continue pour votre projet. Il s'agit notamment de Jenkins, TravisCI, CircleCI, GitLab CI, GitHub Actions, etc. Pour ce didacticiel, je vais utiliser les actions GitHub.

Actions GitHub pour une intégration continue

Actions CI est une fonctionnalité relativement nouvelle sur GitHub et permet la création de workflows qui exécutent automatiquement la génération et les tests de votre projet. Un flux de travail contient un ou plusieurs travaux qui peuvent être activés lorsqu'un événement se produit. Cet événement peut être une poussée vers l'une des branches du dépôt ou la création d'une pull request. J'expliquerai ces termes en détail au fur et à mesure.

Commençons!

Prérequis

Ceci est un tutoriel pour les débutants donc je parlerai surtout de GitHub Actions CI au niveau de la surface. Les lecteurs doivent déjà être familiarisés avec la création d'une API REST Node JS à l'aide de la base de données PostgreSQL, Sequelize ORM et l'écriture de tests avec Mocha et Chai.

Vous devriez également avoir les éléments suivants installés sur votre machine:

  • NodeJS,
  • PostgreSQL,
  • NPM,
  • VSCode (ou tout éditeur et terminal de votre choix).

Je vais utiliser une API REST que j'ai déjà créée appelée countries-info-api . Il s'agit d'une simple API sans autorisations basées sur les rôles (comme au moment de la rédaction de ce didacticiel). Cela signifie que n'importe qui peut ajouter, supprimer et / ou mettre à jour les détails d'un pays. Chaque pays aura un identifiant (UUID généré automatiquement), un nom, une capitale et une population. Pour ce faire, j'ai utilisé Node js, le framework express js et Postgresql pour la base de données.

J'expliquerai brièvement comment j'ai configuré le serveur, la base de données avant de commencer par écrire les tests de couverture de test et le fichier de workflow pour une intégration continue.

Vous pouvez cloner le référentiel countries-info-api pour suivre ou créer votre propre API.

Technologie utilisée : Node Js, NPM (un gestionnaire de paquets pour Javascript), base de données Postgresql, sequelize ORM, Babel.

Configuration du serveur

Avant de configurer le serveur, j'ai installé quelques dépendances de npm.

 npm install express dotenv cors

npm install --save-dev @ babel / core @ babel / cli @ babel / preset-env nodemon

J'utilise le framework express et j'écris au format ES6, donc j'aurai besoin de Babeljs pour compiler mon code. Vous pouvez lire la documentation officielle pour en savoir plus sur son fonctionnement et comment le configurer pour votre projet. Nodemon détectera toutes les modifications apportées au code et redémarrera automatiquement le serveur.

Remarque : Les packages Npm installés à l'aide de l'indicateur - save-dev ne sont requis que pendant les étapes de développement et sont visibles sous devDependencies dans le fichier package.json .

J'ai ajouté ce qui suit à mon fichier index.js :

 import express from "Express";
importer bodyParser depuis "body-parser";
importer des cors de "cors";
import "dotenv / config";

const app = express ();
port const = process.env.PORT;

app.use (bodyParser.json ());

app.use (bodyParser.urlencoded ({extended: true}));

app.use (cors ());

app.get ("/", (req, res) => {
    res.send ({message: "Bienvenue sur la page d'accueil!"})
})

app.listen (port, () => {
    console.log (`Le serveur fonctionne sur $ {port} ...`)
})

Ceci configure notre API pour qu'elle s'exécute sur tout ce qui est assigné à la variable PORT dans le fichier .env . C'est également là que nous déclarerons des variables auxquelles nous ne voulons pas que les autres aient facilement accès. Le package dotenv npm charge nos variables d'environnement depuis .env .

Maintenant, lorsque j'exécute npm run start dans mon terminal, j'obtiens ceci:

 ] Serveur en cours d'exécution
Serveur opérationnel sur le port 3000. ( Grand aperçu )

Comme vous pouvez le voir, notre serveur est opérationnel. Yay!

Ce lien http://127.0.0.1:your_port_number/ dans votre navigateur Web devrait renvoyer le message de bienvenue. Autrement dit, tant que le serveur fonctionne.

 Navigateur
Page d'accueil. ( Grand aperçu )
Ensuite, base de données et modèles.

J'ai créé le modèle de pays en utilisant Sequelize et je me suis connecté à ma base de données Postgres. Sequelize est un ORM pour Nodejs. Un avantage majeur est que cela nous fait gagner le temps d'écrire des requêtes SQL brutes.

Puisque nous utilisons Postgresql, la base de données peut être créée via la ligne de commande psql en utilisant la commande CREATE DATABASE nom_base_de_données . Cela peut également être fait sur votre terminal, mais je préfère PSQL Shell.

Dans le fichier env, nous allons configurer la chaîne de connexion de notre base de données, en suivant ce format ci-dessous.

 TEST_DATABASE_URL = postgres: // :  @ 127.0.0.1: 5432 / 

Pour mon modèle, j'ai suivi ce tutoriel de séquelle . Il est facile à suivre et explique tout sur la configuration de Sequelize.

Ensuite, j'écrirai des tests pour le modèle que je viens de créer et je configurerai la couverture sur Coverall.

Écriture de tests et rapport de couverture

Pourquoi écrire des tests ? Personnellement, je pense que la rédaction de tests vous aide en tant que développeur à mieux comprendre comment votre logiciel est censé fonctionner entre les mains de votre utilisateur car il s'agit d'un processus de brainstorming. Il vous aide également à découvrir les bogues à temps.

Tests:

Il existe différentes méthodes de test de logiciels, cependant, Pour ce tutoriel, j'ai utilisé des tests unitaires et de bout en bout . [19659018] J'ai écrit mes tests en utilisant le framework de test Mocha et la bibliothèque d'assertions Chai. J'ai également installé sequelize-test-helpers pour aider tester le modèle que j'ai créé en utilisant sequelize.define .

Couverture du test:

Il est conseillé pour vérifier votre couverture de test parce que le résultat montre si nos cas de test couvrent réellement le code et aussi combien de code est utilisé lorsque nous exécutons nos cas de test.

J'ai utilisé Istanbul (un outil de couverture de test) , nyc (client CLI d'Instabul) et Combinaisons.

Selon la documentation, Istanbul instrumente votre code JavaScript ES5 et ES2015 + avec des compteurs de ligne, afin que vous puissiez suivre dans quelle mesure vos tests unitaires exercent votre base de code.

Dans mon fichier package.json le script de test exécute les tests et génère un rapport.

 {
    "scripts": {
        "test": "nyc --reporter = lcov --reporter = text mocha -r @ babel / register ./src/test/index.js"
    }
}

Dans le processus, il créera un dossier .nyc_output contenant les informations brutes de couverture et un dossier de couverture contenant les fichiers de rapport de couverture. Les deux fichiers ne sont pas nécessaires sur mon dépôt, je les ai donc placés dans le fichier .gitignore .

Maintenant que nous avons généré un rapport, nous devons l'envoyer à Coveralls. Une chose intéressante à propos de Combinaisons (et d'autres outils de couverture, je suppose) est la façon dont elle rapporte votre couverture de test. La couverture est décomposée fichier par fichier et vous pouvez voir la couverture pertinente, les lignes couvertes et manquées, ainsi que ce qui a changé dans la couverture de construction.

Pour commencer, installez le paquet combinaison npm. Vous devez également vous connecter à une combinaison et y ajouter le repo.

 coveralls repo
Repo connecté à Coveralls. ( Grand aperçu )

Ensuite, configurez des combinaisons pour votre projet javascript en créant un fichier coveralls.yml dans votre répertoire racine. Ce fichier contiendra votre repo-token obtenu de la section settings pour votre repo sur les combinaisons.

Un autre script nécessaire dans le fichier package.json est les scripts de couverture. Ce script sera utile lorsque nous créerons une compilation via Actions.

 {
    "scripts": {
        "coverage": "nyc npm run test && nyc report --reporter = text-lcov --reporter = lcov | node ./node_modules/coveralls/bin/coveralls.js --verbose"
    }
}

Fondamentalement, il exécutera les tests, obtiendra le rapport et l'envoyera aux combinaisons pour analyse.

Passons maintenant au point principal de ce didacticiel.

Créer un fichier de flux de travail JS de nœud

À ce stade, nous avons configuré les tâches nécessaires que nous exécuterons dans notre action GitHub. (Vous vous demandez ce que signifie «travaux»? Continuez à lire.)

GitHub a facilité la création du fichier de flux de travail en fournissant un modèle de démarrage. Comme indiqué sur la page Actions, il existe plusieurs modèles de flux de travail ayant des objectifs différents. Pour ce tutoriel, nous utiliserons le workflow Node.js (que GitHub a déjà gentiment suggéré).

 Page Actions
Page Actions GitHub. ( Grand aperçu )

Vous pouvez éditer le fichier directement sur GitHub mais je vais créer manuellement le fichier sur mon dépôt local. Le dossier .github / workflows contenant le fichier node.js.yml sera dans le répertoire racine.

Ce fichier contient déjà quelques commandes de base et le premier commentaire explique ce qu'elles do.

 # Ce flux de travail effectuera une installation propre des dépendances de nœud, construira le code source et exécutera des tests sur différentes versions de nœud

Je vais y apporter quelques modifications afin qu'en plus du commentaire ci-dessus, il exécute également la couverture.

Mon .node.js.yml fichier: [19659034] nom: NodeJS CI
sur: [« push »]
emplois:
construire:
nom: Build
run-on: windows-dernier
stratégie:
matrice:
version du nœud: [12.x, 14.x]

pas:
– utilise: actions / checkout @ v2
– nom: utilisez Node.js $ {{matrix.node-version}}
utilise: actions / setup-node @ v1
avec:
version du nœud: $ {{matrix.node-version}}
– exécuter: npm install
– run: npm run build – si présent
– course: couverture de course npm

– nom: Salopette
utilise: coverallsapp / github-action @ master
env:
COVERALLS_REPO_TOKEN: $ {{secrets.COVERALLS_REPO_TOKEN}}
COVERALLS_GIT_BRANCH: $ {{github.ref}}
avec:
jeton github: $ {{secrets.GITHUB_TOKEN}}

Qu'est-ce que cela signifie?

Décomposons-le.

  • name
    Ce serait le nom de votre workflow (NodeJS CI) ou job (build) et GitHub l'affichera sur la page des actions de votre référentiel.
  • sur
    C'est l'événement qui déclenche le workflow. Cette ligne de mon fichier indique essentiellement à GitHub de déclencher le flux de travail chaque fois qu'une transmission est effectuée dans mon dépôt.
  • jobs
    Un workflow peut contenir au moins un ou plusieurs jobs et chaque job s'exécute dans un environnement spécifié par rodage . Dans l'exemple de fichier ci-dessus, il n'y a qu'un seul travail qui exécute la génération et exécute également la couverture, et il s'exécute dans un environnement Windows. Je peux également le séparer en deux emplois différents comme celui-ci:

Fichier Node.yml mis à jour

 nom: NodeJS CI
sur: [push]
emplois:
  construire:
    nom: Build
    run-on: windows-dernier
    stratégie:
      matrice:
        version du nœud: [12.x, 14.x]
          
    pas:
    - utilise: actions / checkout @ v2
    - nom: utilisez Node.js $ {{matrix.node-version}}
      utilise: actions / setup-node @ v1
      avec:
        version du nœud: $ {{matrix.node-version}}
    - exécuter: npm install
    - run: npm run build - si présent
    - exécuter: test d'exécution npm

  couverture:
    nom: Combinaison
    run-on: windows-dernier
    stratégie:
      matrice:
        version du nœud: [12.x, 14.x]
          
    pas:
    - utilise: coverallsapp / github-action @ master
      env:
        COVERALLS_REPO_TOKEN: $ {{secrets.COVERALLS_REPO_TOKEN}}
      avec:
        jeton github: $ {{secrets.GITHUB_TOKEN}}
  • env
    Il contient les variables d'environnement qui sont disponibles pour tous les travaux ou étapes spécifiques du workflow. Dans la tâche de couverture, vous pouvez voir que les variables d'environnement ont été «masquées». Ils peuvent être trouvés dans la page des secrets de votre dépôt sous les paramètres.
  • étapes
    Il s'agit essentiellement d'une liste des étapes à suivre lors de l'exécution de cette tâche.
  • Le build job fait un certain nombre de choses:
    • Il utilise une action d'extraction (v2 signifie la version) qui extrait littéralement votre référentiel afin qu'il soit accessible par votre flux de travail;
    • Il utilise une action setup-node qui configure l'environnement de nœud à utiliser;
    • Il exécute les scripts d'installation, de construction et de test trouvés dans notre fichier package.json.
  • coverage
    Ceci utilise une action de combinaison qui publie les données de couverture LCOV de votre suite de tests sur coveralls.io pour analyse.
 jobs réussis
Tous les jobs s'exécutent avec succès. ( Grand aperçu )

J'ai d'abord poussé ma branche feat-add-controllers-and-route et j'ai oublié d'ajouter le repo_token de Coveralls à mon . coveralls.yml j'ai donc obtenu l'erreur que vous pouvez voir à la ligne 132.

 Échec de la construction
Échec du travail en raison d'une erreur dans le fichier de configuration des combinaisons. ( Grand aperçu )
 Mauvaise réponse: 422 {"message": "Impossible de trouver un dépôt correspondant à cette tâche.", "Error": true}

Une fois que j'ai ajouté le repo_token ma compilation a pu s'exécuter avec succès. Sans ce jeton, les combinaisons ne seraient pas en mesure de rapporter correctement mon analyse de couverture de test. Heureusement, notre CI Actions GitHub a signalé l'erreur avant qu'elle ne soit poussée vers la branche principale.

 Construction réussie
Erreur corrigée, travail réussi. Yay! ( Grand aperçu )

N.B: Celles-ci ont été prises avant que je sépare le travail en deux emplois. De plus, j'ai pu voir le résumé de la couverture et le message d'erreur sur mon terminal parce que j'ai ajouté l'indicateur - verbeux à la fin de mon script de couverture

Conclusion

Nous pouvons voir comment pour mettre en place une intégration continue de nos projets et intégrer également la couverture de test à l'aide des Actions mises à disposition par GitHub. Il existe de nombreuses autres façons de l'ajuster pour répondre aux besoins de votre projet. Bien que l'exemple de dépôt utilisé dans ce didacticiel soit un projet vraiment mineur, vous pouvez voir à quel point l'intégration continue est essentielle, même dans un projet plus important. Maintenant que mes travaux se sont déroulés avec succès, je suis convaincu de fusionner la succursale avec ma succursale principale. Je vous conseillerais toujours de lire également les résultats des étapes après chaque exécution pour voir que c'est complètement réussi.

 Smashing Editorial (ra, yk, il)




Source link