TP CI/CD
Cette formation vise à te donner les clés pour pouvoir écire tes propres CI/CD à travers l'outil Pipeline de gitlab, afin de te simplifier la vie lors de l'écriture et le déploiement de ton code. Ceci peut te servir dans un contexte personnel, associatif, ou même lors des Coding Weeks ;)
Dans ce README se trouvent des informations supplémentaires sur nombreux concepts qui seront explorés dans la formation.
Pour t'aider lors de cette formation, tu peux également trouver des informations complémentaires dans la documentation officielle de gitlab, ici.
Pré-requis
La première étape est de forker
le projet actuel, pour pouvoir travailler sur un projet personnel sans se marcher sur les pieds les uns les autres. Il faut ensuite cloner
le projet en local pour pouvoir travailler dessus, et push
ses modifications comme vous avez pu le faire lors de la formation Git (dont les slides sont disponibles ici).
Lors de ce projet, nous allons exécuter de nombreuses pipelines. Pour suivre l'état des pipelines, il suffit de se rendre sur l'interface web dans CI/CD > Pipelines.
A LIRE POUR L'ETAPE DE TEST
Les variables d'environnement
Les variables d'environnement sont des variables dynamiques utilisées par la machine dans laquelle nous travaillons. Comme nous travaillons dans des Docker qui n'ont que des variables d'environnement par défaut, il faut définir toutes les variables d'environnement nécessaires au bon fonctionnement des processus.
De nombreuses variables d'environnements spécifiques à la CI/CD existent également. Une liste d'une grande partie de celles-ci se trouve ici.
La déclaration de variables d'environnement peut se faire de deux manières différentes: avec des variables globales à toute la CI/CD ou avec des variables spécifiques à certaines jobs. Dans les deux cas, elles sont définies grâce au mot clé variables
tel que décrit ci-dessous:
variables:
PORT: 3069
Il est aussi possible de définir des variables secrètes dans Settings > CI/CD > Variables. Ceci est notamment utile pour les mot de passes ;)
A LIRE POUR L'ETAPE D'INSTALLATION
Artifacts
Les artifacts
permettent d'archiver des fichiers et des dossiers afin qu'ils soient réutilisés facilement dans d'autres étapes de la pipeline, et dans d'autres pipelines.
Ceci permet par exemple de ne pas perdre de temps sur l'installation des dépendances dans chaque étapes de la CI/CD, en ne le faisant qu'une seule fois. Cela permet également de compiler des sites dans une étape et de récupérer les fichiers compilés dans une autre (ce qui n'est pas nécessaire pour le projet actuel).
Les artifacts se définissent sur des jobs, de la manière suivante:
job:
artifacts:
paths:
- my/path
expire_in: 1 week
script:
- mon script d'installation des dépendances
Ici, on veut mettre les dépendances en artifact. Pour ceci, il faut rajouter le dossier node_modules
dans les artifacts dans l'étape d'installation.
Dependencies
Certains jobs dépendent d'autres jobs pour fonctionner. Pour ceci, il existe le mot clé dependencies
. Il permet de définir tous les jobs qui doivent être exécutés avant celui que l'on est en train de définir. De plus, si on veut récupérer les artifacts d'un job, il faut dépendre de celui-ci.
job:
dependencies:
- myotherjob
- anotherjob
script:
- mon script qui dépend des installations
A LIRE POUR L'ETAPE DE DEPLOIEMENT
Les access tokens Gitlab
Les access tokens
sont des tokens qui permettent, en fonction des permissions qu'on leur définit, d'accéder à un projet gitlab, de lire ses fichiers, et même de les modifier. Cela permet d'utiliser un projet Gitlab sur une machine sans utiliser le compte personnel de quelqu'un.
Ces tokens peuvent être créés dans Settings > Access Tokens. Attention, le token ne sera affiché sur l'interface web que lors de la création, il faut donc le sauvegarder quelque part.
Une fois ce token créé, il est possible de cloner un projet avec la commande suivante: git clone https://<token name>:<token>@gitlab.viarezo.fr/<project path>
. Il faut lancer ceci une première fois sur la machine sur laquelle tourne le site. Ensuite, il sera possible de faire des git pull
sur la machine pour récupérer le code du site à jour.
Conditions de lancement d'un job
Parfois, il y a des étapes de la pipeline que l'on ne veut pas appliquer à chaque commit, à chaque branche... Pour ça, on peut mettre des conditions sur le lancement des jobs.
Il existe deux syntaxes différentes:
-
only
est une liste de conditions à respecter pour pouvoir lancer la pipeline. Par exemple :
myjob:
only: [master, staging, merge_requests]
script:
- mon script qui ne se fait que sous certaines conditions
-
rules
est une liste de règles à respecter pour pouvoir lancer la pipeline. Les règles permettent plus de flexibilité queonly
, en définissant si la règle inclut ou exclut le job, et en utilisant des conditions plus complexes. Par exemple :
myjob:
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
when: always
- if: '$CUSTOM_VARIABLE == "manual"'
when: manual
script:
- mon script qui ne se fait que sous certaines conditions
Déploiement
Cas actuel: utilisation de Sshpass
Sshpass
permet d'utiliser la commande ssh
avec mot de passe dans une CI/CD. En effet, l'utilisation de ssh
avec mot de passe est interactive, ce qqu'on ne souhaite pas dans notre pipeline. Grâce à la variable d'environnement SSHPASS
dont la valeur doit être égale au mot de passe SSH, Sshpass permet d'éviter cette partie interactive.
On l'utilise de la manière suivante, en précédant les commandes par sshpass -e
. Par exemple, sshpass -e ssh -p 2096 gowoons@padawan.viarezo.fr
. Ou pour scp, sshpass -e scp -P 2096 -r ./node_modules gowoons@padawan.viarezo.fr:~/forma-cicd
.
(Vous devez utiliser ces commandes, mais n'oubliez pas de changer le port, et l'username)
Avant le script qui permet de copier des fichiers sur la machine, de s'y connecter et de lancer le serveur, il faut réaliser les opérations suivantes pour installer Sshpass et configurer l'agent SSH :
job: deploy
before_script:
- apt update && apt install sshpass -y
- mkdir -p ~/.ssh
- chmod 600 -R ~/.ssh
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
script:
- mon script
Ce qu'il faudrait utiliser en production
De manière générale, l'utilisation de ssh
avec mot de passe est une mauvaise pratique. En effet, c'est généralement beaucoup plus simple à cracker qu'une clé SSH.
Ainsi, en production, il faut créer une clé ssh sur la machine. Ensuite, il faut mettre la clé privée dans les variables de CI/CD. Bien sûr, on ne va pas l'écrire en clair dans le Gitlab comme pour les autres variables. Il est possible de définir des variables secrètes dans Settings > CI/CD > Variables.
Dans ce cas là, le script à appliquer avant de déployer le serveur sur la machine est le suivant :
job: deploy
before_script:
- eval $(ssh-agent -s)
- ssh-add <(echo "${SSH_PRIVATE_KEY}")
- mkdir -p ~/.ssh
- '[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config'
script:
- mon script
Pour aller plus loin
Le templating
Souvent, on a plusieurs environnements sur lesquels on lance des CI/CD très similaires : par exemple, la production et le staging. Pour ceci, au lieu d'écrire deux fois le même job, on va utiliser du templating avec le mot clé extends
.
On définit un job de base qui lui ne sera jamais run, mais sur lequel sont construits les jobs que l'on va faire tourner. On utilise le format suivant :
.deploy:
stage: build
script:
- ssh ${USER}@${DOMAIN} "cd my/site && git pull && systemctl reload nginx"
deploy-prod:
extends: .build
only:
- master
variables:
PROD: true
USER: myuser
DOMAIN: prod.viarezo.fr
deploy-staging:
extends: .build
only:
- staging
variables:
PROD: false
USER: myuser
DOMAIN: staging.viarezo.fr