Je déteste vraiment GitHub Actions
(xlii.space)- Partage de l’expérience frustrante d’un développeur face à la boucle de feedback lente et au débogage complexe de GitHub Actions
- Dans le projet tmplr, la documentation était générée avec CUE via
build.rs, mais les échecs du build CI ont déclenché le problème - Sur 4 plateformes, seul Linux ARM échouait au build ; la cause était le comportement de GitHub Actions qui masque les binaires x86_64 sur un runner arm64 lors d’un cross build
- Une boucle de feedback inefficace où 2 à 3 minutes étaient nécessaires pour tester une seule modification
- Solution adoptée : suppression de
build.rset passage à un GNU Makefile, afin de contrôler directement la logique CI et de résoudre le problème
Contexte du problème
- tmplr est un outil de scaffolding de fichiers/projets qui utilise des fichiers de template lisibles et modifiables par des humains
build.rsutilisait CUE pour générerREADME.md,CHANGELOG.mdainsi que les fichiers de version et d’aide, afin de garantir la cohérence- Le travail en lui-même a été terminé en environ 1,5 heure, et l’article associé était également déjà rédigé
- Tout fonctionnait en local, mais dans l’environnement CI de GitHub Actions, le build a échoué parce que le binaire CUE n’était pas installé
Cause de l’échec du build
- Parmi 4 plateformes (Linux ARM, macOS ARM, Linux x86_64, macOS x86_64), seul Linux ARM produisait une erreur « command not found »
- Cause : le matrix cross build est fortement isolé, si bien que CUE n’était installé que sur l’hôte Linux x86_64 et l’hôte macOS ARM
- Sur macOS, exécuter un binaire x86_64 ne pose pas de problème
- Sur Linux x86_64 non plus, exécuter un binaire x86_64 ne pose pas de problème
- En revanche, GitHub Actions masque les binaires x86_64 sur un runner arm64, les rendant impossibles à exécuter
Une boucle de feedback inefficace
- Processus répété pour tenter de résoudre le problème :
1. chercher des corrections possibles
2. modifierci.yml
3. commit et push (jj squash --ignore-immutable && jj git push)
4. ouvrir l’onglet « Actions »
5. ouvrir la dernière exécution
6. ouvrir l’exécution Linux ARM
7. attendre quelques secondes
8. frustration
9. recommencer - 2 à 3 minutes étaient nécessaires par modification
- Dans l’idéal, GitHub fournirait soit un runner local complet, soit une fonction permettant de vérifier rapidement la progression après un push
- Une fonctionnalité du type « scratch commit » : un moyen de tester différentes exécutions sans polluer l’historique Git ni l’historique des exécutions Actions
- Mais à ce jour, une telle fonction n’existe pas
Solution
- Après avoir répété cette boucle pendant 30 minutes, arrêt
- Application d’une méthode bien connue sur Internet : « ne laissez pas GitHub Actions gérer la logique ; contrôlez directement le script et laissez Actions se contenter de l’appeler »
- Suppression de
build.rs(à regret, mais le sacrifice était nécessaire) - Déplacement de toutes les tâches de génération dans un GNU Makefile
- Commit des fichiers générés dans le dépôt et annulation des changements CI
- Problème résolu
Conclusion
- GitHub Actions empêche parfois de bénéficier de certaines bonnes approches
- Beaucoup de temps est perdu à déboguer les runners ou à optimiser le processus de build
- Mais il offre aussi des avantages difficiles à obtenir autrement, comme les builds macOS
- Et bien sûr, il n’existe pas vraiment de système réputé plus simple à configurer que GitHub Actions
We are all doomed to GitHub Actions. …but at least I dodged the bullet early.
3 commentaires
On dirait que c’est un problème inévitable, puisqu’on est obligé de mettre la logique dans du YAML.
L’article ci-dessus semble proposer plus ou moins cette réponse, mais j’ai aussi l’impression que si l’on remplaçait la partie script par Dagger, ce serait peut-être la bonne solution.
« Ne laissez pas GitHub Actions gérer la logique ; contrôlez directement les scripts, et faites en sorte qu’Actions se contente d’appeler ces scripts. »
Les GitHub Actions ne devraient servir qu’à configurer l’environnement (OS, toolchain de build, …) et à exécuter des scripts (shell, Python, bat, ps1…). Même si GitHub tombe, on devrait pouvoir builder n’importe où du moment que l’environnement est prêt. Quand je vois les workflows GitHub Actions en ce moment, je me dis qu’est-ce que ça vaut vraiment la peine d’aller chercher et d’utiliser jusque-là. Il y a très longtemps (?), Ansible a fait pareil et s’est planté.
Réactions sur Hacker News
Le problème principal de GitHub Actions, c’est que la boucle de feedback est beaucoup trop lente
Devoir pousser puis attendre juste pour constater un échec trivial est vraiment frustrant
Je pense qu’il vaut mieux séparer les tâches de CI dans des scripts exécutables en local, et n’utiliser les fonctionnalités d’Actions que comme amélioration progressive
La combinaison
workflow_dispatchetgh workflow runest correcte aussi, mais le fait que ce dernier ne donne pas directement l’URL du workflow lancé est pénibleÇa a plutôt bien marché pour obtenir un feedback rapide
Quand un problème survient, je peux déboguer dans un état presque identique à l’environnement GitHub Actions
Ça devrait être une exigence de base de tout système de CI
Au final, l’essentiel, ce sont des fonctions comme la mise en file d’attente, l’analyse des sorties et la télémétrie de l’historique des builds
gh workflow run, j’ai dû relister les exécutions du workflow via l’API GitHubÇa peut se mélanger s’il y a plusieurs exécutions en même temps, mais pour l’instant ça fonctionne à peu près bien
J’ai compilé quelques conseils de conception pour la CI
Un shell simple devrait suffire
C’est bien de définir des cibles CI dans un
Makefileet de les appeler simplement, par exemple avecmake ci-testDepuis, je gère toute ma CI avec des wrappers simples comme
make buildCe serait bien de pouvoir les séparer avec des marqueurs comme
BeginStep("Step Name")Le problème, plus que GitHub Actions lui-même, c’est l’automatisation bricolée qu’on a empilée dessus
La logique devrait être scriptée dans un langage comme Python pour pouvoir être exécutée aussi en local
À chaque fois, il faut modifier le workflow, pousser et attendre
Je fais toute ma CI dans des conteneurs
La plateforme de CI ne fait qu’exécuter ce conteneur, donc je peux lancer exactement la même chose en local
Les plateformes détestent cette approche, parce qu’elle casse le vendor lock-in
En cas d’échec, on peut se connecter directement en SSH pour déboguer, et relancer après avoir modifié le manifeste sans pousser de branche
En revanche, il faut l’auto-héberger
Ça facilite la standardisation, mais avec le compromis de devoir maintenir l’image
En pratique, il n’y a pas vraiment de lock-in, mais les gens sont tombés dans le cargo cult du CI/CD
Moi, j’aime bien GitHub Actions
C’est mieux que Travis, que j’utilisais avant, et c’est très utile comme ressource gratuite pour les projets OSS
Depuis que j’ai adopté Nix, la reproductibilité des environnements a beaucoup augmenté, donc l’intégration avec Actions est nettement meilleure
On peut exécuter tel quel dans Actions le conteneur construit avec flake
Projet d’exemple
Je pense que GitHub Actions devrait simplement appeler des scripts bash ou python
bash a beaucoup de limites, Python est plus flexible et plus simple à exécuter en local
Une approche comme dans cet article, où
uvs’installe automatiquement et gère les dépendances, est idéaleC’est plus complexe que bash, mais dans l’environnement Actions, l’impact sur les performances n’est pas très important
Le plus gros problème d’Actions, c’est la manière dont on le vend comme un assemblage de workflows
Le débogage est presque impossible, et la configuration du cache est délicate, ce qui ralentit les builds
Pour ces raisons, l’idée d’exécuter directement sur une VM persistante devient attrayante
Je suis le fondateur de Depot
Nous exploitons un service qui fournit des runners GitHub Actions plus rapides et moins chers
Les frustrations que ressentent beaucoup de gens reflètent en fait l’avis de la majorité
Le système Actions est structurellement inefficace, et nous découvrons chaque semaine un nouveau goulot d’étranglement
Je suis convaincu qu’il existe une meilleure façon de faire, et nous sommes en train de l’expérimenter
Plus d’infos sur depot.dev
Le week-end dernier, j’ai créé un outil appelé
gg watch actionC’est un outil qui retrouve l’action la plus récente ou en cours pour la branche actuelle
Lien GitHub
gh»En revanche, il y avait un bug dans la commande
gg tuioù les dépôts n’apparaissaient pasJe me demandais si un outil comme
actpouvait aidernektos/act
À cause des différences d’architecture, l’exécution locale peut différer de l’exécution en ligne, mais ça reste utile
Il y avait environ 80 % de compatibilité
SourceHut prend ça en charge, et c’est vraiment pratique