Exercice 05 : Intégrer Terraform dans un pipeline CI/CD
🎯 Objectifs
À la fin de cet exercice, vous serez capable de :
- ✅ Configurer GitHub Actions avec
hashicorp/setup-terraform@v3 - ✅ Vérifier le formatage avec
terraform fmt -check - ✅ Sauvegarder un plan avec
terraform plan -out=tfplan - ✅ Poster le résultat du plan comme commentaire de PR
Durée estimée : 30 minutes
Difficulté : ⭐⭐⭐⭐⭐ (Avancé)
Prérequis : Compte GitHub, projet Terraform fonctionnel, exercices avancés 01-04 terminés
📖 Contexte
En équipe, les modifications Terraform doivent passer par une PR avec un plan visible. Un pipeline CI/CD garantit que le code est valide et formaté, que le plan est prévisualisé dans la PR pour revue, et que l'apply ne se déclenche que sur la branche principale après approbation.
📋 Énoncé
Vous allez créer deux workflows GitHub Actions : un workflow de validation et plan (déclenché sur PR), et un workflow d'apply (déclenché sur merge dans main).
Résultat attendu :
- Pipeline CI/CD Terraform complet
- Plan automatiquement commenté dans les PRs
🧭 Déroulement de l'exercice
Tâche 1 : Créer le workflow de validation
Créez .github/workflows/terraform-ci.yml qui se déclenche sur les PR et effectue fmt, validate et plan.
Indice :
on: pull_requestdéclenche le workflow à chaque PR. Les steps s'exécutent dans l'ordre.
Vérification : Ouvrir une PR déclenche le workflow. L'étape fmt -check échoue si le code n'est pas formaté.
Tâche 2 : Configurer les credentials AWS
Configurez les credentials AWS comme secrets GitHub pour le pipeline.
Indice :
Settings → Secrets → Actions: créezAWS_ACCESS_KEY_IDetAWS_SECRET_ACCESS_KEY. Utilisezenv:dans le step.
Vérification : Le step terraform init réussit avec le backend S3.
Tâche 3 : Générer et sauvegarder le plan
Ajoutez une étape qui génère le plan dans un fichier binaire et sauvegarde la sortie texte.
Indice :
terraform plan -out=tfplan+terraform show -no-color tfplanpour la sortie texte.
Vérification : L'artifact tfplan est disponible dans la liste des artifacts du workflow.
Tâche 4 : Poster le plan dans la PR
Utilisez l'API GitHub (via github-script ou l'action dédiée) pour poster le plan comme commentaire de la PR.
Indice : L'action
actions/github-scriptpermet d'appeler l'API GitHub avec du JavaScript. Capturez la sortie du plan dans une variable d'environnement.
Vérification : Un commentaire avec le plan Terraform apparaît automatiquement dans la PR.
Tâche 5 : Créer le workflow d'apply
Créez .github/workflows/terraform-apply.yml qui se déclenche uniquement sur push dans main et applique le plan.
Indice :
on: push: branches: [main]. L'apply doit utiliser-auto-approveou un plan sauvegardé.
Vérification : Merger la PR dans main déclenche l'apply automatique.
🗂️ Mini-Projet : Pipeline complet CI/CD Terraform
.github/
└── workflows/
├── terraform-ci.yml # PR : fmt + validate + plan + commentaire
└── terraform-apply.yml # main : apply automatiqueWorkflow CI (PR) :
# .github/workflows/terraform-ci.yml
name: Terraform CI
on:
pull_request:
branches: [main]
paths:
- "terraform/**"
- ".github/workflows/terraform-*.yml"
permissions:
contents: read
pull-requests: write
jobs:
terraform:
name: Terraform Plan
runs-on: ubuntu-latest
defaults:
run:
working-directory: terraform/
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: "~1.7"
- name: Terraform Format Check
id: fmt
run: terraform fmt -check -recursive
- name: Terraform Init
id: init
run: terraform init
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Terraform Validate
id: validate
run: terraform validate -no-color
- name: Terraform Plan
id: plan
run: terraform plan -no-color -out=tfplan 2>&1 | tee plan_output.txt
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Upload Plan
uses: actions/upload-artifact@v4
with:
name: tfplan
path: terraform/tfplan
- name: Comment PR with Plan
uses: actions/github-script@v7
with:
script: |
const fs = require('fs');
const plan = fs.readFileSync('terraform/plan_output.txt', 'utf8');
const maxLength = 65000;
const truncated = plan.length > maxLength
? plan.substring(0, maxLength) + '\n... (truncated)'
: plan;
github.rest.issues.createComment({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
body: `## Terraform Plan\n\`\`\`terraform\n${truncated}\n\`\`\``
});Workflow Apply (main) :
# .github/workflows/terraform-apply.yml
name: Terraform Apply
on:
push:
branches: [main]
paths:
- "terraform/**"
jobs:
terraform:
name: Terraform Apply
runs-on: ubuntu-latest
environment: production
defaults:
run:
working-directory: terraform/
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
with:
terraform_version: "~1.7"
- name: Terraform Init
run: terraform init
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Terraform Apply
run: terraform apply -auto-approve
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}Checkpoints :
- Ouvrir une PR → le workflow CI se déclenche automatiquement
- Code non formaté (
terraform fmt -check) → le workflow échoue avec le message d'erreur - Code valide → un commentaire avec le plan apparaît dans la PR
- Merger dans
main→ le workflow Apply se déclenche et exécuteterraform apply - Le
environment: productionnécessite une approbation manuelle configurée dans GitHub Settings