Conseils pour créer des workflows personnalisés dans GitLab CI

Remarque perev. : L'article original a Ă©tĂ© Ă©crit par MiƂosz SmóƂka, l'un des fondateurs de la petite entreprise polonaise Three Dots Labs , spĂ©cialisĂ©e dans les «solutions avancĂ©es de backend». L'auteur s'appuie sur son expĂ©rience dans l'utilisation active de GitLab CI et partage les conseils accumulĂ©s pour les autres utilisateurs de ce produit Open Source. AprĂšs les avoir lus, nous avons rĂ©alisĂ© Ă  quel point les problĂšmes dĂ©crits par lui Ă©taient proches de nous, nous avons donc dĂ©cidĂ© de partager les solutions proposĂ©es avec un public plus large.



Cette fois, je couvrirai des sujets plus avancĂ©s dans GitLab CI. Une tĂąche courante consiste Ă  implĂ©menter des fonctionnalitĂ©s non standard dans le pipeline. La plupart des conseils sont spĂ©cifiques Ă  GitLab, bien que certains d'entre eux puissent ĂȘtre appliquĂ©s Ă  d'autres systĂšmes CI.

Exécutez des tests d'intégration


En rĂšgle gĂ©nĂ©rale, la vĂ©rification du code Ă  l'aide de tests unitaires est facile Ă  connecter Ă  n'importe quel systĂšme CI. Habituellement, cela n'est pas plus compliquĂ© que d'exĂ©cuter l'une des commandes intĂ©grĂ©es Ă  l'ensemble standard d'utilitaires dans un langage de programmation. Dans de tels tests, vous ĂȘtes susceptible d'utiliser divers moki et stubs pour masquer les dĂ©tails d'implĂ©mentation et vous concentrer sur le test d'une logique spĂ©cifique. Par exemple, vous pouvez utiliser la base de donnĂ©es en mĂ©moire comme stockage ou Ă©crire des talons pour les clients HTTP qui renverront toujours des rĂ©ponses dĂ©jĂ  prĂ©parĂ©es.

Cependant, tÎt ou tard, vous aurez besoin de tests d'intégration pour couvrir des situations plus inhabituelles avec des tests. Je n'entrerai pas dans la discussion sur tous les types de tests possibles et je dirai simplement que par intégration, je veux dire les tests qui utilisent une sorte de ressources externes. Il peut s'agir d'un véritable serveur de base de données, d'un service HTTP, d'un stockage connecté, etc.

Dans GitLab, il est facile d'exĂ©cuter des ressources enfichables en tant que conteneurs Docker associĂ©s au conteneur dans lequel les scripts s'exĂ©cutent. Ces dĂ©pendances peuvent ĂȘtre dĂ©finies Ă  l'aide de services . Ils sont disponibles par le nom de l'image ou par le nom de votre choix, si vous le spĂ©cifiez dans le champ alias .

Voici un exemple simple d'utilisation d'un conteneur enfichable avec MySQL:

 integration_tests: stage: tests services: - name: mysql:8 alias: db script: - ./run_tests.sh db:3306 

Dans ce cas, dans les scripts de test, vous devrez vous connecter à l'hÎte db . L'utilisation d'un alias est généralement une bonne idée, car elle vous permet de remplacer des images sans avoir à modifier le code de test. Par exemple, vous pouvez remplacer l'image mysql par mariadb , et le script fonctionnera toujours correctement.

En attente de conteneurs


Étant donnĂ© que les conteneurs de plug-ins prennent du temps Ă  charger, vous devrez peut-ĂȘtre attendre avant d'envoyer des demandes. Un moyen simple est d' attendre le script wait-for-it.sh avec un timeout dĂ©fini.

Utilisation de Docker Compose


Dans la plupart des cas, les services devraient ĂȘtre suffisants. Cependant, une interaction avec des services externes peut parfois ĂȘtre nĂ©cessaire. Par exemple, dans le cas du lancement de Kafka et ZooKeeper dans deux conteneurs distincts (c'est ainsi que les images officielles sont collectĂ©es). Un autre exemple est l'exĂ©cution de tests avec un nombre dynamique de nƓuds, tels que Selenium. La meilleure solution pour exĂ©cuter ces services serait Docker Compose :

 version: '3' services: zookeeper: image: confluentinc/cp-zookeeper environment: ZOOKEEPER_CLIENT_PORT: 2181 kafka: image: confluentinc/cp-kafka environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 ports: - 9092:9092 

Si vous utilisez votre installation avec des exécuteurs GitLab sur des serveurs fiables, vous pouvez exécuter Docker Composer via l' exécuteur Shell . Une autre option possible est le dind Docker in Docker ( dind ). Mais dans ce cas, lisez d'abord cet article .

Une façon d'utiliser Compose est de configurer votre environnement, d'exécuter des tests, puis de tout détruire. Un simple script bash ressemblerait à ceci:

 docker-compose up -d ./run_tests.sh localhost:9092 docker-compose down 

Tant que vous exécutez des tests dans un environnement minimal, tout ira bien. Bien qu'une situation puisse survenir dans laquelle vous devez installer certaines dépendances ... Il existe une autre façon d'exécuter des tests dans Docker Compose - elle vous permet de créer votre propre image Docker avec un environnement de test. Dans l'un des conteneurs, vous exécutez des tests et quittez avec le code retour correspondant:

 version: '3' services: zookeeper: image: confluentinc/cp-zookeeper environment: ZOOKEEPER_CLIENT_PORT: 2181 kafka: image: confluentinc/cp-kafka environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 tests: image: registry.example.com/some-image command: ./run_tests.sh kafka:9092 

Notez que nous avons éliminé la nécessité de mapper les ports. Dans cet exemple, les tests peuvent interagir directement avec tous les services.

Et leur lancement s'effectue par une seule commande:

 docker-compose up --exit-code-from tests 

L' --abort-on-container-exit --exit-code-from implique --abort-on-container-exit , ce qui signifie: tout l'environnement initiĂ© par docker-compose up sera arrĂȘtĂ© aprĂšs la fin de l'un des conteneurs. Le code d'achĂšvement de cette commande sera Ă©quivalent au code de sortie du service sĂ©lectionnĂ© (c'est-Ă -dire qu'il s'agit de tests dans l'exemple ci-dessus). Si la commande qui dĂ©marre les tests se termine avec un code diffĂ©rent de zĂ©ro, la commande docker-compose up entiĂšre se termine avec elle.

Utilisation d'étiquettes comme balises CI


Attention : c'est une idée plutÎt inhabituelle, mais elle m'a paru trÚs utile et flexible.

Comme vous le savez peut-ĂȘtre, GitLab dispose d'une fonctionnalitĂ© d'Ă©tiquettes disponible au niveau du projet et du groupe. Des Ă©tiquettes peuvent ĂȘtre dĂ©finies sur les tickets et les demandes de fusion. Cependant, ils n'ont aucun lien avec les pipelines.



Un petit raffinement vous permettra d'accéder aux libellés de la demande de fusion dans les scripts de jobs. Dans GitLab 11.6, tout est devenu encore plus facile, car la variable d'environnement CI_MERGE_REQUEST_IID est apparue (oui, c'est avec l' IID , pas l' ID ) si le pipeline utilise only: merge_requests .

Si only: merge_requests pas utilisĂ© ou si vous travaillez avec une ancienne version de GitLab, MR peut toujours ĂȘtre obtenu - en utilisant l'appel API:

 curl "$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/commits/$CI_COMMIT_SHA/merge_requests?private_token=$GITLAB_TOKEN" 

Le domaine dont nous avons besoin est iid . Cependant, n'oubliez pas que de nombreux MR peuvent revenir pour un commit donné.

Lorsque le MR IID est reçu, il ne reste plus qu'à se tourner vers l' API Merge Requests et à utiliser le champ des labels de la réponse:

 curl "$CI_API_V4_URL/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID?private_token=$GITLAB_TOKEN" 

Se connecter


Malheureusement, pour le moment, il n'est pas possible d'utiliser $CI_JOB_TOKEN pour accéder à l'API du projet (au moins si le projet n'est pas public). Si le projet a un accÚs limité (interne ou privé), pour l'autorisation dans l'API GitLab, vous devrez générer un jeton d'API personnel.



Cependant, ce n'est pas la solution la plus sûre, alors soyez prudent. Si le jeton tombe entre de mauvaises mains, l'accÚs en écriture à tous vos projets peut apparaßtre avec lui. Une façon de réduire les risques consiste à créer un compte distinct avec le droit de lire le référentiel et de générer un jeton personnel pour ce compte.

Vos variables sont-elles sûres?


Il y a quelques versions, la section Variables s'appelait Variables secrÚtes , ce qui semble avoir été créé pour stocker de maniÚre fiable les informations d'identification et autres informations critiques. En fait, les variables sont simplement cachées aux utilisateurs qui ne disposent pas des privilÚges du responsable. Ils ne sont pas chiffrés sur le disque et leur fuite peut facilement se produire via des variables d'environnement dans les scripts.

Gardez cela à l'esprit lorsque vous ajoutez des variables et envisagez de garder des secrets dans des solutions plus sécurisées (par exemple, Vault de HashiCorp ).

Cas d'utilisation


Que faire des listes d'étiquettes dépend de vous. Voici quelques idées:

  • Utilisez-les pour segmenter les tests.
  • Utilisez la sĂ©mantique des valeurs-clĂ©s avec deux points comme sĂ©parateur (par exemple, des Ă©tiquettes comme tests:auth , tests:user )
  • Inclure certaines fonctionnalitĂ©s pour les travaux.
  • Autorisez le dĂ©bogage de travaux spĂ©cifiques si l'Ă©tiquette existe.

Appel d'API externes


Bien que GitLab soit livrĂ© avec une gamme de fonctionnalitĂ©s dĂ©jĂ  disponibles, il est trĂšs probable que vous souhaitiez utiliser d'autres utilitaires pouvant ĂȘtre intĂ©grĂ©s aux pipelines. La façon la plus simple de l'implĂ©menter est, bien sĂ»r, d'appeler la bonne vieille curl .

Si vous créez vos propres outils, vous pouvez leur apprendre à écouter les Webhooks GitLab (voir l'onglet Intégrations dans les paramÚtres du projet). Cependant, si vous avez l'intention de les utiliser avec des systÚmes critiques, assurez-vous qu'ils répondent aux exigences de haute disponibilité.

Exemple: annotations Grafana


Si vous travaillez avec Grafana , les annotations sont un excellent moyen de marquer des Ă©vĂ©nements qui se sont produits au fil du temps sur des graphiques. Ils peuvent ĂȘtre ajoutĂ©s non seulement manuellement en cliquant dans l'interface graphique, mais Ă©galement en appelant l' API REST Grafana :



Pour accéder à l'API, vous devrez générer une clé API. Envisagez de créer un utilisateur distinct avec un accÚs limité:



Définissez deux variables dans les paramÚtres du projet:

  • GRAFANA_URL - URL de l'installation de Grafana (par exemple, https://grafana.example.com );
  • GRAFANA_APIKEY - clĂ© gĂ©nĂ©rĂ©e pour l'API.

Pour pouvoir le réutiliser, placez le script dans le référentiel avec des scripts communs :

 #!/bin/bash set -e if [ $# -lt 2 ]; then echo "Usage: $0 <text> <tag>" exit 1 fi readonly text="$1" readonly tag="$2" readonly time="$(date +%s)000" cat >./payload.json <<EOF { "text": "$text", "tags": ["$tag"], "time": $time, "timeEnd": $time } EOF curl -X POST "$GRAFANA_URL/api/annotations" \ -H "Authorization: Bearer $GRAFANA_APIKEY" \ -H "content-type: application/json" \ -d @./payload.json 

Vous pouvez maintenant ajouter son appel à la configuration CI avec les paramÚtres nécessaires:

 deploy: stage: deploy script: - $SCRIPTS_DIR/deploy.sh production - $SCRIPTS_DIR/grafana-annotation.sh "$VERSION deployed to production" deploy-production 

Ces appels peuvent ĂȘtre placĂ©s dans le script deploy.sh pour simplifier la configuration CI.

Bonus: conseils rapides


GitLab a une excellente documentation sur tous les mots clĂ©s possibles qui peuvent ĂȘtre utilisĂ©s pour configurer CI. Je ne veux pas dupliquer son contenu ici, mais je soulignerai quelques cas utiles. Cliquez sur les titres pour voir la documentation associĂ©e.

Utilisation avancée de seulement / sauf


En définissant des modÚles pour les variables CI, vous pouvez définir des assemblages personnalisés pour certaines branches. Cela peut aider, par exemple, à identifier les correctifs push pour les correctifs urgents, mais n'en abusez pas:

 only: refs: - branches variables: - $CI_COMMIT_REF_NAME =~ /^hotfix/ 

GitLab a de nombreuses variables prédéfinies dans chaque travail CI - utilisez-les.

Ancres Yaml


Utilisez-les pour éviter les doublons.

À partir de la version 11.3, vous pouvez Ă©galement utiliser le mot clĂ© extend :

 .common_before_script: &common_before_script before_script: - ... - ... deploy: <<: *common_before_script 

Exclusion d'artefacts


Par défaut, tous les artefacts collectés dans le pipeline seront transférés vers tous les travaux suivants. Si vous répertoriez explicitement les artefacts dont dépendent les travaux, vous pouvez économiser du temps et de l'espace disque:

 dependencies: - build 

Ou - au contraire - sautez complĂštement tout si aucun n'est requis:

 dependencies: [] 

Stratégie Git


Ignorer le clonage du référentiel si le travail n'utilise pas ces fichiers:

 variables: GIT_STRATEGY: none 

C’est tout!

Merci d'avoir lu! Pour des commentaires et des questions, contactez-moi sur Twitter ou Reddit .

Plus de conseils GitLab peuvent ĂȘtre trouvĂ©s dans les articles prĂ©cĂ©dents:


PS du traducteur


Lisez aussi dans notre blog:

Source: https://habr.com/ru/post/fr436910/


All Articles