Aller au contenu
use-cases / crontab-per-branch / hero
CRON · GIT · PLANNINGS PAR BRANCHE

Un crontab par branche, déployé avec le code

Versionnez `.hoody/crontab` dans le dépôt à côté de vos jobs. Lorsque le script de déploiement crée un conteneur pour `main`, `feature/billing-v2` ou n'importe quelle branche de prévisualisation, il envoie ce fichier en PUT sur l'API Cron du nouveau conteneur. Le planning embarque avec la branche — et disparaît quand la branche disparaît.

Lire l'API Cron
use-cases / crontab-per-branch / mechanism

Comment `.hoody/crontab` devient un vrai planning

Chaque conteneur de branche exécute Hoody Cron. Le script de déploiement lit le crontab versionné et l'envoie en PUT sur l'endpoint raw-crontab du nouveau conteneur. Le conteneur exécute le planning décrit par le fichier — ni plus, ni moins.

deploy.sh · poussé par CI
shell · client
#!/bin/sh
# Provisionner un conteneur neuf pour cette branche.
BRANCH=$(git branch --show-current)
CTR=$(hoody containers create --from main-snapshot)

# Remplacer le crontab du conteneur par celui du dépôt.
curl -X PUT --data-binary @.hoody/crontab \
  -H "Content-Type: text/plain" \
  https://$CTR-cron-1.hoody.com/users/root/crontab

# Terminé. Le planning de la branche vit dans son conteneur.
echo "deployed $BRANCH → $CTR"
PUT /users/root/crontab
cron · serveur
# Endpoint raw-crontab de Hoody Cron — remplace le fichier entier de manière atomique.
PUT /users/root/crontab HTTP/1.1
Host: ctr_4d72b9-cron-1.hoody.com
Content-Type: text/plain

0 2 * * * /srv/jobs/billing-rollup-v2.sh
*/15 * * * * /srv/jobs/sync-stripe.py
@hourly curl -fsS http://localhost/healthz
*/5 * * * * /srv/jobs/diff-v1-v2.sh

HTTP/1.1 200 OK
# 200 OK : le démon cron recharge, planning actif en moins d'une seconde.

Le crontab est une donnée que la branche transporte, pas un état que le serveur cron mémorise. Supprimez le conteneur, et il ne reste aucune entrée à nettoyer — le fichier est parti avec le disque.

use-cases / crontab-per-branch / powers

Trois choses que vous arrêtez de faire

Une fois que le planning est un fichier dans le dépôt, trois catégories de travail disparaissent.

VERSIONING

Les plannings voyagent dans le même diff que le code

Quand vous changez `billing-rollup.sh` en v2, le nouveau planning arrive dans la même pull request. Le relecteur voit la ligne cron juste à côté du script. Annulez un commit et le planning est annulé avec lui.

DÉMONTAGE

Supprimez la branche, le cron part avec

Les conteneurs de branche sont éphémères. Quand vous fusionnez ou fermez la branche, vous démontez le conteneur. Le crontab vivait dedans, donc le planning disparaît sans concierge — il n'y a pas de serveur cron partagé qui retient des entrées obsolètes.

ISOLATION

L'expérimentation ne peut pas se déclencher en staging

Un job expérimental horaire sur `experiment/llm-rollups` tourne dans son propre conteneur avec son propre système de fichiers. Le démon cron de staging ne le voit jamais ; le démon cron de production ne le voit jamais. Il n'y a pas de garde-fous `if BRANCH_ENV` à l'intérieur des jobs eux-mêmes.

use-cases / crontab-per-branch / compare

Crontab partagé vs crontab par branche

Le modèle standard "un crontab géré par les ops" et le modèle lié à la branche échouent dans des directions opposées. Même job, rayon d'impact très différent.

AXECRONTAB PARTAGÉCRONTAB PAR BRANCHE
Source de vérité
wiki ops + rôle ansiblele planning vit dans un dépôt différent du script
.hoody/crontab dans le dépôtà côté du script invoqué par la ligne cron
Ajouter un job
merger le code → pinger les ops → SSH vers l'hôte crondeux systèmes doivent s'accorder, manuellement
éditer le fichier, pousser, déployerun diff, un merge, un déploiement
Isolation par branche
if [ "$ENV" = staging ]; then …chaque job connaît chaque environnement
un conteneur par branchepas de drapeau d'environnement dans le script
Nettoyage
se rappeler de retirer la ligneles entrées obsolètes s'accumulent pendant des années
branche supprimée = cron suppriméle système de fichiers a disparu, le planning a disparu
Expérimentations
le crontab de production est le seultout test risque de se déclencher en prod
branche d'essai = crontab d'essaise déclenche uniquement dans son conteneur

La différence n'est pas une fonctionnalité — c'est l'endroit où vit le planning. Un fichier que la branche transporte, vs une ligne dans une table partagée que la branche emprunte.

use-cases / crontab-per-branch / capacity

Ce que Hoody Cron vous donne réellement

Le Cron par conteneur est une vraie surface REST — trois familles d'endpoints, syntaxe cron standard, isolation totale par utilisateur. Chiffres tirés de la spec de l'API Cron, pas de benchmarks inventés.

  1. CRONTAB PAR CONTENEUR1

    Chaque conteneur de branche a son propre crontab par utilisateur. PUT du fichier complet, GET pour le récupérer, remplacement atomique. Aucune table de planning partagée en coulisses.

  2. FAMILLES D'ENDPOINTS3

    Crontab brut (GET/PUT), entrées gérées (POST/PATCH/DELETE avec UUID et `expires_at`), et listage par utilisateur. Choisissez ce dont votre script de déploiement a besoin.

  3. EXPRESSIONS CRON À 5 CHAMPS5

    Standard `min hour day month dow` plus les macros : `@hourly`, `@daily`, `@weekly`, `@monthly`, `@yearly`. La même syntaxe que celle que votre `.hoody/crontab` utilise déjà.

Selon l'API Hoody Cron : GET/PUT /users/[user]/crontab et POST/PATCH/DELETE /users/[user]/entries sur l'URL du service cron de chaque conteneur.

use-cases / crontab-per-branch / punchline

Le planning vit à côté du code qu'il déclenche, dans le même conteneur, sur la même branche.

avant · deux systèmes à reteniraprès · un fichier dans le dépôt
CE QUE VOUS AVIEZ AVANTplanning dans ops/ansible · code dans app/ · jamais d'accordmerger la PR, puis ouvrir un ticket pour mettre à jour l'hôte cron
CE QUE VOUS AVEZ MAINTENANTPUT @.hoody/crontab → cron-1.[branch].hoody.comun PUT, un conteneur, un planning, une branche
Lire l'API Cron
use-cases / crontab-per-branch / replaces

Ce que cela remplace

Six endroits où le planning cron vivait, aucun à côté du code. Le crontab lié à la branche les rend tous redondants.

  • crontab de production partagéUn fichier sur un hôte cron autour duquel toutes les équipes devaient se coordonner
  • synchronisation manuelle de la config cronRôle Ansible / manifeste Puppet appliqués hors-bande de vos merges de code
  • plannings GitHub Actions épinglés à mainPlannings liés à la branche par défaut, invisibles aux travaux de feature et aux prévisualisations
  • "se rappeler de mettre à jour cron au merge"Une checklist humaine — la seule chose qui sépare vous d'une entrée obsolète
  • dépôt séparé de config cronUn second dépôt dont le seul rôle était de prendre du retard sur celui qui contient le vrai code
  • migrations programmées Atlas/LiquibaseOutils de migration faisant office de planificateur car il n'y avait nulle part de mieux pour cela
use-cases / crontab-per-branch / cta

Arrêtez de synchroniser des plannings entre systèmes. Versionnez le crontab. Laissez la branche le porter.

Lire la doc Cron
use-cases / crontab-per-branch / related

Découvrez les autres