First commit

This commit is contained in:
Johan
2025-12-19 10:07:55 +01:00
commit 0a1abf97f1
17 changed files with 2313 additions and 0 deletions

307
.github/workflows/ci-cd.yml vendored Normal file
View File

@@ -0,0 +1,307 @@
name: Déploiement sur AWS Elastic Beanstalk
on:
push:
# Déclenche le workflow uniquement sur des pushs vers la branche master
branches:
- master
jobs:
test:
name: CI - Tests et vérifications
runs-on: ubuntu-24.04
env:
SECRET_KEY: "key_for_testing"
steps:
# 1. Récupération du code
- name: 1. Récupérer le code
uses: actions/checkout@v5.0.0
# 2. Installation de Python
- name: 2. Mettre en place Python 3.13
uses: actions/setup-python@v6.0.0
with:
python-version: '3.13'
# 3. Installation de Poetry
- name: 3. Installer Poetry
run: pip install poetry==1.8.3
# 4. Installation des dépendances
- name: 4. Installer les dépendances
run: |
echo "Synchronisation du fichier poetry.lock..."
poetry lock --no-update
echo "Exportation des dépendances (y compris dev) vers requirements-dev.txt..."
poetry export --with dev -f requirements.txt --output requirements-dev.txt --without-hashes
echo "Installation via pip à partir de requirements-dev.txt..."
pip install -r requirements-dev.txt
# 5. Lancement des tests unitaires
- name: 5. Lancer les tests unitaires
run: poetry run pytest
# 6. DevSecOps - Vérifie la qualité et le style du code
- name: 6. Linter et Formater (Ruff)
run: |
echo "Vérification de la qualité du code..."
poetry run ruff check .
echo "Vérification du formatage du code..."
poetry run ruff format --check .
# 7. DevSecOps - Scanne le code Python pour les failles de sécurité courantes.
- name: 7. SAST - Analyse statique
run: |
echo "Analyse de sécurité statique (SAST) du code source (src/)..."
# Scan strict sur le code de l'application (src)
poetry run bandit -r src/
echo "Analyse de sécurité statique (SAST) du code de test (tests/)..."
# Scan des tests, en ignorant la règle B101 (assert_used)
# L'option -s (ou --skip) liste les règles à ignorer.
poetry run bandit -r tests/ -s B101
# 8. DevSecOps - Scanne les dépendances pour les vulnérabilités connues.
- name: 8. SCA - Scan des dépendances (Trivy)
# Utilise Trivy pour scanner le fichier poetry.lock à la recherche de CVEs
# et le code pour des secrets ou mauvaises configurations.
uses: aquasecurity/trivy-action@0.33.1
with:
scan-type: 'fs' # Scan du système de fichiers
scan-ref: '.' # Scanner le répertoire courant
ignore-unfixed: true # Ignorer les CVEs sans correctif connu
format: 'table' # Sortie facile à lire dans les logs
scanners: 'vuln,secret' # Activer le scan de vulnérabilités ET de secrets
# Fait échouer le build si une vulnérabilité HAUTE ou CRITIQUE est trouvée
severity: 'HIGH,CRITICAL'
# 9. DevSecOps - Scanne l'historique Git pour des secrets accidentellement commités.
- name: 9. Scan des secrets de l'historique Git (Gitleaks)
# Scanne tout l'historique Git pour des secrets (clés, mots de passe)
# qui auraient pu être commités puis supprimés.
uses: gitleaks/gitleaks-action@v2.3.9
deploy-python-aws-eb:
name: CD - Déploiement Python sur AWS EB
runs-on: ubuntu-24.04
env:
AWS_REGION: us-east-1 # Mettre la région de son environnement AWS Elastic Beanstalk "HelloWorldAPI-env"
EB_APPLICATION_NAME: "Hello World API" # doit matcher avec le nom de l'application dans l'environnement EB
EB_ENVIRONMENT_NAME: "HelloWorldAPI-env" # doit matcher avec le nom de l'environnement EB
needs: test
if: github.ref == 'refs/heads/master'
steps:
# 1. Récupération du code
- name: 1. Récupérer le code
uses: actions/checkout@v5.0.0
# 2. Installation de Python
- name: 2. Mettre en place Python 3.13
uses: actions/setup-python@v6.0.0
with:
python-version: '3.13'
# 3. Installation de nos outils
- name: 3. Installer Poetry et AWS CLI
run: |
pip install poetry==1.8.3
pip install awscli==1.42.59
# 4. Création du 'requirements.txt' dont EB a besoin
- name: 4. Exporter les dépendances (Poetry -> requirements.txt)
run: poetry export -f requirements.txt --output requirements.txt --without-hashes
# 5. Authentification auprès d'AWS
- name: 5. Configurer les identifiants AWS
uses: aws-actions/configure-aws-credentials@v5.1.0
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
# 6. Récupération dynamique de l'ID de compte
- name: 6. Récupérer l'ID de compte AWS
# Maintenant que nous sommes authentifiés, nous demandons à AWS "Qui suis-je ?".
# La commande 'aws sts get-caller-identity' renvoie l'ID du compte.
# '--query Account' filtre la réponse pour ne garder que l'ID.
# '--output text' le renvoie en texte brut.
run: |
echo "Récupération de l'ID de compte..."
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
echo "ID de compte trouvé : $ACCOUNT_ID"
# On stocke cet ID dans l'environnement GitHub pour les étapes suivantes
echo "AWS_ACCOUNT_ID=$ACCOUNT_ID" >> $GITHUB_ENV
# 7. Préparation des noms uniques
- name: 7. Définir les noms de version et de fichier
# On crée des variables uniques pour ce déploiement spécifique
run: |
# Crée une étiquette de version (ex: v-ffc6c4c...)
echo "VERSION_LABEL=v-${{ github.sha }}" >> $GITHUB_ENV
# Crée un nom de fichier unique (ex: deploy-ffc6c4c.zip)
echo "ZIP_FILE_NAME=deploy-${{ github.sha }}.zip" >> $GITHUB_ENV
# Construit le nom du bucket S3 d'EB en utilisant l'ID de compte de l'étape 6
echo "S3_BUCKET_NAME=elasticbeanstalk-${{ env.AWS_REGION }}-${{ env.AWS_ACCOUNT_ID }}" >> $GITHUB_ENV
# 8. Zippage du projet
- name: 8. Créer le paquet de déploiement (ZIP)
# On zippe tout le code (Procfile, src/, requirements.txt)
# On exclut les dossiers qui ne servent à rien sur le serveur
run: |
echo "Création du fichier ${{ env.ZIP_FILE_NAME }}..."
zip -r ${{ env.ZIP_FILE_NAME }} . -x ".git/*" ".github/*" "*.idea/*" "*.vscode/*"
# 9. Envoi du code sur S3
- name: 9. Envoyer le paquet sur S3
# Elastic Beanstalk déploie depuis S3. On doit y copier notre ZIP.
run: |
echo "Envoi sur s3://${{ env.S3_BUCKET_NAME }}/${{ env.ZIP_FILE_NAME }}"
aws s3 cp ${{ env.ZIP_FILE_NAME }} s3://${{ env.S3_BUCKET_NAME }}/${{ env.ZIP_FILE_NAME }}
# 10. Informer EB qu'une nouvelle version existe
- name: 10. Créer la nouvelle version de l'application
# On dit à EB : "Voici une nouvelle version (VERSION_LABEL),
# son code source est à cet emplacement S3 (source-bundle)"
run: |
echo "Création de la version ${{ env.VERSION_LABEL }}..."
aws elasticbeanstalk create-application-version \
--application-name "${{ env.EB_APPLICATION_NAME }}" \
--version-label "${{ env.VERSION_LABEL }}" \
--source-bundle S3Bucket="${{ env.S3_BUCKET_NAME }}",S3Key="${{ env.ZIP_FILE_NAME }}" \
--description "Déploiement depuis GitHub Actions (SHA: ${{ github.sha }})"
# 11. Donner l'ordre de déploiement
- name: 11. Lancer la mise à jour de l'environnement
# C'est l'ordre final. On dit à EB :
# "Prends cette nouvelle version (VERSION_LABEL) et applique-la
# à cet environnement (EB_ENVIRONMENT_NAME)"
run: |
echo "Mise à jour de l'environnement ${{ env.EB_ENVIRONMENT_NAME }}..."
aws elasticbeanstalk update-environment \
--environment-name "${{ env.EB_ENVIRONMENT_NAME }}" \
--version-label "${{ env.VERSION_LABEL }}"
deploy-docker-aws-eb:
name: CD - Déploiement Docker sur AWS EB
runs-on: ubuntu-24.04
env:
AWS_REGION: us-east-1 # Mettre la même région
EB_APPLICATION_NAME: "Hello World API" # doit matcher avec le nom de l'application dans l'environnement EB
EB_ENVIRONMENT_NAME: "HelloWorldAPI-env-docker" # doit matcher avec le nom du NOUVEL environnement EB
ECR_REPOSITORY: "mynamespace/hello-world-api" # Le nom du dépôt ECR
needs: test # Dépend aussi du job 'test'
if: github.ref == 'refs/heads/master'
steps:
# 1. Récupération du code
- name: 1. Récupérer le code
uses: actions/checkout@v5.0.0
# 2. Configurer les identifiants AWS (Nécessaire pour ECR et EB)
- name: 2. Configurer les identifiants AWS
uses: aws-actions/configure-aws-credentials@v5.1.0
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ${{ env.AWS_REGION }}
# 3. Récupération dynamique de l'ID de compte
- name: 3. Récupérer l'ID de compte AWS
run: |
echo "Récupération de l'ID de compte..."
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
echo "ID de compte trouvé : $ACCOUNT_ID"
echo "AWS_ACCOUNT_ID=$ACCOUNT_ID" >> $GITHUB_ENV
# 4. Se connecter à Amazon ECR
- name: 4. Se connecter à Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v2.0.1
# 5. Définir les variables de l'image Docker
- name: 5. Définir les variables de l'image
run: |
# Récupère l'URI du registre ECR (ex: 123456789.dkr.ecr.us-east-1.amazonaws.com)
echo "ECR_REGISTRY=${{ steps.login-ecr.outputs.registry }}" >> $GITHUB_ENV
# Construit le nom complet de l'image avec le tag (SHA du commit)
echo "ECR_IMAGE_NAME=${{ steps.login-ecr.outputs.registry }}/${{ env.ECR_REPOSITORY }}:${{ github.sha }}" >> $GITHUB_ENV
# 6. Builder, tagger et pousser l'image Docker sur ECR
- name: 6. Builder et Pousser l'image Docker
run: |
echo "Build de l'image : ${{ env.ECR_IMAGE_NAME }}"
docker build -t ${{ env.ECR_IMAGE_NAME }} .
echo "Push de l'image vers ECR..."
docker push ${{ env.ECR_IMAGE_NAME }}
# 7. Générer le fichier Dockerrun.aws.json
# Ce fichier dit à EB quelle image ECR utiliser et quel port exposer
- name: 7. Générer le Dockerrun.aws.json
run: |
echo "Génération du Dockerrun.aws.json..."
# Crée le fichier JSON
echo '{' > Dockerrun.aws.json
echo ' "AWSEBDockerrunVersion": "1",' >> Dockerrun.aws.json
echo ' "Image": {' >> Dockerrun.aws.json
echo ' "Name": "${{ env.ECR_IMAGE_NAME }}",' >> Dockerrun.aws.json
echo ' "Update": "true"' >> Dockerrun.aws.json
echo ' },' >> Dockerrun.aws.json
echo ' "Ports": [' >> Dockerrun.aws.json
echo ' {' >> Dockerrun.aws.json
echo ' "ContainerPort": 8000' >> Dockerrun.aws.json
echo ' }' >> Dockerrun.aws.json
echo ' ]' >> Dockerrun.aws.json
echo '}' >> Dockerrun.aws.json
echo "Contenu du Dockerrun.aws.json :"
cat Dockerrun.aws.json
# 8. Préparation des noms uniques (pour le zip S3)
- name: 8. Définir les noms de version et de fichier
run: |
echo "VERSION_LABEL=v-docker-${{ github.sha }}" >> $GITHUB_ENV
# Le zip ne contiendra QUE le Dockerrun.aws.json
echo "ZIP_FILE_NAME=deploy-docker-${{ github.sha }}.zip" >> $GITHUB_ENV
echo "S3_BUCKET_NAME=elasticbeanstalk-${{ env.AWS_REGION }}-${{ env.AWS_ACCOUNT_ID }}" >> $GITHUB_ENV
# 9. Zippage du Dockerrun.aws.json
- name: 9. Créer le paquet de déploiement (ZIP)
# Pour la plateforme Docker, le "source bundle" est juste le Dockerrun.aws.json
run: |
echo "Création du fichier ${{ env.ZIP_FILE_NAME }}..."
zip -r ${{ env.ZIP_FILE_NAME }} Dockerrun.aws.json
# 10. Envoi du paquet sur S3
- name: 10. Envoyer le paquet sur S3
run: |
echo "Envoi sur s3://${{ env.S3_BUCKET_NAME }}/${{ env.ZIP_FILE_NAME }}"
aws s3 cp ${{ env.ZIP_FILE_NAME }} s3://${{ env.S3_BUCKET_NAME }}/${{ env.ZIP_FILE_NAME }}
# 11. Informer EB qu'une nouvelle version existe
- name: 11. Créer la nouvelle version de l'application
run: |
echo "Création de la version ${{ env.VERSION_LABEL }}..."
aws elasticbeanstalk create-application-version \
--application-name "${{ env.EB_APPLICATION_NAME }}" \
--version-label "${{ env.VERSION_LABEL }}" \
--source-bundle S3Bucket="${{ env.S3_BUCKET_NAME }}",S3Key="${{ env.ZIP_FILE_NAME }}" \
--description "Déploiement Docker depuis GitHub Actions (SHA: ${{ github.sha }})"
# 12. Attendre qu'EB traite la nouvelle version
- name: 12. Attendre le traitement de la version par AWS
run: |
echo "Pause de 60 secondes pour laisser à AWS le temps de traiter la version..."
sleep 60
# 12. Donner l'ordre de déploiement
- name: 12. Lancer la mise à jour de l'environnement
run: |
echo "Mise à jour de l'environnement DOCKER ${{ env.EB_ENVIRONMENT_NAME }}..."
aws elasticbeanstalk update-environment \
--environment-name "${{ env.EB_ENVIRONMENT_NAME }}" \
--version-label "${{ env.VERSION_LABEL }}"