Commit 386fa8c
Eric Bower
·
2026-05-07 10:07:59 -0400 EDT
parent e2e0d12
style(runner): update session status
1 files changed,
+40,
-13
M
main.go
M
main.go
+40,
-13
| ... | ... | @@ -14,6 +14,7 @@ import ( | |
| 14 | 14 | "os/exec" | |
| 15 | 15 | "os/signal" | |
| 16 | 16 | "path/filepath" | |
| 17 | + | "strconv" | |
| 17 | 18 | "strings" | |
| 18 | 19 | "syscall" | |
| 19 | 20 | "time" |
| ... | ... | @@ -500,16 +501,17 @@ func waitAndReport(cfg *Cfg, log *slog.Logger, name, jobID string) error { | |
| 500 | 501 | fmt.Fprintln(os.Stdout) | |
| 501 | 502 | fmt.Fprint(os.Stdout, "⏳ waiting for completion...\n") | |
| 502 | 503 | ||
| 503 | - | // Track what we've already printed to avoid duplicates | |
| 504 | + | // Track state for each session | |
| 504 | 505 | type sessionState struct { | |
| 505 | 506 | status string // "running", "success", "failed" | |
| 506 | 507 | exitCode string | |
| 507 | 508 | duration string | |
| 508 | - | printed bool | |
| 509 | + | printed bool // true once final state (success/failed) is printed | |
| 509 | 510 | } | |
| 510 | 511 | known := make(map[string]*sessionState) | |
| 511 | 512 | var jobSessions []SessionInfo | |
| 512 | 513 | var sessionOrder []string // track insertion order for deterministic output | |
| 514 | + | var liveLines []string // last set of status lines printed (for overwrite) | |
| 513 | 515 | ||
| 514 | 516 | for { | |
| 515 | 517 | select { |
| ... | ... | @@ -552,6 +554,8 @@ func waitAndReport(cfg *Cfg, log *slog.Logger, name, jobID string) error { | |
| 552 | 554 | ||
| 553 | 555 | if s.Ended == "" { | |
| 554 | 556 | state.status = "running" | |
| 557 | + | created, _ := strconv.ParseInt(s.Created, 10, 64) | |
| 558 | + | state.duration = fmtDurationTs(created, time.Now().Unix()) | |
| 555 | 559 | } else { | |
| 556 | 560 | if s.ExitCode == "0" { | |
| 557 | 561 | state.status = "success" |
| ... | ... | @@ -560,22 +564,45 @@ func waitAndReport(cfg *Cfg, log *slog.Logger, name, jobID string) error { | |
| 560 | 564 | state.exitCode = s.ExitCode | |
| 561 | 565 | } | |
| 562 | 566 | state.duration = fmtDuration(s.Created, s.Ended) | |
| 567 | + | state.printed = true // lock final state | |
| 563 | 568 | } | |
| 569 | + | } | |
| 564 | 570 | ||
| 565 | - | // Print when state changes | |
| 566 | - | if !state.printed { | |
| 567 | - | icon := map[string]string{"running": "🚀", "success": "✅", "failed": "❌"}[state.status] | |
| 568 | - | detail := "" | |
| 569 | - | if state.status == "failed" && state.exitCode != "" { | |
| 570 | - | detail = fmt.Sprintf(", exit %s", state.exitCode) | |
| 571 | - | } | |
| 572 | - | if state.duration != "" && state.duration != "—" { | |
| 573 | - | detail += fmt.Sprintf(" (%s)", state.duration) | |
| 571 | + | // Build current status lines | |
| 572 | + | lines := make([]string, 0, len(sessionOrder)) | |
| 573 | + | for _, short := range sessionOrder { | |
| 574 | + | state := known[short] | |
| 575 | + | icon := map[string]string{"running": "🚀", "success": "✅", "failed": "❌"}[state.status] | |
| 576 | + | detail := "" | |
| 577 | + | if state.status == "failed" && state.exitCode != "" { | |
| 578 | + | detail = fmt.Sprintf(", exit %s", state.exitCode) | |
| 579 | + | } | |
| 580 | + | if state.duration != "" && state.duration != "—" { | |
| 581 | + | detail += fmt.Sprintf(" (%s)", state.duration) | |
| 582 | + | } | |
| 583 | + | lines = append(lines, fmt.Sprintf(" %-12s %s %s%s", short, icon, state.status, detail)) | |
| 584 | + | } | |
| 585 | + | ||
| 586 | + | // Overwrite previous lines with cursor-up, or print fresh | |
| 587 | + | if len(liveLines) > 0 { | |
| 588 | + | // Move cursor up to overwrite previous lines | |
| 589 | + | for range len(liveLines) { | |
| 590 | + | fmt.Fprint(os.Stdout, "\033[A") | |
| 591 | + | } | |
| 592 | + | // Clear each line | |
| 593 | + | for i, line := range lines { | |
| 594 | + | if i > 0 { | |
| 595 | + | fmt.Fprint(os.Stdout, "\n") | |
| 574 | 596 | } | |
| 575 | - | fmt.Fprintf(os.Stdout, " %-12s %s %s%s\n", s.Short, icon, state.status, detail) | |
| 576 | - | state.printed = true | |
| 597 | + | fmt.Fprint(os.Stdout, line+"\033[K") | |
| 598 | + | } | |
| 599 | + | fmt.Fprint(os.Stdout, "\n") | |
| 600 | + | } else { | |
| 601 | + | for _, line := range lines { | |
| 602 | + | fmt.Fprintln(os.Stdout, line) | |
| 577 | 603 | } | |
| 578 | 604 | } | |
| 605 | + | liveLines = lines | |
| 579 | 606 | ||
| 580 | 607 | // Check if all sessions are done | |
| 581 | 608 | if allCompleted(jobSessions) { |