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.