- Version : GitHub Actions (runner v2.334.0) — gratuit pour les dépôts publics, 2 000 min/mois pour les privés
- Ce qu'il faut faire : Créer
.github/workflows/ci.ymlavec les jobs test et deploy, configurer les 4 secrets GitHub (VPS_HOST, VPS_USER, VPS_SSH_KEY, CODECOV_TOKEN) - Piège fréquent : Oublier de configurer les secrets GitHub → le deploy échoue avec
"Permission denied (publickey)" - Délai : 20 minutes pour un projet Python existant
Introduction
Vous allez construire un pipeline CI/CD complet avec GitHub Actions qui teste automatiquement votre code Python à chaque push, exécute les tests, vérifie la couverture et déploie sur un serveur VPS — le tout gratuit pour les dépôts publics (2 000 minutes/mois pour les dépôts privés). Documentation officielle GitHub Actions.
Ce que vous allez construire et pourquoi en 2026
Un workflow GitHub Actions qui : 1) installe les dépendances Python, 2) lance les tests avec pytest, 3) vérifie le linting avec ruff, 4) déploie automatiquement sur votre VPS via SSH si les tests passent. Prérequis : un dépôt GitHub (public ou private), Python 3.10+, et un VPS avec accès SSH. Temps estimé : 20 minutes. GitHub Actions est gratuit pour les dépôts publics et offre 2 000 minutes/mois pour les dépôts privés (Linux x64 à 0,002 $/minute au-delà).
Installation : commandes exactes à copier
# Cloner votre dépôt (si pas déjà fait)
git clone https://github.com/votre-compte/votre-projet.git
cd votre-projet # Créer la structure du workflow
mkdir -p .github/workflows # Installer pytest et ruff localement pour tester
pip install pytest ruff pytest-covRésultat attendu : le dossier .github/workflows/ est créé, prêt à recevoir le fichier YAML du workflow. Erreur courante : "Permission denied" sur mkdir → vérifiez que vous êtes dans le bon dépôt git et que le dossier n'est pas en lecture seule.
Configuration : les fichiers et variables à définir
Créez le fichier .github/workflows/ci.yml :
name: CI/CD Pipeline on: push: branches: [main, develop] pull_request: branches: [main] jobs: test: runs-on: ubuntu-latest strategy: matrix: python-version: ["3.10", "3.11", "3.12"] steps: - name: Checkout le code uses: actions/checkout@v4 - name: Configurer Python ${{ matrix.python-version }} uses: actions/setup-python@v5 with: python-version: ${{ matrix.python-version }} cache: "pip" - name: Installer les dépendances run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install pytest pytest-cov ruff - name: Linting avec ruff run: ruff check . - name: Lancer les tests run: pytest --cov=src --cov-report=xml --cov-report=term-missing - name: Upload couverture uses: codecov/codecov-action@v4 with: token: ${{ secrets.CODECOV_TOKEN }} deploy: needs: test runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' && github.event_name == 'push' steps: - name: Déployer sur le VPS uses: appleboy/ssh-action@v1 with: host: ${{ secrets.VPS_HOST }} username: ${{ secrets.VPS_USER }} key: ${{ secrets.VPS_SSH_KEY }} script: | cd /var/www/votre-projet git pull origin main pip install -r requirements.txt sudo systemctl restart votre-projetLes secrets VPS_HOST, VPS_USER, VPS_SSH_KEY et CODECOV_TOKEN se configurent dans GitHub : Settings → Secrets and variables → Actions → New repository secret. La clé SSH doit être au format PEM (pas le format OpenSSH) — générez-la avec ssh-keygen -t ed25519 -m PEM -f deploy_key.
Le code du projet : construire la fonctionnalité principale
Pour que le pipeline fonctionne, votre projet doit avoir ces fichiers minimum :
# requirements.txt
fastapi>=0.110.0
uvicorn>=0.29.0
pytest>=8.0.0
pytest-cov>=5.0.0
ruff>=0.4.0# tests/test_app.py
from fastapi.testclient import TestClient
from src.app import app client = TestClient(app) def test_homepage(): response = client.get("/") assert response.status_code == 200 assert "Bienvenue" in response.json()["message"] def test_health_check(): response = client.get("/health") assert response.status_code == 200 assert response.json()["status"] == "ok"# src/app.py
from fastapi import FastAPI app = FastAPI(title="Mon Projet", version="1.0.0") @app.get("/")
def homepage(): return {"message": "Bienvenue sur Mon Projet"} @app.get("/health")
def health_check(): return {"status": "ok"}Le workflow teste votre code sur 3 versions de Python (3.10, 3.11, 3.12) en parallèle grâce à la matrix. Si tous les tests passent sur main, le job deploy se déclenche automatiquement et pousse le code sur votre VPS via SSH.
Tester et valider que ça fonctionne
# Committer et pousser le workflow
git add .github/workflows/ci.yml requirements.txt tests/ src/
git commit -m "Ajout du pipeline CI/CD avec GitHub Actions"
git push origin mainAllez sur https://github.com/votre-compte/votre-projet/actions — vous devez voir le workflow "CI/CD Pipeline" s'exécuter avec 3 jobs de test (un par version de Python) et 1 job de déploiement. Si un job échoue, cliquez dessus pour voir les logs détaillés. Erreur courante : "ModuleNotFoundError" → vérifiez que requirements.txt contient toutes les dépendances nécessaires. Si le déploiement échoue avec "Permission denied (publickey)" → vérifiez que le secret VPS_SSH_KEY contient la clé privée complète (y compris les lignes BEGIN/END).
Déployer et utiliser en production
Pour un déploiement plus robuste, ajoutez ces étapes au job deploy :
- name: Vérifier la santé après déploiement run: | sleep 5 curl -f http://${{ secrets.VPS_HOST }}:8000/health || exit 1 - name: Rollback en cas d'échec if: failure() uses: appleboy/ssh-action@v1 with: host: ${{ secrets.VPS_HOST }} username: ${{ secrets.VPS_USER }} key: ${{ secrets.VPS_SSH_KEY }} script: | cd /var/www/votre-projet git reset --hard HEAD~1 sudo systemctl restart votre-projetPour limiter les coûts, ajoutez un timeout global dans le workflow : jobs: test: timeout-minutes: 15. Un job Python moyen consomme 3-5 minutes, soit environ 0,01 $ par push sur un dépôt privé. Pour surveiller la consommation, allez sur github.com/settings/billing.
Aller plus loin : 3 extensions concrètes
1. Ajouter un cache Docker pour accélérer les builds — Utilisez actions/cache@v4 avec path: ~/.cache/docker pour cacher les layers Docker entre les builds. Réduction du temps de build de 50% en moyenne. Ajoutez dans votre workflow : - uses: actions/cache@v4 with: path: ~/.cache/docker key: docker-${{ hashFiles('Dockerfile') }}.
2. Déployer automatiquement sur Vercel ou Railway — Remplacez le job deploy par uses: amondnet/vercel-action@v25 avec vercel-token: ${{ secrets.VERCEL_TOKEN }}. Pour Railway : uses: railwayapp/railway-action@v1 avec railway-token: ${{ secrets.RAILWAY_TOKEN }}. Voir docs.github.com/en/actions/deployment.
3. Ajouter un scan de sécurité avec Dependabot — Créez .github/dependabot.yml avec package-ecosystem: pip et schedule: interval: weekly. Dependabot ouvre automatiquement des PR pour les dépendances vulnérables. Voir docs.github.com/en/code-security/dependabot.
Étapes à suivre5
Étape 1 — Créer le dépôt et la structure du workflow
Créez un dépôt GitHub ou clonez un projet existant avecgit clone https://github.com/votre-compte/votre-projet.git. Organisez votre projet avec les dossiers standards :mkdir -p .github/workflows tests src. Le dossier.github/workflows/est l’emplacement obligatoire pour tous vos fichiers YAML de pipelines — GitHub Actions les détecte automatiquement à chaque push. Installez les dépendances de test dans un environnement virtuel isolé :python3 -m venv venv && source venv/bin/activate && pip install pytest pytest-cov ruff. Créez un fichierrequirements.txtavecpip freeze > requirements.txtpour verrouiller les versions. Vérifiez que pytest fonctionne :pytest --versiondoit afficher 8.0+. Si"No module named pytest", vérifiez que votre environnement virtuel est activé avecwhich python— il doit pointer vers votre venv, pas vers le Python système. Ajoutez un fichiertests/test_main.pyminimal avecdef test_health(): assert Truepour que le pipeline ait au moins un test à exécuter dès le premier push. Structure recommandée :requirements.txtà la racine,src/pour le code applicatif,tests/pour les tests unitaires, et.github/workflows/ci.ymlpour le pipeline. Voir la documentation GitHub sur la gestion des dépôts.Étape 2 — Configurer les secrets GitHub pour le déploiement
Allez sur votre dépôt GitHub → Settings → Secrets and variables → Actions → New repository secret. Ajoutez 4 secrets :VPS_HOST(l’IP de votre serveur, ex:203.0.113.50),VPS_USER(l’utilisateur SSH, ex:deploy),VPS_SSH_KEY(la clé privée ED25519 au format PEM), etCODECOV_TOKEN(optionnel, pour la couverture de code). Pour générer la clé SSH :ssh-keygen -t ed25519 -m PEM -f deploy_keysur votre machine locale, puis ajoutez la clé publique (deploy_key.pub) dans~/.ssh/authorized_keyssur le VPS avecssh-copy-id -i deploy_key.pub deploy@203.0.113.50. Copiez le contenu dedeploy_key(la clé privée) dans le secret VPS_SSH_KEY — y compris les lignes-----BEGINet-----END. Testez la connexion :ssh -i deploy_key deploy@203.0.113.50doit réussir sans mot de passe. Important : ne jamais committer la clé privée dans le dépôt — ajoutezdeploy_keyau.gitignore. Pour renforcer la sécurité, configurezAllowlistdans les paramètres du dépôt pour limiter les secrets aux workflows autorisés uniquement. Voir la documentation GitHub sur les secrets Actions.Étape 3 — Écrire le workflow CI/CD complet
Créez.github/workflows/ci.ymlavec 2 jobs :test(lance pytest sur 3 versions de Python via une matrix) etdeploy(déploie via SSH si les tests passent sur la branche main). Voici la structure complète du fichier. En-tête YAML :name: CI/CD Pipelinepuison: { push: { branches: [main] }, pull_request: { branches: [main] } }. Le jobtestutiliseactions/checkout@v4,actions/setup-python@v5avecpython-version: ["3.10", "3.11", "3.12"]et cache pip viacache: "pip", puis lanceruff check .pour le linting etpytest --cov --cov-report=xmlpour les tests avec couverture. Le jobdeployutiliseappleboy/ssh-action@v1avec les secrets configurés à l’étape 2 :host: ${{ secrets.VPS_HOST }},username: ${{ secrets.VPS_USER }},key: ${{ secrets.VPS_SSH_KEY }}. Les commandes de déploiement :cd /var/www/votre-projet && git pull origin main && pip install -r requirements.txt && sudo systemctl restart votre-projet. La conditionif: github.ref == "refs/heads/main"empêche le déploiement sur les PR et les autres branches. Ajoutezneeds: testsur le job deploy pour garantir que les tests passent avant tout déploiement. Voir la documentation GitHub sur les workflows.Étape 4 — Tester le pipeline et déboguer les échecs
Poussez le workflow :git add .github/workflows/ci.yml && git commit -m "Ajout CI/CD" && git push origin main. Allez surgithub.com/votre-compte/votre-projet/actionspour voir l’exécution en temps réel — chaque job affiche ses logs avec les étapes colorées (vert = succès, rouge = échec). Si un job échoue, cliquez dessus pour voir les logs détaillés. Erreurs fréquentes et solutions :"ModuleNotFoundError"→ ajoutez le package manquant dansrequirements.txtet relancez."Permission denied (publickey)"→ vérifiez que le secret VPS_SSH_KEY contient la clé privée complète avec les lignes BEGIN/END, sans espaces supplémentaires."Host key verification failed"→ ajoutezscript_stop: trueetdebug: truedans la config ssh-action pour voir les détails de connexion."pytest exit code 1"→ un test échoue en local aussi : lancezpytest -vpour identifier le test en cause avant de repousser. Pour les erreurs intermittentes (timeout réseau), ajoutezretry-attempts: 3dans ssh-action. Activez les notifications GitHub : Settings → Notifications → Actions pour recevoir un email à chaque échec. Voir la documentation de troubleshooting GitHub Actions.Étape 5 — Ajouter le health check et le rollback automatique
Ajoutez une étape de vérification après le déploiement dans le job deploy :curl -f http://${{ secrets.VPS_HOST }}:8000/health || exit 1avec unsleep 5avant pour laisser le service démarrer. Le flag-fde curl fait échouer la commande si le serveur retourne un code HTTP 4xx ou 5xx. Ajoutez un job de rollback conditionnel dans le même fichier :if: failure()qui exécutecd /var/www/votre-projet && git reset --hard HEAD~1 && sudo systemctl restart votre-projetsur le VPS. Ce job ne se déclenche que si le job deploy échoue, restaurant automatiquement la version précédente. Pour limiter les coûts GitHub Actions (2 000 minutes/mois gratuits pour les dépôts privés), ajouteztimeout-minutes: 15au niveau de chaque job. Un job Python moyen consomme 3-5 minutes. Pour surveiller la consommation :github.com/settings/billing. Pour déclencher manuellement le workflow (utile en cas de rollback), ajoutezworkflow_dispatch:dans la sectionon:. Vous pouvez aussi ajouter un cache pour accélérer les builds :actions/cache@v4avecpath: ~/.cache/pipetkey: pip-${{ runner.os }}-${{ hashFiles("requirements.txt") }}. Voir la documentation GitHub sur le déploiement.
Conseils pratiques
- Utilisez
cache: "pip"dansactions/setup-python@v5— cela réduit le temps d'installation des dépendances de 60% en moyenne en cahant le cache pip entre les runs. - Ajoutez
timeout-minutes: 15au niveau de chaque job — un workflow qui tourne indéfiniment consomme vos minutes GitHub Actions. 15 minutes est un bon compromis pour un projet Python standard. - Testez votre workflow avec
workflow_dispatchavant de le pousser sur main — ajoutezworkflow_dispatch:dans la sectionon:pour déclencher manuellement depuis l'onglet Actions du dépôt.
Points d'attention
- Erreur
"Permission denied (publickey)"au déploiement → vérifiez que le secret VPS_SSH_KEY contient la clé privée complète, y compris les lignes-----BEGIN OPENSSH PRIVATE KEY-----et-----END OPENSSH PRIVATE KEY-----. Les sauts de ligne doivent être préservés. - Erreur
"ModuleNotFoundError: No module named X"dans les tests → vérifiez querequirements.txtcontient toutes les dépendances, y compris les packages de test (pytest, ruff). Lancezpip freeze > requirements.txtpour les capturer automatiquement. - Erreur
"fatal: could not read Username for 'https://github.com'"→ GitHub Actions checkout utilise le token GITHUB_TOKEN automatiquement pour les dépôts publics. Pour un dépôt privé, vérifiez que le workflow a la permissioncontents: read(par défaut) et que le token n'a pas expiré.
Questions fréquentes5
GitHub Actions fonctionne-t-il avec les dépôts privés ?
Oui. Les dépôts privés bénéficient de 2 000 minutes/mois gratuitement (plan Free), 3 000 minutes/mois (plan Pro), et 50 000 minutes/mois (Enterprise). Au-delà, le coût est de 0,002 $/minute pour Linux x64, 0,010 $/minute pour Windows et 0,062 $/minute pour macOS.
Quelle version de Python est nécessaire pour GitHub Actions ?
actions/setup-python@v5. La matrice recommandée teste sur 3.10, 3.11 et 3.12 pour une couverture maximale. Python 3.13 est supporté mais certaines dépendances peuvent ne pas être encore compatibles.GitHub Actions est-il gratuit ?
Oui pour les dépôts publics (minutes illimitées). Pour les dépôts privés : 2 000 minutes/mois sur le plan Free, 3 000 sur Pro, 50 000 sur Enterprise. Un workflow Python typique consomme 3-5 minutes par push, soit environ 400 à 600 runs/mois sur le plan Free.
Comment débugger un workflow GitHub Actions qui échoue ?
- name: Debug run: env | sort dans un step pour afficher toutes les variables d'environnement. Activez le debug SSH en ajoutant les secrets ACTIONS_RUNNER_DEBUG=true et ACTIONS_STEP_DEBUG=true pour des logs verbeux.GitHub Actions vs GitLab CI : lequel choisir ?
GitHub Actions est intégré nativement à GitHub avec 20 000+ actions pré-construites — idéal si votre code est déjà sur GitHub. GitLab CI offre un fichier .gitlab-ci.yml plus flexible et des runners Docker natifs. Choisissez GitHub Actions si vous êtes sur GitHub (zéro configuration supplémentaire), GitLab CI si votre infrastructure est sur GitLab.
Guides Technologie & IA
Voir toutConstruire un chatbot local avec Ollama et Python en 30 minutes
Utiliser DeepSeek V4 en 2026 pour améliorer la recherche
Utiliser Claude Opus 4.7 en 2026 pour améliorer la productivité
Comment créer et gérer ses mots de passe de manière sécurisée en 2026
Reconnaître un deepfake en 2026 — Comment ça marche
Poursuivez votre lecture
Multi-catégories"Impôts du Cœur" : les agents des finances publiques proposent leur aide à la déclaration de revenus sur le marché
Comment refuser un loyer supérieur à 30 % du revenu en 2026 ?
Comment créer et utiliser son identité numérique avec FranceConnect en 2026
Automatiser ses emails avec Python et l'API Gmail en 2026
Utiliser Qwen 3 en local avec Ollama : guide complet 2026
Transmission d'entreprise 2026 : dispositifs fiscaux et étapes clés pour vendre ou céder son affaire
Équipe éditoriale GuidePratiquefr
Rédacteurs spécialisés en droit, fiscalité et finances
Rédigé et vérifié par notre équipe de rédacteurs spécialisés. Sources officielles consultées : service-public.fr, legifrance.gouv.fr, impots.gouv.fr, ameli.fr. Dernière vérification : 14 mai 2026.
Sources officielles consultées
Les informations contenues dans ce guide sont fournies à titre indicatif et ne remplacent pas un conseil professionnel personnalisé.