17 July 2025
Accompagner le lecteur dans la mise en place d’un pipeline CI/CD minimaliste mais fonctionnel pour une application Python, avec un déploiement automatique sur PyPI.
L’automatisation des processus de développement est devenue incontournable dans les projets modernes. Un pipeline CI/CD bien conçu permet non seulement de détecter les régressions tôt dans le cycle de développement, mais aussi d’automatiser entièrement le processus de déploiement.
Dans cet article, nous allons explorer comment mettre en place un pipeline complet avec GitHub Actions pour une application Python, de l’intégration continue (CI) au déploiement continu (CD) sur PyPI.
Notre pipeline se compose de deux workflows distincts :
CI Pipeline : Exécuté sur chaque push et pull request
CD Pipeline : Déclenché uniquement lors des releases GitHub
Le workflow CI est conçu pour valider chaque contribution au code. Voici sa configuration complète :
name: CI/CD Pipeline
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install ruff pytest pytest-mock
- name: Run Linting (Ruff)
run: ruff check .
- name: Run Tests (Pytest)
run: pytest
on
)on:
push:
branches:
- main
pull_request:
branches:
- main
Le pipeline se déclenche sur :
- Chaque push sur la branche main
- Chaque pull request vers main
Cette approche garantit que le code principal reste stable et que toute contribution est validée avant intégration.
runs-on: ubuntu-latest
Ubuntu Latest offre un bon compromis entre performance, coût et compatibilité pour la plupart des projets Python.
- name: Checkout code
uses: actions/checkout@v4
L’action checkout@v4
récupère le code source du repository. La version v4 apporte des améliorations de performance et de sécurité.
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
L’utilisation de '3.x'
permet d’automatiquement utiliser la dernière version stable de Python 3, simplifiant la maintenance.
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
pip install ruff pytest pytest-mock
Cette étape : - Met à jour pip vers la dernière version - Installe les dépendances du projet - Ajoute les outils de développement (linting et tests)
- name: Run Linting (Ruff)
run: ruff check .
Ruff est un linter Python ultra-rapide écrit en Rust. Il combine les fonctionnalités de plusieurs outils (Flake8, Black, isort) en un seul outil performant.
- name: Run Tests (Pytest)
run: pytest
Pytest exécute l’ensemble de la suite de tests, garantissant que les modifications n’introduisent pas de régressions.
Le workflow CD se déclenche uniquement lors des releases GitHub et automatise la publication sur PyPI :
name: Publish to PyPI
on:
release:
types:
- published
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.x'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install setuptools wheel twine
- name: Build and publish
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
run: |
python setup.py sdist bdist_wheel
twine upload dist/*
on:
release:
types:
- published
Le pipeline CD ne se déclenche que lors de la publication d’une release GitHub. Cette approche assure un contrôle précis des déploiements.
pip install setuptools wheel twine
setuptools : Outils de packaging Python
wheel : Format de distribution Python moderne
twine : Outil sécurisé pour uploader vers PyPI
env:
TWINE_USERNAME: __token__
TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }}
L’authentification utilise un token API PyPI stocké comme secret GitHub, plus sécurisé que les identifiants classiques.
run: |
python setup.py sdist bdist_wheel
twine upload dist/*
sdist
: Crée une distribution source
bdist_wheel
: Crée une wheel (distribution binaire)
twine upload
: Publie les distributions sur PyPI
Pour que le pipeline fonctionne, votre projet doit inclure un fichier setup.py
:
from setuptools import setup, find_packages
with open("README.adoc", "r", encoding="utf-8") as fh:
long_description = fh.read()
setup(
name="playlist-downloader",
version="1.0.0",
author="Votre Nom",
author_email="votre.email@example.com",
description="CLI tool for managing YouTube playlists",
long_description=long_description,
long_description_content_type="text/plain",
url="https://github.com/cheroliv/playlist-downloader",
packages=find_packages(),
classifiers=[
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
],
python_requires=">=3.8",
install_requires=[
"typer>=0.9.0",
"yt-dlp>=2023.1.6",
"google-api-python-client>=2.70.0",
"google-auth-oauthlib>=0.7.1",
"pymonad>=2.4.0",
"pyyaml>=6.0",
],
entry_points={
"console_scripts": [
"playlist-downloader=cli:app",
],
},
)
Métadonnées : Nom, version, auteur, description
Dépendances : Liste des packages requis
Entry Points : Commandes CLI exposées
Classifiers : Métadonnées pour PyPI
Créer un token API sur PyPI :
Connectez-vous à PyPI
Allez dans Account Settings > API tokens
Créez un nouveau token avec les permissions appropriées
Ajouter le secret dans GitHub :
Repository Settings > Secrets and variables > Actions
Créez un nouveau secret nommé PYPI_API_TOKEN
Collez votre token PyPI
Utilisez des tags Git sémantiques :
git tag -a v1.2.3 -m "Release version 1.2.3"
git push origin v1.2.3
Pour tester sur plusieurs versions Python :
strategy:
matrix:
python-version: [3.8, 3.9, "3.10", "3.11"]
Accélérez les builds avec le cache :
- name: Cache pip dependencies
uses: actions/cache@v3
with:
path: ~/.cache/pip
key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
Utilisez les environnements GitHub pour des déploiements contrôlés :
jobs:
deploy:
environment: production
runs-on: ubuntu-latest
GitHub Actions fournit des logs détaillés pour chaque étape. Pour débugger :
Examinez les logs de chaque step
Activez le debug avec ACTIONS_STEP_DEBUG
Utilisez des artifacts pour sauvegarder les fichiers de build
- name: Upload build artifacts
uses: actions/upload-artifact@v3
if: failure()
with:
name: build-logs
path: build/
Ajoutez des notifications Slack ou email :
- name: Notify on failure
if: failure()
uses: 8398a7/action-slack@v3
with:
status: ${{ job.status }}
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
La mise en place d’un pipeline CI/CD robuste avec GitHub Actions transforme radicalement l’expérience de développement. En automatisant le linting, les tests et le déploiement, vous :
Réduisez les erreurs en production
Accélérez les cycles de développement
Améliorez la confiance dans vos releases
Facilitez la collaboration en équipe
Ce pipeline peut être adapté à différents types de projets Python en ajustant les outils de linting, les frameworks de test, ou les destinations de déploiement.
L’investissement initial dans la configuration de ces workflows est rapidement rentabilisé par le gain de temps et la réduction des erreurs manuelles lors des déploiements.
✅ Pipeline fonctionnel atteint ! Vous avez désormais un pipeline CI/CD simple qui vous permet d’automatiser vos tests et de publier votre package Python sur PyPI directement depuis GitHub Actions.
Cependant, ce pipeline reste volontairement minimaliste. Il ne couvre pas encore certains aspects indispensables dans un contexte professionnel :
Tests multi-versions de Python,
Analyse de sécurité automatique,
Déploiement progressif via Test PyPI,
Surveillance et métriques du pipeline,
Automatisation du versioning et intégration des bonnes pratiques modernes (pyproject.toml).
Dans la prochaine partie, nous allons passer à l’étape supérieure. Vous apprendrez à transformer ce pipeline de base en une véritable chaîne de déploiement industrielle, robuste et sécurisée, prête pour des projets Python de production.