Dans le monde rapide du développement logiciel, livrer des applications de haute qualité rapidement et de manière fiable est crucial. C’est là que le CI/CD (Intégration Continue et Livraison/Déploiement Continus) entre en jeu.

Le CI/CD est un ensemble de pratiques et d’outils conçus pour automatiser et rationaliser le processus d’intégration des modifications de code, de les tester et de les déployer en production. En adoptant le CI/CD, votre équipe peut réduire les erreurs manuelles, accélérer les cycles de publication et s’assurer que votre code est toujours dans un état déployable.

Dans ce tutoriel, nous nous concentrerons sur une approche conviviale pour les débutants pour mettre en place un pipeline CI/CD de base en utilisant Bitbucket, un serveur Linux et Python avec Flask. Plus précisément, nous allons créer un processus automatisé qui récupère les dernières modifications d’un dépôt Bitbucket vers votre serveur Linux chaque fois qu’il y a un push ou une fusion vers une branche spécifique.

Ce processus sera alimenté par des webhooks Bitbucket et un serveur Python simple basé sur Flask qui écoute les événements de webhook entrants et déclenche le déploiement.

Il est important de noter que le CI/CD est un domaine vaste et complexe, et ce tutoriel est conçu pour fournir une compréhension fondamentale plutôt que d’être un guide exhaustif.

Nous couvrirons les bases de la mise en place d’un pipeline CI/CD en utilisant des outils accessibles aux débutants. Gardez simplement à l’esprit que les systèmes CI/CD du monde réel impliquent souvent des outils et des configurations plus avancés, tels que la conteneurisation, l’orchestration et les environnements de test à plusieurs étapes.

À la fin de ce tutoriel, vous aurez un exemple fonctionnel de comment automatiser les déploiements en utilisant Bitbucket, Linux et Python, sur lequel vous pourrez vous appuyer pour approfondir vos connaissances des concepts CI/CD.

Table des matières:

  1. Pourquoi le CI/CD est-il important?

  2. Étape 1: Configurer un Webhook dans Bitbucket

  3. Étape 2: Configurer l’écouteur Flask sur votre serveur Linux

  4. Étape 3: Exposer l’application Flask (facultatif)

  5. Étape 4: Tester la configuration

  6. Étape 5 : Considérations de sécurité

  7. Conclusion

Pourquoi le CI/CD est-il important?

Le CI/CD est devenu un pilier du développement logiciel moderne pour plusieurs raisons. Tout d’abord, il accélère le processus de développement. En automatisant des tâches répétitives telles que les tests et le déploiement, les développeurs peuvent se concentrer davantage sur l’écriture de code et moins sur les processus manuels. Cela permet une livraison plus rapide de nouvelles fonctionnalités et de correctifs, ce qui est particulièrement important dans des marchés concurrentiels où la vitesse peut être un facteur différenciateur.

Un autre avantage clé du CI/CD est la réduction des erreurs et l’amélioration de la fiabilité. Les tests automatisés garantissent que chaque changement de code est rigoureusement vérifié pour détecter les problèmes avant son intégration dans le code principal. Cela réduit au minimum le risque d’introduire des bogues qui pourraient perturber l’application ou nécessiter des correctifs coûteux ultérieurement. Les pipelines de déploiement automatisés réduisent également la probabilité d’erreurs humaines lors du processus de publication, garantissant que les déploiements sont cohérents et prévisibles.

CI/CD favorise également une meilleure collaboration entre les membres de l’équipe. Dans les flux de travail de développement traditionnels, l’intégration des modifications de code provenant de plusieurs développeurs peut être un processus long et sujet aux erreurs. Avec CI/CD, le code est intégré et testé fréquemment, souvent plusieurs fois par jour. Cela signifie que les conflits sont détectés et résolus tôt, et que la base de code reste dans un état stable. En conséquence, les équipes peuvent travailler plus efficacement et avec une plus grande confiance, même lorsque plusieurs contributeurs travaillent simultanément sur différentes parties du projet.

Enfin, CI/CD soutient l’amélioration continue et l’innovation. En automatisant le processus de déploiement, les équipes peuvent publier des mises à jour en production plus fréquemment et avec moins de risques. Cela leur permet de recueillir plus rapidement des retours d’utilisateurs et d’itérer sur leurs produits de manière plus efficace.

Ce que nous allons aborder dans ce tutoriel

Dans ce tutoriel, nous passerons en revue le processus de mise en place d’un pipeline CI/CD simple qui automatise le déploiement des modifications de code depuis un dépôt Bitbucket vers un serveur Linux. Voici ce que vous apprendrez :

  1. Comment configurer un dépôt Bitbucket pour envoyer des notifications webhook chaque fois qu’il y a un push ou une fusion vers une branche spécifique.

  2. Comment mettre en place un serveur Python basé sur Flask sur votre serveur Linux pour écouter les événements webhook entrants.

  3. Comment écrire un script qui extrait les derniers changements du référentiel et les déploie sur le serveur.

  4. Comment tester et dépanner votre processus de déploiement automatisé.

À la fin de ce tutoriel, vous aurez un exemple fonctionnel d’un pipeline CI/CD de base que vous pouvez personnaliser et étendre selon vos besoins. Commençons!

Étape 1: Configurer un webhook dans Bitbucket

Avant de commencer la configuration, expliquons brièvement ce qu’est un webhook et comment il s’intègre dans notre processus CI/CD.

Un webhook est un mécanisme qui permet à un système de notifier un autre système d’un événement en temps réel. Dans le contexte de Bitbucket, un webhook peut être configuré pour envoyer une requête HTTP (souvent une requête POST avec des données de charge utile) à une URL spécifiée chaque fois qu’un événement spécifique se produit dans votre référentiel, tel qu’un push vers une branche ou une fusion de demande de tirage.

Dans notre cas, le webhook notifiera notre serveur Python basé sur Flask (en cours d’exécution sur votre serveur Linux) chaque fois qu’il y a un push ou une fusion vers une branche spécifique. Cette notification déclenchera un script sur le serveur pour extraire les derniers changements du référentiel et les déployer automatiquement. Fondamentalement, le webhook agit comme le pont entre Bitbucket et votre serveur, permettant une automatisation transparente du processus de déploiement.

Maintenant que vous comprenez le rôle d’un webhook, configurons-en un dans Bitbucket:

  1. Connectez-vous à Bitbucket et accédez à votre dépôt.

  2. Dans la barre latérale gauche, cliquez sur Paramètres.

  3. Sous la section Workflow, recherchez et cliquez sur Webhooks.

  4. Cliquez sur le bouton Ajouter un webhook.

  5. Entrez un nom pour votre webhook (par exemple, « Tirage automatique »).

  6. Dans le champ URL, fournissez l’URL de votre serveur où le webhook enverra la requête. Si vous exécutez localement une application Flask, cela ressemblerait à quelque chose comme http://votre-adresse-ip-serveur/tirer-depot. (Pour les environnements de production, il est fortement recommandé d’utiliser HTTPS pour sécuriser la communication entre Bitbucket et votre serveur.)

  7. Dans la section Déclencheurs, choisissez les événements auxquels vous souhaitez écouter. Pour cet exemple, nous choisirons Push (et éventuellement, Fusion de la demande de tirage si vous souhaitez déployer également après les fusions).

  8. Enregistrez le webhook avec un nom explicite pour pouvoir l’identifier facilement ultérieurement.

Une fois le webhook configuré, Bitbucket enverra une requête POST à l’URL spécifiée à chaque fois que l’événement sélectionné se produira. Dans les prochaines étapes, nous mettrons en place un serveur Flask pour gérer ces requêtes entrantes et déclencher le processus de déploiement.

Voici ce que vous devriez voir lorsque vous configurez le webhook Bitbucket

Étape 2 : Configurer l’écouteur Flask sur votre serveur Linux

Dans l’étape suivante, vous configurerez un serveur web simple sur votre machine Linux qui écoutera le webhook de Bitbucket. Lorsqu’il recevra la notification, il exécutera un git pull ou un pull forcé (en cas de modifications locales) pour mettre à jour le dépôt.

Installer Flask:

Pour créer l’application Flask, commencez par installer Flask en exécutant :

pip install flask

Créer l’application Flask :

Créez un nouveau script Python (par exemple, app_repo_pull.py) sur votre serveur et ajoutez le code suivant :

from flask import Flask
import subprocess

app = Flask(__name__)

@app.route('/pull-repo', methods=['POST'])
def pull_repo():
    try:
        # Récupérer les derniers changements du dépôt distant
        subprocess.run(["git", "-C", "/path/to/your/repository", "fetch"], check=True)
        # Réinitialiser de force la branche locale pour correspondre à la branche distante 'test'
        subprocess.run(["git", "-C", "/path/to/your/repository", "reset", "--hard", "origin/test"], check=True)  # Remplacez 'test' par le nom de votre branche
        return "Force pull successful", 200
    except subprocess.CalledProcessError:
        return "Failed to force pull the repository", 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Voici ce que fait ce code :

  • subprocess.run(["git", "-C", "/chemin/vers/votre/dépôt", "fetch"]) : Cette commande récupère les derniers changements du dépôt distant sans affecter le répertoire de travail local.

  • subprocess.run(["git", "-C", "/chemin/vers/votre/dépôt", "reset", "--hard", "origin/test"]): Cette commande effectue une réinitialisation en force, forçant le dépôt local à correspondre à la branche test distante. Remplacez test par le nom de votre branche.

Assurez-vous de remplacer /chemin/vers/votre/dépôt par le chemin réel de votre dépôt Git local.

Étape 3: Exposer l’application Flask (Facultatif)

Si vous souhaitez rendre l’application Flask accessible depuis l’extérieur de votre serveur, vous devez l’exposer publiquement. Pour cela, vous pouvez configurer un proxy inverse avec NGINX. Voici comment faire:

Commencez par installer NGINX si vous ne l’avez pas déjà en exécutant cette commande:

sudo apt-get install nginx

Ensuite, vous devrez configurer NGINX pour envoyer les requêtes à votre application Flask. Ouvrez le fichier de configuration NGINX:

sudo nano /etc/nginx/sites-available/default

Modifiez la configuration pour inclure ce bloc:

server {
    listen 80;
    server_name your-server-ip;

    location /pull-repo {
        proxy_pass http://localhost:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Il ne reste plus qu’à recharger NGINX pour appliquer les changements:

sudo systemctl reload nginx

Étape 4: Tester la configuration

Maintenant que tout est configuré, lancez l’application Flask en exécutant ce script Python:

python3 app_repo_pull.py

Maintenant, pour tester si tout fonctionne :

  1. Faites un commit : Poussez un commit dans la branche test de votre dépôt Bitbucket. Cette action déclenchera le webhook.
  1. Déclenchement du webhook : Le webhook enverra une requête POST à votre serveur. L’application Flask recevra cette requête, effectuera un pull forcé depuis la branche test, et mettra à jour le dépôt local.

  2. Vérifiez le pull : Vérifiez la sortie des logs de votre application Flask ou inspectez le dépôt local pour vérifier que les modifications ont été tirées et appliquées avec succès.

Étape 5 : Considérations de sécurité

Lorsque vous exposez une application Flask à Internet, sécuriser votre serveur et votre application est crucial pour les protéger contre les accès non autorisés, les violations de données et les attaques. Voici les principaux domaines sur lesquels se concentrer :

1. Utilisez un serveur sécurisé avec des règles de pare-feu appropriées

Un serveur sécurisé est celui qui est configuré pour minimiser l’exposition aux menaces externes. Cela implique d’utiliser des règles de pare-feu, de minimiser les services inutiles et de s’assurer que seuls les ports nécessaires sont ouverts pour la communication.

Exemple de configuration d’un serveur sécurisé :
  • Logiciel minimal: Installez uniquement le logiciel dont vous avez besoin (par exemple, Python, Flask, NGINX) et supprimez les services inutiles.

  • Mises à jour du système d’exploitation: Assurez-vous que le système d’exploitation de votre serveur est à jour avec les derniers correctifs de sécurité.

  • Configuration du pare-feu: Utilisez un pare-feu pour contrôler le trafic entrant et sortant et limiter l’accès à votre serveur.

Par exemple, une configuration de base du pare-feu UFW (Uncomplicated Firewall) sur Ubuntu pourrait ressembler à ceci:

# Autoriser SSH (port 22) pour l'accès à distance
sudo ufw allow ssh

# Autoriser HTTP (port 80) et HTTPS (port 443) pour le trafic web
sudo ufw allow http
sudo ufw allow https

# Activer le pare-feu
sudo ufw enable

# Vérifier l'état du pare-feu
sudo ufw status

Dans ce cas:

  • Le pare-feu autorise les connexions SSH entrantes sur le port 22, HTTP sur le port 80 et HTTPS sur le port 443.

  • Tous les ports ou services inutiles doivent être bloqués par défaut pour limiter l’exposition aux attaques.

Règles de pare-feu supplémentaires :
  • Limiter l’accès au point de terminaison webhook : Idéalement, autorisez uniquement le trafic vers le point de terminaison webhook à partir des adresses IP de Bitbucket pour empêcher l’accès externe. Vous pouvez configurer cela dans votre pare-feu ou en utilisant votre serveur web (par exemple, NGINX) en acceptant uniquement les requêtes de la plage d’adresses IP de Bitbucket.

  • Refuser tout autre trafic entrant : Pour tout service qui n’a pas besoin d’être exposé à Internet (par exemple, les ports de base de données), assurez-vous que ces ports sont bloqués.

2. Ajouter une authentification à l’application Flask

Étant donné que votre application Flask sera accessible publiquement via l’URL webhook, vous devriez envisager d’ajouter une authentification pour garantir que seuls les utilisateurs autorisés (comme les serveurs de Bitbucket) peuvent déclencher le pull.

Exemple d’authentification de base :

Vous pouvez utiliser une authentification basée sur un jeton simple pour sécuriser votre point de terminaison webhook. Voici un exemple de modification de votre application Flask pour exiger un jeton d’authentification:

from flask import Flask, request, abort
import subprocess

app = Flask(__name__)

# Définir un jeton secret pour la vérification du webhook
SECRET_TOKEN = 'your-secret-token'

@app.route('/pull-repo', methods=['POST'])
def pull_repo():
    # Vérifier si la requête contient le bon jeton
    token = request.headers.get('X-Hub-Signature')
    if token != SECRET_TOKEN:
        abort(403)  # Interdit si le jeton est incorrect

    try:
        subprocess.run(["git", "-C", "/path/to/your/repository", "fetch"], check=True)
        subprocess.run(["git", "-C", "/path/to/your/repository", "reset", "--hard", "origin/test"], check=True)
        return "Force pull successful", 200
    except subprocess.CalledProcessError:
        return "Failed to force pull the repository", 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
Comment cela fonctionne:
  • Le X-Hub-Signature est un en-tête personnalisé que vous ajoutez à la requête lors de la configuration du webhook dans Bitbucket.

  • Seules les requêtes avec le bon jeton seront autorisées à déclencher la récupération. Si le jeton est manquant ou incorrect, la requête est rejetée avec une réponse 403 Forbidden.

Vous pouvez également utiliser des formes d’authentification plus complexes, telles que OAuth ou HMAC (Code d’authentification basé sur un message haché), mais cette approche simple de jeton fonctionne pour de nombreux cas.

3. Utiliser HTTPS pour une communication sécurisée

Il est crucial de crypter les données transmises entre votre application Flask et le webhook Bitbucket, ainsi que toutes les données sensibles (comme les jetons ou les mots de passe) transmises sur le réseau. Cela garantit que les attaquants ne peuvent pas intercepter ou modifier les données.

Pourquoi HTTPS ?
  • Chiffrement des données : HTTPS chiffre la communication, garantissant que des données sensibles comme votre jeton d’authentification ne sont pas exposées aux attaques de l’homme du milieu.

  • Confiance et intégrité : HTTPS aide à garantir que les données reçues par votre serveur n’ont pas été altérées.

Utiliser Let’s Encrypt pour sécuriser votre application Flask avec SSL :
  1. Installer Certbot (l’outil pour obtenir des certificats Let’s Encrypt) :
sudo apt-get update
sudo apt-get install certbot python3-certbot-nginx

Obtenir un certificat SSL gratuit pour votre domaine :

sudo certbot --nginx -d your-domain.com
  • Cette commande configurera automatiquement Nginx pour utiliser HTTPS avec un certificat SSL gratuit de Let’s Encrypt.

  • S’assurer que HTTPS est utilisé : Assurez-vous que votre application Flask ou la configuration Nginx force tout le trafic à utiliser HTTPS. Vous pouvez le faire en configurant une règle de redirection dans Nginx :

server {
    listen 80;
    server_name your-domain.com;

    # Rediriger HTTP vers HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name your-domain.com;

    ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;

    # Autre configuration Nginx...
}

Renouvellement automatique: Les certificats Let’s Encrypt sont valides pendant 90 jours, il est donc important de configurer le renouvellement automatique :

sudo certbot renew --dry-run

Cette commande teste le processus de renouvellement pour s’assurer que tout fonctionne.

4. Journalisation et surveillance

Mettre en place la journalisation et la surveillance pour votre application Flask afin de suivre toute tentative non autorisée, les erreurs ou l’activité inhabituelle :

  • Journaliser les requêtes : Journaliser toutes les requêtes entrantes, y compris l’adresse IP, les en-têtes de requête et le statut de la réponse, pour pouvoir surveiller toute activité suspecte.

  • Utiliser des outils de surveillance : Mettre en place des outils tels que Prometheus, Grafana, ou New Relic pour surveiller les performances du serveur et la santé de l’application.

Conclusion

Dans ce tutoriel, nous avons exploré comment mettre en place un pipeline CI/CD simple et adapté aux débutants qui automatise les déploiements en utilisant Bitbucket, un serveur Linux et Python avec Flask. Voici un récapitulatif de ce que vous avez appris :

  1. Fondamentaux de CI/CD: Nous avons discuté des bases de l’Intégration Continue (CI) et du Déploiement Continu (CD), qui sont des pratiques essentielles pour automatiser l’intégration, les tests et le déploiement du code. Vous avez appris comment le CI/CD aide à accélérer le développement, à réduire les erreurs et à améliorer la collaboration entre les développeurs.

  2. Configuration des Webhooks Bitbucket: Vous avez appris comment configurer un webhook Bitbucket pour notifier votre serveur à chaque fois qu’il y a un push ou une fusion dans une branche spécifique. Ce webhook sert de déclencheur pour initier automatiquement le processus de déploiement.

  3. Création d’un Écouteur de Webhook basé sur Flask: Nous vous avons montré comment mettre en place une application Flask sur votre serveur Linux pour écouter les demandes de webhook entrantes de Bitbucket. Cette application Flask reçoit les notifications et exécute les commandes Git nécessaires pour extraire et déployer les derniers changements.

  4. Automatisation du processus de déploiement: En utilisant Python et Flask, nous avons automatisé le processus d’extraction des changements du dépôt Bitbucket et effectué une extraction forcée pour garantir que le code le plus récent est déployé. Vous avez également appris comment configurer le serveur pour exposer l’application Flask et accepter les demandes de manière sécurisée.

  5. Considérations de sécurité: Nous avons abordé les étapes de sécurité critiques pour protéger votre processus de déploiement:

    • Règles de pare-feu: Nous avons discuté de la configuration des règles de pare-feu pour limiter l’exposition et garantir que seul le trafic autorisé (provenant de Bitbucket) peut accéder à votre serveur.

    • Authentification: Nous avons ajouté une authentification basée sur des jetons pour garantir que seules les demandes autorisées peuvent déclencher des déploiements.

    • HTTPS: Nous avons expliqué comment sécuriser la communication entre votre serveur et Bitbucket en utilisant des certificats SSL de Let’s Encrypt.

    • Journalisation et surveillance: Enfin, nous avons recommandé de configurer la journalisation et la surveillance pour suivre toute activité inhabituelle ou erreurs.

Étapes suivantes

À la fin de ce tutoriel, vous disposez désormais d’un exemple fonctionnel d’un pipeline de déploiement automatisé. Bien qu’il s’agisse d’une implémentation de base, cela sert de fondation sur laquelle vous pouvez construire. À mesure que vous vous familiarisez avec CI/CD, vous pouvez explorer des sujets avancés tels que :

  • Pipelines de déploiement multi-étapes

  • Intégration avec des outils de conteneurisation comme Docker

  • Stratégies de test et de déploiement plus complexes

  • Utilisation d’outils d’orchestration comme Kubernetes pour le scalabilité

Les pratiques CI/CD évoluent continuellement, et en maîtrisant les bases, vous vous préparez au succès en élargissant vos compétences dans ce domaine. Bonne automatisation et merci de votre lecture !

Vous pouvez forker le code à partir d’ici.