Intégration continue avec GitLab

Dans la continuité de ce qu’on a fait précédemment en se créant des tests unitaires et des tests end to end, on va maintenant plugger tout ça (et un peu plus) à un pipeline Gitlab afin de :

  • Lancer nos tests unitaires directement après un push
  • Builder notre application et la balancer sur un FTP
  • Jouer avec les variables d’environnement afin de choisir sur quel FTP on veut envoyer notre build (dev / prod)
  • Lancer nos tests end to end pour s’assurer qu’on a pas pété notre UI

Let’s go !

L’application

J’ai retouché rapidement notre précédente App en ajoutant un coup de Bootstrap et en fixant les tests unitaires.

Vous pouvez clone tout ça ici :

https://gitlab.com/Daibai/demo-gitlab-ci/

Configurer un pipeline pour Gitlab

Pour lancer un pipeline, il suffit de créer un fichier Yaml à la racine de votre projet et d’y décrire ce que vous voulez. Il existe des templates tout faits, mais voici ce que donne le mien :

image: node:latest

cache:
 paths:
 - node_modules/

before_script:
 - yarn install

all_tests:
 script:
 - yarn test
 - npm run build

Attention, le fichier étant un yml, l’indentation est importante (des espaces, pas de tabulations).

On :

  • Défini une image, ici node:latest
  • On met notre dossier node_modules en cache
  • Avant l’exécution de nos scripts, on fait l’installation de nos dépendances
  • On balance ensuite nos tests unitaires
  • On créé une build

WARNING

Dans la suite de cette démo, on va déployer dans un sous dossier sur mon ftp. On a donc besoin de modifier un chouya la config de build afin que le chemin relatif de nos assets soit correct.

Autant le faire maintenant.

On déploiera dans le sous dossier enzymedemo, on va donc définir, dans package.json :

 "homepage": "http://www.babonaux.com/enzymedemo",

Pour s’assurer que tout est prêt, allez dans votre repo sur Gitlab, puis Settings puis Pipelines. Ici, on va utiliser les Shared Runners. C’est gratuit, pas trop long en terme de queue, et ca fera l’affaire pour notre démo.

Dans le cas de react-scripts, qui exécutent nos scripts de test et de build, on a besoin d’ajouter une variable d’environnement CI à true qui indiquera au pipeline de sortir du mode interactif après les tests unitaires :

A noter que la plupart des serveurs d’intégration continue définissent déjà cette variable d’environnement.

Il suffit ensuite d’un push pour lancer le pipeline, ce qui lancera automatiquement un job et vous avertira par mail de son résultat. Une console est également accessible sur GitLab pour identifier ce qui a coincé en cas de fail.

Ca casse !

 

Après avoir fixé nos deux petits warning (un composant non utilisé, et une erreur de syntaxe lors du map des todos), ca va tout de suite mieux.

La suite

On vient de mettre en place une première version de notre intégration continue qui :

  • Check les tests unitaires
  • Build notre application

Maintenant qu’on a une build, on devrait envisager de la tester fonctionnellement parlant. On va reprendre notre exemple de tests end 2 end avec Nightwatch et Browserstack, mais avant ça, il faut un environnement pour les tests.

On a faire simple et balancer le contenu de notre build sur un FTP. Ca va nous permettre de :

  • Définir des variables d’environnement depuis GitLab
  • Balancer notre code sur notre (enfin, mon…) FTP
  • Le tester
  • S’assurer que les tests sont ok…
  • … et éventuellement déployer en prod

Il y a plein de façons de procéder, et comme on est un peu feignasse, on va utiliser la façon la plus simple avec lftp. Dans notre config gitlab, on a maintenant :

image: node:latest

cache:
 paths:
 - node_modules/

before_script:
 - yarn install

all_tests:
 script:
 - yarn test
 - npm run build
 - apt-get update
 - apt-get install -y lftp
 - lftp -c "set ftp:ssl-allow no; open -u $FTP_USERNAME,$FTP_PASSWORD babonaux.com; mirror -R build www/enzymedemo"

On commence par faire un update d’apt-get, on install lftp puis on balance l’upload.

Quelques mots sur notre ligne de commande lftp

La doc de lftp est assez bien foutue, je ne reviens pas sur la commande en elle même. Pensez quand même à adapter la config FTP selon la votre.

Vous aurez remarqué qu’on passe deux variables, $FTP_USERNAME et $FTP_PASSWORD. Il s’agit de variables à créer sur votre pipeline Gitlab :

Pensez à passer le protected à Yes.

Une fois qu’on a fait tout ça, un push sur Gitlab va relancer le bouzin :

Un petit tour sur http://www.babonaux.com/enzymedemo/ et…

Shazam !

On avance !

Test end 2 end rapide

Maintenant qu’on a une url a tester, il ne nous reste plus qu’à balancer un bon gros nightwatch des familles.

Reprenez mon précédent post à ce sujet :

Nightwatch et BrowserStack : Aimez vos tests End to End

On va apporter une petite modification à notre test (demo.test.js) :

module.exports = {
 "Test démo" : function (browser) {
 browser
 .url("http://www.babonaux.com/enzymedemo")
 .waitForElementVisible('body', 2000)
 .expect.element('#root').to.be.present;
 browser.end();
 }
};

On lance localement la commande :

nightwatch -c nightwatch.browserstack.js -e chrome,firefox,ie

Un petit tour sur Browserstack pour vérifier que tout est ok :

On n’a plus qu’à automatiser tout ça avec GitLab. On créé deux nouvelles variables d’environnement (protected) :

BROWSERSTACK_USER : votre username browsertack
BROWSERSTACK_KEY : votre clé browserstack

Dans notre fichier de configuration nightwatch.browserstack.js, on va adapter :

nightwatch_config = {
 "src_folders" : ["nw/tests/"],
 "selenium" : {
 "start_process" : false,
 "host" : "hub.browserstack.com",
 "port" : 80
 },
 "common_capabilities": {
 "browserstack.user": process.env.BROWSERSTACK_USER,
 "browserstack.key": process.env.BROWSERSTACK_KEY,
 },

"test_settings": {
 "default": {},
 "chrome": {
 "desiredCapabilities": {
 "browser": "chrome"
 }
 },
 "firefox": {
 "desiredCapabilities": {
 "browser": "firefox"
 }
 },
 "ie": {
 "desiredCapabilities": {
 "browser": "internet explorer"
 }
 }
 }
}

// Code to support common capabilites
for(var i in nightwatch_config.test_settings){
 var config = nightwatch_config.test_settings[i];
 config['selenium_host'] = nightwatch_config.selenium.host;
 config['selenium_port'] = nightwatch_config.selenium.port;
 config['desiredCapabilities'] = config['desiredCapabilities'] || {};
 for(var j in nightwatch_config.common_capabilities){
 config['desiredCapabilities'][j] = config['desiredCapabilities'][j] || nightwatch_config.common_capabilities[j];
 }
}

module.exports = nightwatch_config;

Notez ici qu’on utilise les variables d’environnement pour les credentials Browserstack qu’on a défini dans les variables GitLab.

On va également adapter notre config gitlab :

image: node:latest

cache:
 paths:
 - node_modules/

before_script:
 - yarn install
 - npm install -g nightwatch

all_tests:
 script:
 - yarn test
 - npm run build
 - apt-get update
 - apt-get install -y lftp
 - lftp -c "set ftp:ssl-allow no; open -u $FTP_USERNAME,$FTP_PASSWORD babonaux.com; mirror -R build www/enzymedemo"
 - nightwatch -c nightwatch.browserstack.js -e chrome,firefox,ie

 

Et…

SHAZAM !

En deux mots

On vient de le voir, c’est assez simple de se construire un environnement d’intégration continue. Dans la logique on devrait créer différents environnements pour dev, staging, prod, et bien entendu aller plus loin dans les tests e2e, mais les bases sont là, à vous de les faire évoluer en fonction de votre projet.

 

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *