--- title: Déploiement theme: ./_themes/5ika.css highlightTheme: github verticalSeparator: revealOptions: transition: 'fade' --- # Déploiement et automatisation --- # Développer, ce n’est pas uniquement coder, mais aussi... - Vérifier que l’application passe les tests - Linter le code - Installer des dépendances - Compiler les sources - Compiler une image Docker - Déployer vers un ou plusieurs environnements d’exécution - Notifier d’autres personnes - Packager une application - Migrer une base de données - Recharger la page après une modification du code dans l’IDE - ... --- # On automatise ! L'humain est doué pour réflechir et créer, la machine est douée pour executer et reproduire. L’humain fait des erreurs, oublie des choses, tandis qu’un ordinateur suit continuellement la recette qu’on lui fournit. - Moins de temps sur les tâches redondantes = Plus de temps sur le code - Plus de temps sur le code = Meilleure qualité de code - Meilleure qualité de code = Meilleur produit L’objectif final de l’automatisation, c’est de rendre le travail efficace et intéressant. --- # Quoi automatiser ? **Automatiser**: - Ce qui est récurrent (ex: Lint) - Ce qui est douloureux (ex: Test) - Ce qui est long (ex: Déploiement) **Ne pas automatiser**: - Ce qui relève de la création, de la réflexion - Ce qui demande des compétences très particulières ou nouvelles --- # Qu'est-ce qu'un pipeline ? Des outils permettent de définir un ensemble d’actions à effectuer à chaque fois qu’un développeur push des modifications dans un dépôt Git. Cet ensemble d’actions est appelé **Pipeline**. Un Pipeline est définie en différents stages qui correspondent à des groupes d’actions. Par exemple: Test, Compilation, Déploiement --- ![Pipeline](./img/pipeline.png) --- # C'est quoi un job ? Un pipeline est constitué d’un ensemble de **jobs** (ou tâches). Concrètement, un job est **un script Bash** qui s’exécute sur une base de code (un dépôt Git) dans le but d’effectuer une action claire (tester, déployer, alerter, …). Dans un pipeline, certains jobs peuvent s’effectuer en parallèle tandis que d’autres peuvent s’effectuer séquentiellement. --- # Le CI/CD ![CI/CD](./img/CI-CD.png) --- # Les types de test - Tests unitaires - Tests fonctionnels - Tests de régressions - Tests visuels - Tests de charge - Tests de sécurité - Code coverage - Calcul de dette technique > [SonarQube](https://www.sonarsource.com/products/sonarqube/) est un outil > qui analyse le code pour nous donner des informations précises sur sa qualité --- # Outils de CI/CD Plusieurs outils nous permettent de configurer et gérer des pipelines. Parmis les plus utilisés: - Gitlab CI: Référence dans le domaine, facile à prendre en main - Jenkins: Celui qui a inventé le concept, un peu vieillot mais puissant - GitHub Actions: Manière de faire GitHub … chaque semaine des nouveaux --- # Exemple (GitLab) - Les _jobs_ sont réunis dans des _stages_ - La configuration est faite dans un fichier _.gitlab-ci.yml_ - Tous les scripts sont exécutés dans des containers Docker - Les pipelines sont effectués par des Runners ![Pipeline Gitlab](img/pipeline-gitlab.png) --- ![Jobs dans le pipeline GitLab](img/pipeline-gitlab-jobs.png) --- # Avec GitHub Pour s'aligner avec GitLab, GitHub a mis en place un système de CI/CD nommé **GitHub Actions**. C'est ce que nous allons utiliser pour mettre en place un pipeline sur notre dépôt. --- ## Avantage de GitHub Actions - Intégration transparente : Les actions sont intégrées directement à GitHub, ce qui facilite leur utilisation avec vos dépôts. - Large écosystème : GitHub Actions dispose d'un vaste écosystème d'actions prédéfinies créées par la communauté et les organisations. --- ## Comment créer un workflow (pipeline) Un workflow est un ensemble d'étapes (actions) qui sont déclenchées automatiquement en réponse à des événements spécifiques sur GitHub. > Les étapes suivantes ne sont pas à réaliser tout de suite. > Nous allons les faire ensemble pas à pas ensuite. 1. Dans notre base de code, on crée un dossier `.github` puis un dossier `workflows` dans ce dossier. 2. Dans le dossier `.github/workflows/`, on crée un fichier `deploy.yml` 3. Dans ce fichier `deploy.yml`, on défini nos jobs Lorsque l'on va pusher ce fichier sur le dépôt Git, Github Actions va le lire automatiquement et effectuer les actions définies. --- ## Événements Généralement, le déclenchement d'un nouveau pipeline/workflow est fait à chaque *push* dans le dépôt Git. Mais on peut également déclencher des actions sur d'autres événements: - Création d'une Pull Request - Création d'un *tag* - Push uniquement sur la branche principale - Périodiquement - Création d'une issue [Liste des événements disponibles](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows) --- ## Création du fichier `deploy.yml` La définition des jobs doit suivre la structure attendue par GitHub Actions. ```yaml name: Déploiement # Nom du workflow on: - push # Événement(s) jobs: build-docker-image: # Nom du job runs-on: ubuntu-latest # OS utilisé pour executé le job steps: # Suite de commandes / tâches à effectuer - name: Check out code # Nécessaire, expliqué plus tard uses: actions/checkout@v3 - run: docker login -u ... -p ... - run: docker build -t 5ika/deer . - run: docker push 5ika/deer ``` --- ## Chut 🤫 Pour s'authentifier auprès de Docker Hub afin de pusher notre image, nous avons besoin de fournir nos identifiants et mots de passe dans le fichier `deploy.yml`. Cependant, ce fichier est public. Tout le monde peut le voir. On ne peut donc pas y mettre des informations _secrètes_. GitHub Actions permet de définir ailleurs ces _secrets_ et les utiliser dans notre workflow. --- ## Définir des secrets 1. Sur votre dépôt GitHub, aller dans _Settings_, puis _Secrets and variables_ et _Actions_ 2. Cliquer sur _New repository secret_ 3. Créer un secret avec le nom `DOCKER_HUB_PASSWORD` et mettre vote mot de passe Docker Hub comme valeur Ce secret est maintenant utilisable dans le fichier `deploy.yml`. --- ## Utiliser des secrets dans le workflow On complète notre workflow dans `deploy.yml` pour utiliser notre secret et des variables d'environnement: ```yaml name: Déploiement # Nom du workflow on: push # Événement(s) env: USERNAME: 5ika IMAGE_NAME: deer jobs: build-docker-image: # Nom du job runs-on: ubuntu-latest # OS utilisé pour executé le job steps: # Suite de commandes / tâches à effectuer - name: Check out code uses: actions/checkout@v3 - run: docker login -u $USERNAME -p $PASSWORD env: PASSWORD: ${{secrets.DOCKER_HUB_PASSWORD}} - run: docker build -t $USERNAME/$IMAGE_NAME . - run: docker push $USERNAME/$IMAGE_NAME ``` --- # À vous ! 1. Forker le dépôt https://github.com/5ika/Deer (si ce n'est pas déjà fait) 2. Cloner votre fork sur votre machine (si ce n'est pas déjà fait) 3. Ajouter un Dockerfile (si ce n'est pas déjà fait) 4. Ajouter un workflow grâce aux slides précédentes (ça c'est pas fait) --- ## Utiliser des actions tierces GitHub Actions permet d'utiliser des *steps* toutes prêtes faites par d'autres personnes directement dans vos workflows. Il met à disposition un [Marketplace](https://github.com/marketplace?type=actions) avec des actions toutes prêtes à être utilisées dans votre workflow. --- ### Exemple d'utilisation La GitHub Action [Publish Docker](https://github.com/marketplace/actions/publish-docker) permet de réaliser les étapes que nous avons fait précédemment. Pour l'utiliser dans une _step_, on utilise le mot-clé `uses` plutôt que `run`. --- ```yaml name: Déploiement on: push env: USERNAME: 5ika IMAGE_NAME: deer jobs: build-docker-image: runs-on: ubuntu-latest steps: - name: Check out code uses: actions/checkout@v3 - name: Publish to Registry uses: elgohr/Publish-Docker-Github-Action@v5 with: name: ${{ env.USERNAME }}/${{ env.IMAGE_NAME }} username: ${{ env.USERNAME }} password: ${{ secrets.DOCKER_HUB_PASSWORD }} ``` --- ### actions/checkout L'action [action/checkout](https://github.com/marketplace/actions/checkout) que nous avons utilisé dans notre workflow dès le début appelle une fonction fournie par GitHub. Celle-ci permet de faire en sorte d'avoir le code du dépôt dans le dossier courant pour le job. Un peu comme si on faisait un `git clone` pour récupérer les fichiers avant de builder l'image Docker. --- ## Travail pratique 1. Ajouter un fichier `README.md` à votre dépôt avec un peu de contenu 2. Sur le GitHub Marketplace, trouver l'action qui vous permet de mettre à jour la description de votre image sur Docker Hub 3. Créer une nouvelle _step_ dans votre workflow qui utilise l'action que vous avez trouvé > Une fois terminé, à chaque fois que vous modifiez le README sur votre dépôt Git, > la description de votre image sur Docker Hub doit se mettre à jour. --- # Serveurs dans le Cloud Quand on veut mettre à disposition une application à des utilisateurs, il faut que l'on fasse tourner notre application sur un _serveur_. Nous devons donc acheter un serveur sur un hébergeur. --- # Les types de serveur ![Types de serveur](img/server_types.png) --- ## CAAS Les CAAS, pour _Container as a Service_, sont une forme de PAAS. Elles permettent de faire tourner des images Docker. Dans le cadre de cette formation, nous utiliserons [Jelastic](https://www.virtuozzo.com/application-platform/) (maintenant appelé Virtuozzo Application Platform) proposé par Infomaniak. --- # Démo du fonctionnement de Jelastic sur Infomaniak --- # Travail pratique - Déploiement manuel Déployer manuellement l'image Docker que vous avez sur Docker Hub dans un nouvel environnement sur Jelastic. Tim fourni les identifiants en cours. À la fin de cette étape, vous avez désormais chacun.e: - Un environnement avec un unique node qui tourne, utilisant votre image - Une URL pour accéder à votre environnement --- Maintenant, nous allons faire en sorte que notre environnement sur Infomaniak soit **automatiquement** mis à jour dès qu'on **modifie le code** de notre application dans git (lorsqu'on push). --- # Exemple de job de déploiement vers Jelastic ```yaml ... env: ENVNAME: change-me ... ... deploy-to-jelastic: runs-on: ubuntu-latest container: mwienk/jelastic-cli # Image Docker dans laquelle les steps seront exécutées needs: build-docker-image # Indique qu'il faut attendre le job de build steps: # Petit fixe nécessaire pour la suite - run: ln -s /root/jelastic-cli.jar /github/home/jelastic-cli.jar # Authentification auprès de l'API de Jelastic Infomaniak - run: /root/jelastic/users/authentication/signin --login "$JELASTIC_USERNAME" --password "$JELASTIC_PASSWORD" --platformUrl app.jpc.infomaniak.com env: JELASTIC_USERNAME: ${{ secrets.JELASTIC_USERNAME }} JELASTIC_PASSWORD: ${{ secrets.JELASTIC_PASSWORD }} # Utilisation de l'API de Jelastic pour redéployer l'image Docker utilisé dans son environnement - run: /root/jelastic/environment/control/redeploycontainersbygroup --envName $ENVNAME --nodeGroup cp --tag latest ``` --- Une fois que tout fonctionne, vous avez un pipeline de CI/CD qui met à disposition une image Docker et qui met à jour votre serveur à chaque fois que vous faites une modification au niveau de votre code. Bravo ! 🎉 --- Nous avons fait cela dans un cas très simple avec deux fichiers statiques mais grâce à Docker, la même mécanique peut être utilisée pour tous les langages et tous les types d'application. Il suffit juste d'adapter le fichier Dockerfile pour s'adapter aux besoins de l'app. --- # Travail pratique Mettre en place un workflow qui envoi votre code vers SonarCloud (SonarQube). Une action dans le Marketplace existe: https://github.com/marketplace/actions/sonarcloud-scan --- Maintenant, nous pouvons regarder comment mettre en place cela dans un de vos projets. --- # S'il reste beaucoup de temps - Effectuer des actions sur des environnements autres que le `push` - Aborder comment fonctionne les GitHub pages