Automatisation·

Optimisation des Déploiements Continus avec GitHub Actions

Découvrez comment GitHub Actions transforme le déploiement continu en automatisant les workflows avec efficience et scalabilité.
Optimisation des Déploiements Continus avec GitHub Actions

Introduction

GitHub Actions est devenu mon outil de CD principal depuis 2020, après avoir migré progressivement depuis Jenkins. Après avoir construit et optimisé des pipelines de déploiement continu sur des dizaines de projets -- de WizOps.fr (site vitrine) à Bloomflow (30+ microservices) en passant par F2R2 (infrastructure AWS multi-compte) -- j'ai développé des patterns d'optimisation éprouvés. Voici les techniques concrètes, avec les configurations précises et les chiffres de gain.

Le cache comme levier principal : de 8 minutes à 2 min 30

Le premier levier d'optimisation, et souvent le plus impactant, c'est le cache. Chez WizOps.fr, le build Docker du frontend Nuxt prenait 8 minutes sans aucun cache : téléchargement des dépendances pnpm, build Nuxt complet, construction de l'image Docker layer par layer. En activant trois niveaux de cache -- le cache pnpm via actions/setup-node avec l'option cache: pnpm, le cache Docker layers avec le mode cache-to et cache-from de Buildx utilisant le backend GitHub Actions cache, et le cache .nuxt/ -- le build est descendu à 2 minutes 30.

Chez Bloomflow, avec 30+ microservices, l'impact était encore plus spectaculaire. Le cache des dépendances Python (pip wheel cache) et Node (pnpm store) économisait 15 minutes par pipeline. Le cache Docker registry avec les layers intermédiaires permettait de ne rebuilder que les layers qui avaient changé -- typiquement, seules les layers de code applicatif changeaient, les layers de dépendances restaient en cache. Sur une journée intense avec 20 déploiements, c'est 5 heures de temps compute économisées et autant de temps de feedback gagné pour les développeurs.

Self-hosted runners : quand les runners GitHub ne suffisent plus

Les runners GitHub hébergés sont pratiques et gratuits (pour les repos publics) mais limités : 2 vCPU, 7 Go de RAM, et un disque partagé sans cache persistant entre les runs. Pour les builds Docker multi-plateforme ou les suites de tests volumineuses, c'est insuffisant. Le build Docker WizOps frontend + backend en multi-plateforme (AMD64 + ARM64) prenait 12 minutes sur un runner hébergé.

Chez F2R2, j'ai déployé des self-hosted runners sur des instances EC2 m5.xlarge (4 vCPU, 16 Go RAM). Le build Docker multi-plateforme est passé de 25 minutes à 8 minutes. Chez WizOps, le runner self-hosted sur un serveur dédié Scaleway offre des performances constantes et un cache Docker local persistant. L'astuce que j'ai développée : utiliser des runners éphémères avec des AMI pré-configurées (Docker, pnpm, Python déjà installés) pour avoir un environnement propre à chaque exécution tout en conservant le cache Docker local via un volume EBS persistant monté à chaque démarrage. Le meilleur des deux mondes : propreté et performance.

Environments GitHub : la gouvernance du CD

Les environments GitHub sont un outil puissant et sous-utilisé pour sécuriser le déploiement continu. Chez F2R2, l'environment production nécessitait l'approbation manuelle d'un lead technique avant le déploiement. L'environment staging se déployait automatiquement après merge sur main, sans approbation. Les secrets étaient scopés par environment : les credentials AWS de production n'étaient accessibles que dans le job qui ciblait l'environment production. Un workflow qui ciblait staging ne pouvait physiquement pas accéder aux credentials de prod.

Chez Bloomflow, j'ai ajouté des protection rules plus avancées. Le déploiement en production ne pouvait se faire qu'entre 9h et 17h en semaine (pas de déploiement le vendredi après 15h, pas de déploiement le week-end). L'environment production exigeait que tous les checks CI (lint, typecheck, tests) soient verts, et qu'au moins un reviewer ait approuvé la PR. Une branch protection rule empêchait les push directs sur main. Cette gouvernance par les environments élimine les déploiements accidentels : un développeur junior ne peut pas, même par erreur, déployer en production un code non reviewé à 23h un samedi.

Le pattern deploy-then-verify : détecter les régressions invisibles

Un pattern que j'applique systématiquement et qui a sauvé plusieurs situations critiques : déployer, puis vérifier automatiquement que le déploiement fonctionne, puis rollback automatique si ce n'est pas le cas. Le workflow GitHub Actions met à jour le tag image dans les Helm values du repo GitOps, attend qu'ArgoCD synchronise (vérification via argocd app wait ou polling de l'API ArgoCD), puis exécute des smoke tests HTTP contre l'environnement déployé.

Chez Padam Mobility, les smoke tests vérifiaient que l'API répondait en moins de 500ms, que l'endpoint de calcul de routes retournait un résultat valide pour un trajet test connu, et que l'endpoint de healthcheck retournait 200. Si un smoke test échouait, le workflow déclenchait automatiquement un rollback : git revert du commit de mise à jour des Helm values, push, ArgoCD resynchronise l'ancienne version. En 6 mois, ce pattern a détecté et rollback automatiquement 3 régressions qui auraient impacté les usagers. Le temps total entre le déploiement défaillant et le rollback complet : 3 minutes.

Parallélisation et actions composites : scalabilité du CD

Pour les monorepos ou les projets multi-composants, la parallélisation et la réutilisation sont essentielles. Chez WizOps.fr, le workflow utilise une matrix strategy pour builder le frontend et le backend en parallèle : deux jobs simultanés, chacun avec son Dockerfile, poussés vers GHCR avec des tags différents. Chez Bloomflow, la matrix construisait les 30+ services en parallèle, avec un concurrency group par service pour éviter les déploiements concurrents du même service. Le temps total de pipeline est passé de 45 minutes (séquentiel) à 12 minutes (parallèle avec 6 runners self-hosted).

Pour éviter la duplication entre ces workflows, j'utilise les composite actions : une composite action docker-build-push encapsule le login GHCR, le build Buildx multi-plateforme, le scan Trivy et le push en un seul step réutilisable. Ces composite actions vivent dans un repo .github versionné. Le résultat : les workflows de chaque service font 25 lignes au lieu de 200, sont lisibles par n'importe qui, et toute amélioration de la composite action bénéficie à tous les services simultanément.

Conclusion

L'optimisation des déploiements continus avec GitHub Actions repose sur des techniques concrètes et mesurables : cache multi-niveaux (de 8 à 2 min 30), runners self-hosted pour les builds lourds, environments avec protection rules pour la gouvernance, vérification post-déploiement avec rollback automatique, et parallélisation avec actions composites pour la scalabilité. Ces optimisations, affinées sur des dizaines de projets depuis 2020, transforment GitHub Actions d'un simple exécuteur de scripts YAML en une plateforme de CD robuste, performante et sécurisée.


RDV