neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
Keep watching a run across a forge restart
bdd2439 · Gabriel Morell · 2026-09-19 04:16
Message
{commit_body(@commit)}
Files changed
modified
cli/src/commands/ci.rs
+34
−1
@@ -12,6 +12,11 @@ use crate::output::{
| 12 | 12 | status_mark, status_tone, truncate, |
| 13 | 13 | }; |
| 14 | 14 | |
| 15 | +/// How many consecutive polling failures end a watch. At the default | |
| 16 | +/// interval that is about a minute of silence, which outlasts a restart | |
| 17 | +/// without hiding a forge that has genuinely gone away. | |
| 18 | +const MAX_WATCH_FAILURES: u32 = 12; | |
| 19 | + | |
| 15 | 20 | pub async fn run(ctx: &Ctx, command: &CiCommand) -> Result<()> { |
| 16 | 21 | let repo = ctx.repo()?; |
| 17 | 22 | match command { |
@@ -308,9 +313,37 @@ async fn watch(ctx: &Ctx, repo: &RepoRef, number: Option<i64>, interval: u64) ->
| 308 | 313 | let number = resolve_number(ctx, repo, number).await?; |
| 309 | 314 | let interval = Duration::from_secs(interval.max(1)); |
| 310 | 315 | let mut last_line = String::new(); |
| 316 | + let mut failures = 0; | |
| 311 | 317 | |
| 312 | 318 | loop { |
| 313 | − let res = ctx.api.run(repo, number).await?; | |
| 319 | + // A watch outlives things the forge does to itself. Deploying it | |
| 320 | + // mid-run answers with 502s for a few seconds, and giving up | |
| 321 | + // then is the opposite of what watching is for — so transient | |
| 322 | + // errors are reported once and retried, and only a run of them | |
| 323 | + // ends the watch. | |
| 324 | + let res = match ctx.api.run(repo, number).await { | |
| 325 | + Ok(res) => { | |
| 326 | + if failures > 0 { | |
| 327 | + note("reconnected"); | |
| 328 | + failures = 0; | |
| 329 | + } | |
| 330 | + res | |
| 331 | + } | |
| 332 | + Err(e) => { | |
| 333 | + failures += 1; | |
| 334 | + if failures >= MAX_WATCH_FAILURES { | |
| 335 | + return Err(e.context(format!( | |
| 336 | + "giving up after {failures} consecutive failures watching run #{number}" | |
| 337 | + ))); | |
| 338 | + } | |
| 339 | + if failures == 1 { | |
| 340 | + note(&format!("{e:#} — retrying")); | |
| 341 | + } | |
| 342 | + tokio::time::sleep(interval).await; | |
| 343 | + continue; | |
| 344 | + } | |
| 345 | + }; | |
| 346 | + | |
| 314 | 347 | let run = &res.run; |
| 315 | 348 | let state = effective_status(&run.status, run.conclusion.as_deref()); |
| 316 | 349 |
Parents: 5c5c51d