Commit 05d46cdd authored by Rémi Cailletaud's avatar Rémi Cailletaud
Browse files

corrections diverses

parent 8dcdee29
# TP intégration et déploiement continus #
Le TP est une suite de petits exercices consistant à écrire à chaque fois un fichier .gitlab-ci.yml.
*Prérequis : des bases de Git, Python, Docker.*
Prérequis : des bases de git, python, docker.
Le code source est fourni. Après l'échauffement, Nous allons travailler sur deux (tout) petits codes :
Le TP consiste en une suite de petits exercices consistant à écrire à chaque fois un fichier .gitlab-ci.yml.
Le code source est fourni. Après l'échauffement, nous travaillerons sur deux (tout) petits codes :
* python-extension : une extension python en C, pour voir un peu de vraie compilation, quand même ;
* python-dice : un module pur python d'une ligne, qui tire des dés. Avec lui nous irons des tests au déploiement en production en passant par la doc et la publication sur pypi.
* python-dice : un module pur python d'une ligne, qui tire les dés. Avec lui nous irons des tests au déploiement en production en passant par la mise ne ligne de la documentation et la publication sur pypi.
À chaque fois, nous fournissons les mots-clés à chercher dans la [documentation très complète de gitlab](https://docs.gitlab.com/ee/ci/yaml/README.html). Comme nous sommes gentils, nous fournissons aussi les solutions dans les fichiers .gitlab-ci-\*.yml.
À chaque fois, nous fournissons les mots-clés à chercher dans la [documentation très complète de gitlab](https://docs.gitlab.com/ee/ci/yaml/README.html). Comme nous sommes gentils, nous fournissons aussi les solutions dans les fichiers .gitlab-ci-\*.yml. Vous pouvez tricher !
Nous conseillons fortement l'utilisation de virtualenv pour les tests locaux.
*Note* : Nous conseillons fortement l'utilisation de virtualenv pour les tests locaux.
## Échauffement ##
### 1. Mon premier script ###
### 1. Mon premier fichier .gitlab-ci.yml ###
Mon premier fichier .gitlab-ci.yml. Il s'agit d'un fichier au format YAML décrit une ensemble d'étapes ([stages](https://docs.gitlab.com/ee/ci/yaml/#stage)) qui peuvent comporter plusieurs [jobs](https://docs.gitlab.com/ee/ci/yaml/#jobs).
Il s'agit d'un fichier au format YAML décrivant un ensemble d'étapes ([stages](https://docs.gitlab.com/ee/ci/yaml/#stages)) qui peuvent comporter plusieurs [jobs](https://docs.gitlab.com/ee/ci/yaml/#jobs).
Chaque job contient un [script](https://docs.gitlab.com/ee/ci/yaml/#script), exécuté par le Runner.
**But** : Afficher "Hello world", /etc/issue et l'heure. Aller dans l'interface de Gitlab (CI/CD) et constater le résultat. On peut voir le nom du Runner qui a exécuté le job.
**But** : Afficher "Hello world", /etc/issue et l'heure. Aller dans l'interface de Gitlab (*CI/CD -> Pipelines*) et constater le résultat. On peut voir le nom du Runner qui a exécuté le job.
*Note 1* : Chaque job est indépendant (chaque job peut-être exécuté sur un Runner différent...).
*Note 2* : L'image par défaut est choisie lors de l'installation du Runner.
......@@ -28,18 +27,18 @@ Chaque job contient un [script](https://docs.gitlab.com/ee/ci/yaml/#script), ex
### 2. Le choix de l'image docker ###
Les jobs sont exécutés dans les conteneur docker. Vous pouvez choisir le conteneur à utiliser avec le mot-clés [image](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#define-image-and-services-from-gitlab-ci-yml).
Les jobs sont exécutés dans des conteneurs Docker. Vous pouvez choisir le conteneur à utiliser avec le mot-clés [image](https://docs.gitlab.com/ee/ci/docker/using_docker_images.html#define-image-and-services-from-gitlab-ci-yml).
**But** : Utiliser l'image Ubuntu à la place de celle par défaut (Alpine). Constater la différence.
**But** : Utiliser l'image Ubuntu à la place de celle par défaut. Constater la différence.
*Note 1* : Par défaut on utilise DockerHub, le repository Docker n'étant (encore) pas activé sur notre instance Gitlab.
*Note 1* : Par défaut on utilise DockerHub, le repository Docker n'étant pas (encore) activé sur notre instance Gitlab.
*Note 2* : On peut choisir une image différente par job.
### 3. Le pipeline ###
On définit les Pipelines en déclatant plusieurs [stages](https://docs.gitlab.com/ee/ci/yaml/#stage). Chaque job définit à quelle étape il appartient grâce au mot-clé [stage](https://docs.gitlab.com/ee/ci/yaml/#stage).
On définit les Pipelines en déclarant plusieurs [stages](https://docs.gitlab.com/ee/ci/yaml/#stages). Chaque job définit à quelle étape il appartient grâce au mot-clé [stage](https://docs.gitlab.com/ee/ci/yaml/#stage).
Plusieurs jobs de la même étape pourront être exécuté en même temps si les ressources le permettent. Par contre, l'exécution d'une étape dépend du bon déroulement de la précédente, à moins d'en autoriser explicitement l'échec avec [allow_failure](https://docs.gitlab.com/ee/ci/yaml/#allow_failure).
Plusieurs jobs de la même étape pourront être exécuté en même temps si les ressources le permettent. En revanche, l'exécution d'une étape dépend du bon déroulement de la précédente, à moins d'en autoriser explicitement l'échec avec [allow_failure](https://docs.gitlab.com/ee/ci/yaml/#allow_failure).
```mermaid
graph LR;
......@@ -59,31 +58,31 @@ job2_1-->job3
job2_2-->job3
```
**But** : Définir 3 étapes test1, test2 et test3. Les étapes 1 et 3 comporteront chacune un job, et l'étape deux en compertera deux, dont un qui échoue.
**But** : Définir 3 étapes test1, test2 et test3. Les étapes 1 et 3 comporteront chacune un job, et l'étape 2 en comportera deux, dont un qui échoue.
Observer le comportement dans l'interface, puis ajouter autoriser l'échec pour le job qui échoue.
*Note* : Avec allow_failure, le pipeline passe, mais vous voyez quand même un warning...
*Note* : Avec [allow_failure](https://docs.gitlab.com/ee/ci/yaml/#allow_failure), le pipeline passe, mais vous voyez quand même un warning...
### 4. Une étape manuelle ###
Le mot-clé [when](https://docs.gitlab.com/ee/ci/yaml/#when) permet de définir quand le job est exécuté : en cas de succès(défaut), d'échec, quoi qu'il arrive, ou manuellement.
Le mot-clé [when](https://docs.gitlab.com/ee/ci/yaml/#when) permet de définir quand le job est exécuté : en cas de succès(comportement par défaut), d'échec, quoi qu'il arrive, ou manuellement.
**But** : Ajouter un job manuel au pipeline. Aller sur l'interface pour l'exécuter.
**But** : Ajouter un job manuel au pipeline. Lancer son exécution depuis l'interface.
*Note* : Contrairement aux autres jobs, les jobs manuels sont autorisés à échouer par défaut (pour ne pas bloquer le pipeline). On peut changer ce comportement, mais il faudra alors une intervention humaine pour débloquer le pipeline...
### 5. Pousser des modifications sans lancer le pipeline ###
Dans certains cas, veut pousser des commit sans lancer le pipeline. Pour cela, il suffit de spécifier [skpi-ci] ou [ci-skip] dans le message de commit.
Dans certains cas, on veut pouvoir pousser des changements sans lancer le pipeline. Pour cela, il suffit de spécifier [skpi-ci] ou [ci-skip] dans le message de commit.
**But** : Après une modification, pousser le changement en précisant [skip-ci] dans le message de commit. Observer le comportement dans l'interface.
### 6. Programmer des pipelines : les schedules ###
On peut programmer des pipelines pour qu'il soient lancés à intervalles réguliers (par exemple pour les nightly builds).
On peut programmer des pipelines pour qu'ils soient lancés à intervalles réguliers (par exemple pour les *Nightly Builds*).
**But** : Programmer un pipeline avec dans CI/CD -> Schedule. Puis, ajouter un job qui ne sera exécuté que lors des pipeliens programmés à l'aide du mot-clé [only](https://docs.gitlab.com/ee/ci/yaml/#only-and-except-simplified)
**But** : Programmer un pipeline dans *CI/CD -> Schedule*. Puis, ajouter un job qui ne sera exécuté que lors des pipeliens programmés à l'aide du mot-clé [only](https://docs.gitlab.com/ee/ci/yaml/#only-and-except-simplified)
## Compilation python ##
......@@ -95,7 +94,7 @@ Le premier "vrai" projet est une très simple extension C pour python, histoire
### 7. Utilisation de l'image python et compilation ###
**But** : Utiliser l'image python pour compiler et installer le module.
**But** : Utiliser l'image python pour compiler et installer le module à l'aide de Distutils.
*Note* : Si vous voulez tester l'installation en local sur votre poste, utilisez un virtualenv...
......@@ -127,11 +126,11 @@ Nous allons maintenant travailler avec un petit module en pur python créé pour
### 11. Tests et publication de la documentation à l'aide de Gitlab Pages ###
Nous allons écrire un pipeline complet, qui teste la fonctionnalité et le style du code (avec *pycodestyle*, disponible dans *pip*) et qui génère et déploie la documentation (avec *sphinx*, disponible lui aussi dans *pip*). Pour la partie documentation, on utilisera [only](https://docs.gitlab.com/ee/ci/yaml/#only-and-except-complex) pour ne la regénérer que si le message de commit commence par `[doc]`. Cette étape un peu spéciale est appelée [pages](https://docs.gitlab.com/ee/ci/yaml/#pages) et s'appuie sur une fonctionnalité appelée [Gitlab Pages](https://docs.gitlab.com/ee/user/project/pages/index.html) (original !).
Nous allons écrire un pipeline complet, qui teste la fonctionnalité et le style du code (avec *pycodestyle*, disponible dans *pip*) et qui génère et déploie la documentation (avec *sphinx*, disponible lui aussi dans *pip*). Pour la partie documentation, on utilisera [only](https://docs.gitlab.com/ee/ci/yaml/#only-and-except-complex) pour ne la générer que si le message de commit commence par `[doc]`. Cette étape un peu spéciale est appelée [pages](https://docs.gitlab.com/ee/ci/yaml/#pages) et s'appuie sur une fonctionnalité appelée [Gitlab Pages](https://docs.gitlab.com/ee/user/project/pages/index.html) (original !).
**But** : Écrire un fichier .gitlab-ci.yml qui comporte trois deux étapes.
**But** : Écrire un fichier .gitlab-ci.yml qui comporte deux étapes.
* La première étape comporte deux jobs, l'un qui teste le code à l'aide du test unitaire, et l'autre qui teste son style à l'aide de pycodestyle. Comme nous ne sommes pas des orthodoxes, admettons que dans certains cas le *coding style* peut ne pas être respecté...
* La seconde étape génère et déploie la documentation dans Gitlab Pages
* La seconde étape génère et déploie la documentation dans Gitlab Pages.
Vérifier qu'en ne respectant pas la [PEP8](https://www.python.org/dev/peps/pep-0008/), le pipeline émet une alerte.
Vérifier que la documentation est bien déployée (le lien est disponible dans *Settings -> Pages*).
......@@ -140,11 +139,11 @@ Vérifier que la documentation est bien déployée (le lien est disponible dans
### 12. Les (presque) inutiles et donc indispensables badges ###
L'utilitaire *coverage* (disponible dans *pip*) permet d'obtenir le taux de couverture de vos tests, indicateur intéressant de la qualité du code. Cette information (ainsi que le status du pipeline) peut apparaître par exemple dans votre doc grâce aux désormais très populaires [Badges](https://docs.gitlab.com/ee/user/project/pipelines/settings.html#test-coverage-report-badge)
L'utilitaire *coverage* (disponible dans *pip*) permet d'obtenir le taux de couverture de vos tests, indicateur intéressant de la qualité du code. Cette information (ainsi que le status du pipeline) peut apparaître par exemple dans votre doc grâce aux désormais très populaires [Badges](https://docs.gitlab.com/ee/user/project/pipelines/settings.html#test-coverage-report-badge).
**But** : Ajouter les tests de couveture au job de test. Dans *Settings -> CI/CD -> General pipelines*, spécifier la regexp permettant de récupérer le taux de couverture, et récupérer le code HTMl et/ou Markdown à ajouter à la doc et/ou au fichier README.md.
**But** : Ajouter les tests de couverture au job de test. Dans *Settings -> CI/CD -> General pipelines*, spécifier la regexp permettant de récupérer le taux de couverture, et récupérer le code HTML et/ou Markdown à ajouter à la doc et/ou au fichier README.md.
*Note 1* : Pour lancer les tests de couverture
*Note 1* : Pour lancer les tests de couverture et obtenir le rapport :
```bash
coverage run -m unittest discover
coverage report
......@@ -158,34 +157,36 @@ TOTAL\s+\d+\s+\d+\s+(\d+\%)$
### 13. Le déploiement sur Pypi ###
Nous allons maintenant déployer notre module sur l'instance de test de Pypi à l'aide de *twine*, disponible dans *pip*. Le déploiement ne se fait que pour les branches ou tags nommés "version-\*", grâce à l'utilisation du mot-clé [only](https://docs.gitlab.com/ee/ci/yaml/#only-and-except-simplified). Pour éviter de spécifier les identifiants dans le dépôt, nous utilisons les variables Gitlab (*Settings -> CI/CD -> Varilables*).
Nous allons maintenant déployer notre module sur l'instance de test de Pypi à l'aide de *twine*, disponible dans *pip*. Le déploiement ne se fait que pour les branches ou tags nommés "version-\*", grâce à l'utilisation du mot-clé [only](https://docs.gitlab.com/ee/ci/yaml/#only-and-except-simplified). Pour éviter de spécifier les identifiants dans le dépôt, nous utilisons les [variables Gitlab](https://docs.gitlab.com/ee/ci/variables/#variables) (*Settings -> CI/CD -> Variables*).
But : Ajouter une étape qui va construire et déployer le paquet sur Pypi si le nom de la référence (branche ou tag) commence par *version-*. Utiliser les variables Gitlab pour les identifiants. Pousser un nouveau tag/branche, vérifier que le paquet est bien déployé, et que vous pouvez l'installer via pip.
**But** : Ajouter une étape qui va construire et déployer le paquet sur Pypi si le nom de la référence (branche ou tag) commence par "*version-*". Utiliser les variables Gitlab pour les identifiants. Pousser un nouveau tag ou une nouvelle branche, vérifier que le paquet est bien déployé, et que l'installation est possible via pip.
*Note 1* : Construire une wheel dans le répertoire wheelhouse
*Note 1* : Construire une wheel dans le répertoire wheelhouse :
```bash
pip wheel . -w wheelhouse
```
*Note 2* : Utilisez l'instance de test de Pypi avec `--repository-url https://test.pypi.org/legacy/` pour twine et `--index-url https://test.pypi.org/simple/` pour pip.
*Note 2* : Utiliser l'instance de test de Pypi :
`--repository-url https://test.pypi.org/legacy/` pour twine
`--index-url https://test.pypi.org/simple/` pour pip.
*Note 3* : On ne peut déployer plusieurs fois la même version d'un paquet sur Pypi. Utilisez le numéro de version correspondant au numéro de votre dépôt (ex : version 1.0 pour le groupe formation-ci-01).
*Note 3* : On ne peut déployer plusieurs fois la même version d'un paquet sur Pypi. Utilisez un numéro de version majeure correspondant au numéro de votre dépôt (ex : version 1.x pour le groupe formation-ci-01).
*Note 4* : Pour les gros projets multi-depôts, il est conseillé d'utiliser plutôt des outils dédiés pour la gestion de secrets (comme [Hashicorp Vault](https://www.vaultproject.io/).
*Note 4* : Pour les gros projets multi-dépôts, il est conseillé d'utiliser plutôt des outils dédiés pour la gestion de secrets (comme [Hashicorp Vault](https://www.vaultproject.io/)).
### 14. Dockerception ###
[dice-http-server](pyton-dice/dice-http-server) est un petit serveur web qui permet d'utiliser dice. Par exemple, l'appel à la page http://serveur/4-6 tirera 4 dés à 6 faces. Nous allons maintenant construire un conteneur Docker et le déployer sur notre infrastructure. Comme nous sommes prudents, le déploiement de l'image sera manuel.
[dice-http-server](python-dice/dice-http-server) est un petit serveur web qui permet d'utiliser dice. Par exemple, l'appel à la page http://server/4-6 tirera 4 dés à 6 faces. Nous allons maintenant construire un conteneur Docker et le déployer sur notre infrastructure. Comme nous sommes prudents, le déploiement de l'image sera manuel.
Pour cela, nous allons avoir besoin du [Service](https://docs.gitlab.com/ee/ci/services/) *docker:dind*, qui permet de fournir le démon docker au conteneur exécutant notre job. Notre instance de Gitlab ne fournissant pour l'instant pas de registry, nous utiliserons Docker Hub. Nous utiliserons là encore les variables Gitlab pour spécifier les identifiants.
Pour cela, nous allons avoir besoin du [Service](https://docs.gitlab.com/ee/ci/services/) *docker:dind*, qui permet de fournir le démon docker au conteneur exécutant notre job. Notre instance de Gitlab ne fournissant pour l'instant pas de registry, nous utiliserons Docker Hub. Nous utiliserons là encore les [variables Gitlab](https://docs.gitlab.com/ee/ci/variables/#variables) pour spécifier les identifiants.
But : Construire une image docker grâce au Dockerfile fournit, la pousser sur DockerHub, et permettre son déploiement en production manuel. Lors de la mise à jour, utiliser docker pull stopper l'ancien conteneur avant de lancer le nouveau.
**But** : Construire une image docker grâce au Dockerfile fourni, la pousser sur DockerHub, et permettre son déploiement en production manuel. Lors de la mise à jour, utiliser docker pull afin de stopper l'ancien conteneur avant de lancer le nouveau.
*Note 1* : Demandez le nom du serveur Docker...
*Note 2* : Afin d'éviter les conflits, exposez votre conteneur sur le port 80x0 avec x le numéro du dépôt (ex : port 8010 pour fomration-ci-01).
*Note 2* : Évidemment, dans la réalité nous ne déploierons pas en production depuis le master... Jetez aussi un oeil aux [Environments](https://gricad-gitlab.univ-grenoble-alpes.fr/help/ci/environments).
*Note 2* : Évidemment, dans la réalité nous ne déploierons pas en production depuis le master... Jetez aussi donc un oeil aux [Environments](https://docs.gitlab.com/ee/ci/environments.html).
*Note 3* : Idéalement, notre conteneur doit lui aussi recevoir une série de tests avant d'être déployé !
......@@ -193,17 +194,17 @@ But : Construire une image docker grâce au Dockerfile fournit, la pousser sur D
Un des patterns du déploiement continu est le Blue/Green Deployment[^1] (et sa variante Canary Release). Il consiste à avoir plusieurs conteneurs en production, et les mettre à jour de manière progressive afin de détecter d'éventuelles anomalies.
![canary](img/canary-relase.png)
![canary](img/canary-release.png)
Nous allons maintenant déployer deux conteneurs (dice-green et dice-blue), en utilisant une fonctionnalité YAML appelée [Anchors](https://docs.gitlab.com/ee/ci/yaml/#anchors) qui permet de factoriser du code.
*But* : Deéployer deux conteneurs dice-blue et dice-green. Les jobs sont distincts et manuels.
**But** : Déployer deux conteneurs dice-blue et dice-green. Les jobs sont distincts et manuels.
*Note* : Parmi les [variables Gitlab prédéfinies](https://docs.gitlab.com/ee/ci/variables/README.html#predefined-variables-environment-variables) `$CI_JOB_NAME` pourrait vous intéresser...
*Note*: Utilisez les ports 80x0 et 80x1...
[^1]:https://martinfowler.com/bliki/BlueGreenDeployment.html
[^1]: [Martin Fowler, BlueGreenDeployment](https://martinfowler.com/bliki/BlueGreenDeployment.html)
blue/green ? templates (en fait anchors YAML)
### 16. bonus : répertoire infra, haproxy, docker-compose.yml ###
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment