Commit 386fa8c

Eric Bower  ·  2026-05-07 10:07:59 -0400 EDT
parent e2e0d12
style(runner): update session status
1 files changed,  +40, -13
+40, -13
......@@ -14,6 +14,7 @@ import (
1414 "os/exec"
1515 "os/signal"
1616 "path/filepath"
17+ "strconv"
1718 "strings"
1819 "syscall"
1920 "time"
......@@ -500,16 +501,17 @@ func waitAndReport(cfg *Cfg, log *slog.Logger, name, jobID string) error {
500501 fmt.Fprintln(os.Stdout)
501502 fmt.Fprint(os.Stdout, "⏳ waiting for completion...\n")
502503
503- // Track what we've already printed to avoid duplicates
504+ // Track state for each session
504505 type sessionState struct {
505506 status string // "running", "success", "failed"
506507 exitCode string
507508 duration string
508- printed bool
509+ printed bool // true once final state (success/failed) is printed
509510 }
510511 known := make(map[string]*sessionState)
511512 var jobSessions []SessionInfo
512513 var sessionOrder []string // track insertion order for deterministic output
514+ var liveLines []string // last set of status lines printed (for overwrite)
513515
514516 for {
515517 select {
......@@ -552,6 +554,8 @@ func waitAndReport(cfg *Cfg, log *slog.Logger, name, jobID string) error {
552554
553555 if s.Ended == "" {
554556 state.status = "running"
557+ created, _ := strconv.ParseInt(s.Created, 10, 64)
558+ state.duration = fmtDurationTs(created, time.Now().Unix())
555559 } else {
556560 if s.ExitCode == "0" {
557561 state.status = "success"
......@@ -560,22 +564,45 @@ func waitAndReport(cfg *Cfg, log *slog.Logger, name, jobID string) error {
560564 state.exitCode = s.ExitCode
561565 }
562566 state.duration = fmtDuration(s.Created, s.Ended)
567+ state.printed = true // lock final state
563568 }
569+ }
564570
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")
574596 }
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)
577603 }
578604 }
605+ liveLines = lines
579606
580607 // Check if all sessions are done
581608 if allCompleted(jobSessions) {