Skip to content

fix(deploy) : libérer le verrou « deploying » orphelin après une preview, file de déploiement lisible - #286

Merged
bobdivx merged 1 commit into
mainfrom
fix/preview-cancel-releases-deploying
Oct 27, 2026
Merged

bobdivx merged 1 commit into
mainfrom
fix/preview-cancel-releases-deploying

Conversation

@bobdivx

@bobdivx bobdivx commented Oct 27, 2026

Copy link
Copy Markdown
Owner

Contexte

Le 27/10 vers 11:22 (heure de Paris), la fusion de la PR #3 de jeser a laissé son déploiement production en « queued » pendant de longues minutes, avec seulement [devforge] webhook push… dans les logs. Le projet affichait « deploying » et rien n'indiquait ce qui le retenait.

En relisant l'historique (lecture seule), on voit que la ligne en file attendait le slot du nœud default. Il était occupé de 11:21:43 à 11:36:45 par le build de la preview preview-201 de popcornn-server. Un déploiement relancé à 11:32 est d'ailleurs resté en file jusqu'à 11:36:45, puis il a réussi. La preview jeser (preview-3) avait bien été annulée à 11:22:49.

Ce correctif traite deux faiblesses :

  1. une file muette, sans aucune trace du nœud attendu ni de qui l'occupe ;
  2. un verrou projet « deploying » qui peut rester orphelin. La suppression d'une preview ne recalculait jamais le statut du projet, et le nettoyage existant ne libère le projet qu'au moment où il passe lui-même un déploiement en échec.

Changements

  • pr_previews::teardown (fusion ou fermeture de PR, nettoyage horaire) : après l'annulation des déploiements de la preview, appel de deploy_queue::release_deploying_if_no_active. Le projet ne quitte « deploying » que s'il n'a plus aucun déploiement actif, tous environnements confondus (prod, dev, previews). Une seule requête UPDATE … WHERE NOT EXISTS (…) : un déploiement prod inséré par la fusion garde son verrou, sans fenêtre de course.
  • Garde-fou deploy_queue::release_orphan_project_locks, branché dans la boucle de nettoyage existante (main.rs). Le premier tick est immédiat (donc au démarrage), puis il tourne toutes les 5 min. Un projet resté « deploying » depuis plus de 2 min sans aucun déploiement actif repasse à live (une révision prod a réussi), à failed (un échec prod n'est pas acquitté) ou à idle.
  • File lisible : dans run_in_node_slot, si le slot du nœud est déjà pris, le déploiement en file reçoit une ligne de log du type [devforge] en attente du nœud « default » : occupé par popcornn-server (preview-201, 7974710e) — un seul build à la fois par nœud.
  • La file ne lit pas projects.status : elle ne dépend que du slot du nœud et de l'état de la ligne deployments. Un verrou « deploying » orphelin ne peut donc pas bloquer un build. Le correctif garantit en plus que ce statut ne reste pas affiché à tort.

Tests (nouveaux, deploy_queue::tests)

  • preview_cancel_keeps_lock_while_prod_is_active : preview annulée et prod queued puis running → le projet reste « deploying ».
  • preview_cancel_releases_lock_when_nothing_active : plus rien d'actif → live (succès prod existant) ou idle ; un projet qui n'est pas en « deploying » n'est pas touché.
  • other_active_environment_keeps_lock : une autre preview encore en build garde le verrou.
  • orphan_sweep_frees_only_stale_unbacked_locks : sont libérés seulement les verrous anciens et sans déploiement actif. Résultats : live / failed ; verrou récent ou adossé à un déploiement → conservé.
  • waiting_note_names_the_holder, queued_deploy_logs_who_holds_the_node : note d'attente écrite pendant que le nœud est tenu, puis build exécuté une fois le nœud libéré.

cargo test -p devforge-server en local : 321 tests OK. check-forbidden-names : OK.

Hors périmètre (à décider séparément)

Un build de preview long (15 min ici) bloque les déploiements production de tous les projets du même nœud : un seul slot par nœud. Pour éviter que ça se reproduise, il faudrait par exemple donner la priorité à la prod ou un slot séparé aux previews. Ce changement d'ordonnancement n'est pas inclus ici.

⚠️ Ne pas fusionner sans relecture. Aucun déploiement n'a été lancé pour cette PR.

…le lisible

- Suppression/annulation d'une preview (fusion ou fermeture de PR) : le projet
  ne quitte « deploying » que si plus aucun déploiement n'est actif, tous
  environnements confondus (une prod lancée par la fusion garde son verrou).
- Garde-fou dans la boucle de nettoyage existante (premier tick au boot puis
  toutes les 5 min) : un projet « deploying » sans déploiement actif depuis
  plus de 2 min repasse à live / failed / idle.
- Déploiement en file derrière un autre build du même nœud : une ligne de log
  indique le nœud attendu et le déploiement qui l'occupe.
- Tests unitaires.
@bobdivx
bobdivx merged commit 0e39c3f into main Oct 27, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant