Post

CI/CD avec GitHub Actions : déploys automatisés

CI/CD avec GitHub Actions : déploys automatisés

Si tu déploies encore en SSH à la main, c’est le moment de passer à la CI/CD. GitHub Actions est gratuit pour les repos publics et suffisant pour la plupart des projets. Voici des workflows concrets que j’utilise au quotidien.

CI/CD en 30 secondes

CI (Continuous Integration) : à chaque push, tester automatiquement le code. CD (Continuous Deployment) : si les tests passent, déployer automatiquement.

1
git push → Tests → Build → Deploy → Production

Workflow de base

.github/workflows/ci.yml :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
name: CI

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'
          cache: 'pip'

      - name: Install deps
        run: pip install -e ".[dev]"

      - name: Lint
        run: ruff check .

      - name: Test
        run: pytest -v

Build + Deploy Docker

.github/workflows/deploy.yml :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
name: Deploy

on:
  push:
    branches: [main]
    paths:
      - 'src/**'
      - 'Dockerfile'
      - 'docker-compose.yml'

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Build Docker image
        run: |
          docker build -t myapp:$ .
          docker tag myapp:$ myapp:latest

      - name: Deploy to server
        uses: appleboy/ssh-action@v1
        with:
          host: $
          username: $
          key: $
          script: |
            cd /opt/myapp
            docker compose pull
            docker compose up -d

Workflow multi-environnement

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
name: Deploy Staging → Production

on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: pytest -v

  deploy-staging:
    needs: test
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to staging
        run: echo "Deploying to staging..."
        # ... deploy commands

  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4
      - name: Deploy to production
        run: echo "Deploying to production..."
        # ... deploy commands

Secrets et variables

1
2
3
4
5
6
# Via l'interface GitHub
# Settings → Secrets and variables → Actions → New repository secret

# Ou via CLI
gh secret set SERVER_HOST --body "10.10.11.XX"
gh secret set SSH_KEY --body "$(cat ~/.ssh/id_ed25519)"
1
2
3
4
5
6
# Utilisation dans le workflow
- name: Deploy
  env:
    DB_URL: $
    API_KEY: $
  run: ./deploy.sh

Cache des dépendances

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Python — cache pip
- uses: actions/setup-python@v5
  with:
    python-version: '3.12'
    cache: 'pip'

# Node — cache npm
- uses: actions/setup-node@v4
  with:
    node-version: '20'
    cache: 'npm'

# Docker — cache des couches
- uses: docker/build-push-action@v5
  with:
    context: .
    push: false
    cache-from: type=gha
    cache-to: type=gha,mode=max

Scheduled workflows

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Backup quotidien à 3h du matin
name: Daily Backup

on:
  schedule:
    - cron: '0 3 * * *'

jobs:
  backup:
    runs-on: ubuntu-latest
    steps:
      - name: Backup database
        run: |
          ssh $ "pg_dump mydb | gzip > /backups/$(date +%Y%m%d).sql.gz"

Notifications

1
2
3
4
5
6
7
8
9
10
11
12
# Notification Telegram quand le deploy échoue
- name: Notify on failure
  if: failure()
  uses: appleboy/telegram-action@v1
  with:
    to: $
    token: $
    message: |
      ❌ Deploy failed!
      Repo: $
      Commit: $
      Author: $

Bonnes pratiques

  • Pin les versions : actions/checkout@v4 pas @main
  • Limite les permissions : permissions: contents: read par défaut
  • Path filters : ne pas rebuild si seuls les docs changent
  • Concurrency : annuler les runs précédents sur le même branch
  • Environment protection : require approval pour la prod
1
2
3
4
5
6
7
8
9
# Exemple de permissions minimales
permissions:
  contents: read
  packages: write

# Concurrency — un seul deploy par branch
concurrency:
  group: deploy-$
  cancel-in-progress: true

Références :

Tu veux mettre en place une CI/CD pour ton projet ? Contacte-moi.

This post is licensed under CC BY 4.0 by the author.