GitHub Actions tue lentement les équipes d’ingénierie
(iankduncan.com)- Largement utilisé parce qu’il s’agit d’une CI incluse par défaut dans le repo, mais son inefficacité structurelle et son expérience utilisateur instable nuisent à la productivité des développeurs
- Le chargement lent du visualiseur de logs et les plantages du navigateur, ainsi que la syntaxe YAML complexe et les erreurs d’expression, entraînent un débogage répétitif
- Une architecture où l’on ne possède pas les ressources de calcul montre ses limites en matière de performance, de scalabilité et de contrôle de l’environnement
- En cherchant à contourner ces problèmes, on finit souvent par reconstruire la CI elle-même avec du YAML complexe ou d’énormes scripts Bash
- À l’inverse, Buildkite propose, grâce à une structure YAML simple, des agents auto-hébergeables et une expérience de logs pragmatique, une alternative de CI soutenable sur le long terme
Les problèmes de GitHub Actions
- Le visualiseur de logs de GitHub Actions est inefficace : même pour vérifier une simple erreur, il faut plusieurs clics et chargements de page
- En cas d’échec d’un build, il faut passer de la page récapitulative des checks à la page d’exécution du workflow, puis à la page du job, puis cliquer sur une étape repliée, soit 3 à 4 changements de page, chacun avec son propre temps de chargement
- Sur de gros logs de build, il fait planter le navigateur de manière répétée, et l’utilisation de la recherche peut bloquer Chrome de façon reproductible
- Sur les logs longs, le défilement lui-même cesse de fonctionner, au point qu’il faut télécharger l’artefact de log brut et l’ouvrir dans un éditeur de texte
- Le bouton retour renvoie non pas à la page de PR d’origine, mais vers des pages d’interface GitHub Actions imprévisibles, remplissant l’historique du navigateur d’URL Actions
- Un processus de débogage improductif
- Pour vérifier des variables d’environnement, on ajoute une étape
run: envpuis on push à nouveau, ce qui crée une boucle de feedback de 20 minutes ; pour un simple changement d’une ligne, ce processus peut être répété une dizaine de fois - À force de répéter ces boucles de 20 minutes, une journée entière de travail finit absorbée par l’attente de la CI
- Pour vérifier des variables d’environnement, on ajoute une étape
- Les limites structurelles de YAML
- Le YAML de GitHub Actions est une forme particulière qui combine son propre langage d’expression, un modèle d’objets de contexte et des règles d’interpolation de chaînes
- Dans une expression
${{ }}, une simple erreur de guillemet peut faire attendre 4 minutes avant même que le runner ne démarre, pour découvrir ensuite qu’une chaîne a été perdue - La syntaxe des expressions se situe dans un entre-deux (liminal space) : trop complexe pour être de la simple configuration, trop limitée pour être un vrai langage de programmation
- On l’apprend non pas par la documentation, mais à travers l’expérience de l’échec
- Les risques de sécurité de la Marketplace
- Quand on importe une action externe avec
uses:, on accorde à un tiers non vérifié un accès au dépôt, aux secrets et à l’environnement de build - Il est possible d’épingler un SHA, mais peu de gens le font réellement ; et même dans ce cas, on exécute du code opaque non relu avec des droits d’accès à
GITHUB_TOKEN - La Marketplace mélange des actions maintenues par la communauté de qualité variable, composées pour la plupart de scripts shell et de Dockerfile
- La gestion des dépendances manque de transparence, avec un risque d’exécution de code non sûr
- Quand on importe une action externe avec
- Les contraintes de l’environnement de calcul
- Les runners par défaut de GitHub Actions sont des runners mutualisés appartenant à Microsoft, lents, limités en ressources et impossibles à personnaliser de manière significative
- Le coût des runners plus puissants est du niveau où la finance vous envoie une demande de réunion pour “en discuter”, sans pour autant donner le contrôle de l’environnement
- Il existe au moins six startups — Namespace, Blacksmith, Actuated, Runs-on, BuildJet notamment — spécialisées uniquement dans l’accélération des runners GitHub Actions, ce qui prouve à lui seul les insuffisances de l’environnement de calcul par défaut
- Mettre en place un self-hosted runner résout le problème du calcul, mais laisse intacts tous les autres : expressions YAML, modèle d’autorisations, Marketplace, visualiseur de logs, etc.
Des problèmes de détail, mais qui s’accumulent
actions/cache: les clés de cache sont déroutantes, les cache misses surviennent silencieusement, l’éviction reste opaque, et le temps passé à déboguer le cache dépasse celui qu’il est censé faire gagner- Workflows réutilisables : impossibilité de les imbriquer au-delà d’une certaine profondeur, pas d’accès propre au contexte du workflow appelant, pas de test isolé possible
- Le modèle de permissions
GITHUB_TOKEN:permissions: write-allest beaucoup trop large, et les autorisations fines forment un labyrinthe à cause des interactions entre paramètres au niveau du dépôt, du workflow et du job - Le contrôle de la concurrence (
concurrency) : annuler les exécutions en cours sur la même branche se fait en une ligne, mais aucun contrôle fin au-delà n’est prévu - Impossible d’utiliser des secrets dans les conditions
if: une exécution conditionnelle commeif: secrets.DEPLOY_KEY != ''est impossible ; c’est raisonnable du point de vue sécurité, mais cela oblige à contourner le problème quand on veut un workflow qui fonctionne à la fois sur un fork et sur le dépôt principal
Le piège du « faisons simplement un script Bash »
- Les ingénieurs fatigués du YAML de CI sont tentés de remplacer toute la logique par des scripts bash dans
run:, mais avec le temps s’y ajoutent conditions, fonctions, parsing d’arguments et parallélisation - Trois mois plus tard, on se retrouve avec 800 lignes de bash qui réimplémentent le parallélisme des jobs avec
waitet des fichiers PID, ainsi que leur propre logique de retry et de parsing de sortie - Au final, on n’a pas échappé au système de CI : on a simplement construit à la main en bash un pire système de CI, sans framework de test et que plus personne ne peut suivre
- Bash est adapté comme colle (glue), mais l’utiliser comme système de build ou test harness revient à déplacer la complexité d’un endroit avec garde-fous vers un autre qui en est dépourvu
L’approche alternative de Buildkite
-
Un visualiseur de logs fiable
- Le visualiseur de logs de Buildkite affiche correctement les logs sans faire planter le navigateur, en restituant tel quel le formatage ANSI et celui des frameworks de test
- Grâce à la fonctionnalité Annotation, les étapes de build peuvent afficher directement en Markdown sur la page du build un résumé des échecs de tests, un rapport de couverture ou des liens de déploiement
- Les agents s’exécutant sur votre propre infrastructure, il est possible de se connecter en SSH à la machine de build pour déboguer directement
-
Une structure YAML simple
- Le YAML de Buildkite est une structure de données pure qui décrit le pipeline, en déclarant seulement les étapes, les commandes et les plugins
- Quand une logique réelle est nécessaire, on l’écrit dans un vrai langage de programmation exécutable en local
- Cela maintient clairement la frontière : « l’orchestration dans la configuration, la logique dans le code », précisément la frontière que GitHub Actions brouille
-
Un contrôle total de l’environnement de calcul
- Les agents Buildkite existent sous forme d’un seul binaire et peuvent tourner aussi bien sur votre cloud, on-premise ou sur du matériel personnalisé
- On peut contrôler entièrement le type d’instance, le cache, le stockage local et le réseau, depuis de grosses instances EC2 avec SSD NVMe et 20 Go de cache de couches Docker jusqu’au Raspberry Pi
- Il n’existe pas d’industrie tierce du « Buildkite, mais plus rapide » : il suffit de lancer une machine plus grosse
- Pour un mainteneur individuel qui s’occupe d’une petite bibliothèque open source, l’offre gratuite de GitHub Actions sur les dépôts publics garde toute sa valeur
- Le texte vise surtout les équipes qui exploitent des systèmes de production, où le temps de CI se mesure en heures d’ingénierie perdues chaque semaine et où un build de 45 minutes coûte à la fois en calcul et en main-d’œuvre
- Dans ce contexte, le surcoût opérationnel des agents Buildkite est rapidement amorti
-
Prise en charge des pipelines dynamiques
- Dans Buildkite, les étapes du pipeline sont des données, et un script peut générer (emit) dynamiquement d’autres étapes au runtime puis les téléverser
- Dans un monorepo, cela permet de générer exactement les étapes de build et de test nécessaires à partir des fichiers modifiés, sans matrices codées en dur ni spaghetti de
if: contains(...) - Le
matrix, les conditionsifet les workflows réutilisables de GitHub Actions essaient de s’en approcher, mais finissent par construire une machine de Rube Goldberg dans un langage déclaratif à l’expressivité limitée
-
La simplicité de la structure des plugins
- Structurellement, c’est similaire à la Marketplace de GitHub Actions : on récupère du code depuis des dépôts tiers
- La différence est que les plugins Buildkite sont le plus souvent non pas des images Docker, mais de fins hooks shell, avec une surface réduite qu’on peut lire en entier en quelques minutes
- Comme tout s’exécute sur votre propre infrastructure, c’est l’utilisateur qui maîtrise le blast radius
-
Des détails pensés pour l’expérience utilisateur
- Buildkite permet d’afficher des emojis personnalisés (
:parrot:,:docker:, etc.) à côté des étapes du pipeline ; cela paraît anecdotique, mais montre une attention réelle à l’expérience produit - GitHub Actions donne l’impression d’un produit conçu par comité qui ne s’est jamais demandé : « est-ce agréable à utiliser ? »
- Buildkite permet d’afficher des emojis personnalisés (
Conclusion : comment choisir un système de CI
- GitHub Actions a conquis le marché grâce à son avantage d’outil intégré par défaut, avec la gratuité pour les dépôts publics, une intégration à une plateforme déjà utilisée par tout le monde, et un niveau « assez bon » (Good Enough)
- C’est un peu l’Internet Explorer de la CI : on continue à l’utiliser parce que le coût de migration est réel et que le temps est limité
- Buildkite est supérieur en termes de durabilité d’usage et d’expérience développeur
- Pour un projet open source simple, GitHub Actions suffit, mais dans un environnement de production à grande échelle, Buildkite est plus adapté
- Dans l’histoire des systèmes de CI, la part de marché revient non pas au meilleur système, mais à celui avec lequel il est le plus facile de démarrer
- GitHub Actions est la CI la plus facile pour commencer, Buildkite est la CI la meilleure pour continuer à utiliser, et à long terme c’est ce second critère qui compte
- Si l’outil de CI est structurellement conçu pour consommer le temps des développeurs, le problème n’est pas le développeur, mais bien l’outil lui-même
Aucun commentaire pour le moment.