Cet article vous met dans la peau d’un gestionnaire de site d'information. Avec un peu de chance, vous hébergez déjà le code de votre projet sur GitLab.com et exécutez des tests avec GitLab CI/CD. Maintenant, vous souhaitez connaître toutes les possibilités de déploiement pour votre projet.
Par souci de pertinence, supposons que l'application se résume à un ensemble de fichiers HTML, sans code côté serveur ni compilation sophistiquée des actifs JS. La plateforme de destination sera également générique, nous utiliserons Amazon S3.
Plutôt que de saupoudrer l'article d'extraits à copier-coller, nous allons vous partager les principes et les fonctionnalités de GitLab CI, afin que vous puissiez les appliquer dans votre propre pile technologique.
Déroulons donc notre histoire depuis son commencement, où il n'est pas encore question d'intégration continue.
La ligne de départ
Déploiement : un ensemble de fichiers HTML devraient apparaître dans votre bucket S3 (déjà configuré pour héberger un site web statique). Il y a des millions de façons de procéder. Dans notre cas, nous utiliserons la bibliothèque AWS CLI fournie par Amazon.
La commande complète ressemble à ceci :
aws s3 cp ./ s3://yourbucket/ --recursive --exclude "*" --include "*.html"
Le push du code vers le dépôt et le déploiement sont deux processus distincts.
Détail important : la commande nécessite de fournir les variables d'environnement AWS_ACCESS_KEY_ID
et AWS_SECRET_ACCESS_KEY
. Il vous faudra peut-être aussi spécifier AWS_DEFAULT_REGION
.
Essayons d'automatiser cette procédure avec l'intégration continue de GitLab.
Votre premier déploiement automatisé
GitLab CI s'adapte à l'exécution de vos commandes, à la manière d'un terminal local sur votre ordinateur. Vous pouvez le configurer à votre guise, et les commandes seront dupliquées par GitLab CI au sein de la plateforme. Placez votre script dans le fichier .gitlab-ci.yml et effectuez un push de votre code : l’outil d'intégration continue de GitLab déclenche un job et vos commandes sont exécutées.
Précisons maintenant le contexte d'utilisation de cet exemple avec GitLab CI : il s'agit d'un site de taille modeste, avec une trentaine de visiteurs journaliers, et une seule branche principale de dépôt de code. Commençons par spécifier un job avec la commande ci-dessus dans le fichier .gitlab-ci.yml
:
deploy:
script: aws s3 cp ./ s3://yourbucket/ --recursive --exclude "*" --include "*.html"
Oups, pas de chance :
Il fallait d'abord vérifier l'existence d'un exécutable aws
. Pour ce faire, awscli
requiert l'utilisation de pip
, un outil d'installation de paquets Python. Nous définissons une image Docker contenant à la fois Python préinstallé et pip
:
deploy:
image: python:latest
script:
- pip install awscli
- aws s3 cp ./ s3://yourbucket/ --recursive --exclude "*" --include "*.html"
Vous effectuez un push de votre code sur GitLab, et il est automatiquement déployé par l’outil CI.
L'installation d'awscli
rallonge le temps d'exécution du job, mais pour l'instant ce n'est pas un souci. Pour accélérer le processus, recherchez une image Docker avec awscli
préinstallé, ou créez-la vous-même.
De plus, n’oublions pas les variables d'environnement récupérées depuis la console AWS :
variables:
AWS_ACCESS_KEY_ID: "AKIAIOSFODNN7EXAMPLE"
AWS_SECRET_ACCESS_KEY: "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
deploy:
image: python:latest
script:
- pip install awscli
- aws s3 cp ./ s3://yourbucket/ --recursive --exclude "*" --include "*.html"
Cela devrait fonctionner, mais attention : ce n'est jamais une bonne idée de dévoiler des clés secrètes au sein du code, même dans un dépôt privé. Remédions donc à cette situation.
Des secrets bien gardés
GitLab dispose d’un endroit spécialement dédié aux variables secrètes : Paramètres > CI/CD > Variables.
Tout ce que vous y mettez se transforme en variables d'environnement. En cochant la case « Masquée », vous masquerez la variable dans les job logs. En cochant la case « Protéger la variable », vous n’exporterez la variable uniquement vers les pipelines s'exécutant sur des branches et des étiquettes protégées.
Seuls les utilisateurs ayant le statut de propriétaire ou de chargé de maintenance sur un projet pourront accéder à cette section. Nous pourrions supprimer la section variables
de notre configuration CI, mais nous allons l'utiliser à d'autres fins.
Savoir spécifier et utiliser des variables non-secrètes
Lorsque votre configuration s'agrandit, il devient pratique de conserver certains paramètres sous formes de variables au début de votre configuration. Le cas présent ne le justifie pas, mais pour les besoins de cette démonstration, nous allons définir le nom du compartiment S3 comme variable :
variables:
S3_BUCKET_NAME: "yourbucket"
deploy:
image: python:latest
script:
- pip install awscli
- aws s3 cp ./ s3://$S3_BUCKET_NAME/ --recursive --exclude "*" --include "*.html"
Jusqu'ici, tout va bien :
Dans notre scénario virtuel, la fréquentation du site est en hausse, et vous avez embauché un développeur pour vous aider. Voyons comment le workflow GitLab CI s'adapte au travail en équipe.
Comment utiliser GitLab CI en équipe
Avec deux utilisateurs travaillant sur le même dépôt, il n'est plus pratique d'utiliser la branche principale pour le développement. Vous décidez d'utiliser des branches séparées pour les nouvelles fonctionnalités et les nouveaux articles, et de les fusionner dans la branche principale lorsqu'ils sont prêts.
Cependant, votre configuration CI actuelle ne prend pas en charge les branches. Chaque push effectué dans GitLab sera déployé sur S3. La solution est simple : il suffit d'ajouter only: main
au job deploy
.
En plus de ne pas vouloir déployer chaque branche sur l’environnement de production, vous souhaiteriez pouvoir prévisualiser vos modifications depuis les branches de fonctionnalités.
Comment tester le code dans un endroit spécifique ?
Matteo, votre nouveau développeur, vous propose d'utiliser la fonctionnalité GitLab Pages, idéale pour prévisualiser votre travail en cours. Afin d'héberger des sites web sur GitLab Pages, votre fichier de configuration CI doit répondre à trois règles simples :
- Le job doit être nommé
pages
- Une section
artifacts
doit comporter un dossierpublic
- L'ensemble des contenus que vous souhaitez héberger doit être placé dans le dossier
public
Le contenu du dossier public sera hébergé à l'adresse suivante : http://<username>.gitlab.io/<projectname>/
Voici la configuration complète de l’outil CI de GitLab après avoir appliqué l’exemple de configuration pour les sites web en HTML :
variables:
S3_BUCKET_NAME: "yourbucket"
deploy:
image: python:latest
script:
- pip install awscli
- aws s3 cp ./ s3://$S3_BUCKET_NAME/ --recursive --exclude "*" --include "*.html"
only:
- main
pages:
image: alpine:latest
script:
- mkdir -p ./public
- cp ./*.html ./public/
artifacts:
paths:
- public
except:
- main
Nous avons spécifié deux tâches. L'une d'elles déploie le site web à l'intention de vos lecteurs sur S3 (deploy
). L'autre (pages
) déploie le site web sur GitLab Pages. Nommons-les « Environnement de production » et « Environnement de préproduction ». Toutes les branches seront déployées sur GitLab Pages, à l'exception de la branche principale.
Présentation des environnements
GitLab prend en charge de nombreux environnements (dynamiques ou statiques) ; vous devez simplement spécifier l'environnement correspondant pour chaque job de déploiement :
variables:
S3_BUCKET_NAME: "yourbucket"
deploy to production:
environment: production
image: python:latest
script:
- pip install awscli
- aws s3 cp ./ s3://$S3_BUCKET_NAME/ --recursive --exclude "*" --include "*.html"
only:
- main
pages:
image: alpine:latest
environment: staging
script:
- mkdir -p ./public
- cp ./*.html ./public/
artifacts:
paths:
- public
except:
- main
GitLab garde une trace de tous vos déploiements. Ainsi, vous savez toujours ce qui est en cours de déploiement sur vos serveurs :
L'historique complet de vos déploiements sur chacun de vos environnements actuels vous est aussi fourni :
Maintenant que tout est automatisé et configuré, de nouveaux défis nous attendent.
Assurer le dépannage des déploiements
Oups ! La branche de fonctionnalités que vous avez poussé sur l'environnement de préproduction vient d'être remplacée par celle de Matteo, qui vient d'effectuer un push de sa propre branche. L'énervement vous gagne, c'est la troisième fois que cela arrive aujourd'hui ! Et si vous utilisiez Slack pour notifier vos déploiements, afin d'éviter ce genre de désagrément ?
Utiliser Slack pour les déploiements
Mettre en place des notifications Slack est vraiment simple.
Il suffit pour cela de reprendre l'URL du WebHook entrant de Slack…
...et de le mettre dans Paramètres > Intégrations > Notifications Slack avec votre nom d'utilisateur Slack :
Pour ne recevoir que des notifications de déploiement, cochez uniquement « Déploiement » dans les paramètres ci-dessus. C'est fait, vous ne manquerez plus aucun déploiement :
Du travail d'équipe à grande échelle
Quelque temps plus tard, et vous voilà à la tête d'un site web très populaire, et d'une équipe de huit personnes. Mais, désormais, les membres de votre équipe perdent un temps précieux à attendre de pouvoir prévisualiser leur travail. Le déploiement de chaque branche en préproduction n'est plus optimal.
Il est temps de perfectionner le système. Vous convenez avec votre équipe de fusionner au préalable chaque changement sur la branche de préproduction. La modification dans .gitlab-ci.yml
est minime :
except:
- main
est remplacé par
only:
- staging
Vos collaborateurs doivent fusionner leurs branches de fonctionnalités avant de prévisualiser leur travail en préproduction. Cela demande bien sûr plus de temps et d'efforts, mais tout le monde s'accorde à dire que c'est toujours mieux que d'attendre.
Comment gérer les situations d'urgence ?
Il arrive parfois que les choses tournent mal. Quelqu'un a mal fusionné des branches et a effectué un push du résultat directement en production, juste au moment où le hashtag de votre site devenait viral sur les réseaux sociaux. Des milliers de personnes voient des visuels cassés en lieu et place de votre page d'accueil habituelle. Heureusement, la fonction de retour en arrière Actions > Restaurer a permis de résoudre le problème en moins d'une minute.
La fonction de retour en arrière relance la tâche et la validation précédentes. Vous avez néanmoins réagi en désactivant le déploiement automatique en production, et en passant en déploiement manuel. Pour ce faire, vous devez ajouter when : manual
à votre job. Il n'y aura effectivement plus de déploiement automatique en production. Le déploiement manuel s'effectue en allant dans CI/CD > Pipelines, et en cliquant sur ce bouton :
Effectuons maintenant un bond en avant dans le temps. Votre entreprise est devenue une société de plusieurs centaines d'employés travaillant sur le site web, et les compromis précédents ne fonctionnent plus.
Faire ses premiers pas avec les Review Apps
Logiquement, la nouvelle étape consiste à lancer une instance temporaire de l'application par branche de fonctionnalités pour examen. Pour cela, nous avons configuré un autre bucket S3. Sa seule particularité est que le contenu du site est placé dans un dossier portant le nom de la branche de développement, de sorte que l’URL ressemble à :
http://<REVIEW_S3_BUCKET_NAME>.s3-website-us-east-1.amazonaws.com/<branchname>/
Voici le remplacement du job pages
utilisé auparavant :
review apps:
variables:
S3_BUCKET_NAME: "reviewbucket"
image: python:latest
environment: review
script:
- pip install awscli
- mkdir -p ./$CI_BUILD_REF_NAME
- cp ./*.html ./$CI_BUILD_REF_NAME/
- aws s3 cp ./ s3://$S3_BUCKET_NAME/ --recursive --exclude "*" --include "*.html"
Ici, il est bon de connaître l'origine de cette variable $CI_BUILD_REF_NAME
. GitLab prédéfinit de nombreuses variables d'environnement à utiliser dans vos travaux. Notez que nous avons défini la variable S3_BUCKET_NAME
au sein du job. Vous pouvez ainsi réécrire les définitions de niveau supérieur.
Représentation visuelle de la configuration des Review Apps :
Dans la pratique, la mise en œuvre des Review Apps varie en fonction de votre pile technologique et de votre processus de déploiement. Tout ne sera pas aussi simple qu'avec un site HTML statique. Programmer des instances temporaires à la volée avec tous les logiciels et services requis n'est pas chose aisée. Mais tout cela peut être accompli, notamment à l'aide des conteneurs Docker, Chef ou Ansible.
Le déploiement avec Docker mériterait d'ailleurs un article complet. Et si vous regrettez l'absence de scénarios plus complexes qu'un simple déploiement en HTML statique, nous vous recommandons de lire cet article. Abordons maintenant un dernier sujet.
Déployer sur différentes plateformes
Dans la pratique, nous ne sommes pas limités à S3 et à GitLab Pages. Nous hébergeons et déployons nos applications sur différents services. De plus, si vous décidez un jour de passer à une nouvelle plateforme, vous devrez alors réécrire tous vos scripts de déploiement. Vous pourrez alors utiliser une petite merveille appelée dpl
pour vous faciliter la tâche.
Jusqu'ici, nous avons utilisé awscli
pour livrer du code à un service comme Amazon S3. Quel que soit le système utilisé, le principe reste le même : vous exécutez une commande avec certains paramètres et transmettez une clé secrète d'authentification. L'outil de déploiement dpl
utilise ce principe et fournit une interface unique pour cette liste de fournisseurs. Voici à quoi ressemblerait le déploiement d’un job en production avec dpl
:
variables:
S3_BUCKET_NAME: "yourbucket"
deploy to production:
environment: production
image: ruby:latest
script:
- gem install dpl
- dpl --provider=s3 --bucket=$S3_BUCKET_NAME
only:
- main
En cas de déploiement sur plusieurs systèmes ou de changements fréquents de plateforme de destination, dpl
vous aide à uniformiser vos scripts de déploiement.
Cinq points clés à retenir
-
Un déploiement est une commande (ou un ensemble de commandes) régulièrement exécutée. Il peut donc être exécuté au sein de GitLab CI.
-
La plupart des commandes à exécuter nécessitent de fournir une ou plusieurs clés secrètes, que vous stockez dans Paramètres > CI/CD > Variables.
-
Avec GitLab CI, vous pouvez spécifier de façon flexible les branches vers lesquelles vous déployez votre code.
-
GitLab conserve l'historique des déploiements dans tous vos environnements, et vous permet de revenir à n'importe quelle version précédente.
-
Pour les éléments critiques de votre infrastructure, vous pouvez activer le déploiement manuel depuis l'interface de GitLab, au lieu du déploiement automatisé.