
Votre propre CI sur Forgejo : les pièges du runner, une image pour tout, et des tests qui ne mentent pas
Avoir sa propre forge, c'est avoir sa propre CI : chaque demande de fusion testée sur votre matériel, pas de minutes à acheter, rien qui sorte de la maison. Forgejo Actions lit les mêmes fichiers de workflow que GitHub Actions, presque. C'est dans le « presque » que partent les soirées.
Comment ces chiffres ont été obtenus. Mesurés sur nos propres machines (voir le protocole), en général en un seul passage, vitesses relevées par le serveur lui-même ; nous ne publions pas les journaux bruts. Ce sont des ordres de grandeur sur ce matériel, pas des garanties sur le vôtre. Les chiffres extérieurs sont accompagnés de leur source.
Ce que vous y gagnez. Les trois pièges qui bloquent un premier workflow, une image d'exécutant qui porte tous les outils pour que les jobs cessent de les réinstaller (un job passait 1 min 24 de ses 1 min 30 à réinstaller ses outils), et quatre habitudes qui gardent une CI verte honnête sur une quarantaine de dépôts ici.
Un peu d'histoire
Forgejo descend de Gogs, un service Git auto-hébergé écrit en Go (2014), repris sous le nom de Gitea en 2016 par sa communauté. Quand la gouvernance de Gitea est passée à une entreprise en 2022, l'association Codeberg a lancé Forgejo comme fork communautaire, devenu entièrement indépendant en 2024. Sa CI, Forgejo Actions, lit volontairement le format de workflow popularisé par GitHub Actions (2018), si bien que la plupart des workflows existants tournent avec de petites retouches. L'exécutant est un programme à part : vous décidez quelle machine fait tourner vos jobs, et quels outils elle porte.
1. Trois pièges d'un premier workflow
- L'exécutant ne répond qu'à ses étiquettes. Le nôtre annonce
ubuntu-latest. Tout autreruns-on:laisse le job en attente pour toujours, sans erreur : personne ne le réclame. - Pas d'image slim comme conteneur de job. Les actions JavaScript comme
checkouttournent avecnodedans le conteneur du job. Une imagepython:slimn'a pas node : le job meurt en code 127 avant sa première étape. - Écrivez les actions avec leur adresse complète :
https://data.forgejo.org/actions/checkout@v4. Les noms courts ne sont pas résolus vers GitHub.
2. Une seule image d'exécutant pour tous les dépôts
Chaque workflow réinstallait pip, ruff, pytest, uv, node et compagnie à chaque passage : 1 min 24 sur un job de 1 min 30. Nous avons construit une image qui les porte tous, et pointé l'étiquette de l'exécutant dessus.
- Basée sur une image Python complète, avec node copié depuis l'image officielle (les actions en ont besoin).
- Versions des outils épinglées en un seul endroit, et vérifiées par la dernière étape de construction : un mauvais épinglage fait échouer la construction, il ne part jamais.
- Un manifeste de chaque outil et version est écrit dans l'image, comme preuve.
- Pas besoin de registre : le Dockerfile est la source, et l'image se reconstruit en quelques minutes dans le propre démon Docker de l'exécutant.
3. Quatre habitudes qui gardent le vert honnête
- Lisez le journal de la forge avant de reproduire quoi que ce soit. Une reproduction locale d'un job en échec est un jour sortie verte sur un commit réellement cassé ; le journal nommait les quatre assertions en échec d'un coup. Les journaux sont stockés compressés, un fichier par job, dans le dossier de données de la forge.
- Vérifiez en local avant de pousser. Une vérification de types ou un passage de tests sur le portable prend une minute ; chaque aller-retour par la CI en coûte dix, et une demande de fusion à fermer.
- Un test qui verrouille un bug est pire qu'aucun test. Après le renommage d'un dépôt, trois tests affirmaient encore l'ancien nom : la CI restait verte pendant que chaque déploiement échouait. Testez ce que le système doit faire, pas la valeur qu'il a aujourd'hui.
- Un cliquet pour la cohérence. Notre CI compte le texte qui n'est pas dans la langue du projet et échoue si le compte monte ; quand il baisse, le plafond doit baisser dans la même demande de fusion. Les exceptions légitimes sont listées dans un fichier, chacune avec sa raison.
Pièges
Un message de commit écrit avec un here-document sur la même ligne que d'autres commandes prend ces commandes pour son texte. Gardez git commit -F - <<'MSG' seul dans sa commande, relisez le sujet avec git log -1 --format=%s, et seulement ensuite poussez.
Certains points d'accès de l'API des runs renvoient des listes vides ou des 404 selon les versions, ce qui ressemble à « aucun exécutant ». Fiez-vous au journal du job et à l'état de l'exécutant lui-même, pas à une liste vide.
Sources
Utile ? Dites-nous ce qu'il faut mesurer ensuite.