Commit 759d23c
Eric Bower
·
2026-05-08 20:34:45 -0400 EDT
parent 57ccc40
chore: cleanup
2 files changed,
+25,
-48
M
main.go
+10,
-43
| ... | ... | @@ -1146,9 +1146,8 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str | |
| 1146 | 1146 | } | |
| 1147 | 1147 | } | |
| 1148 | 1148 | // Write published.json, then sync to include it in the rsync. | |
| 1149 | - | // syncArtifacts at end-of-tick will skip this job (has published.json), | |
| 1150 | - | // so this is the only sync for completed jobs. In-progress jobs are | |
| 1151 | - | // synced every tick by syncArtifacts (no published.json yet). | |
| 1149 | + | // This is the only sync for completed jobs. In-progress jobs are | |
| 1150 | + | // synced every tick in the else branch below. | |
| 1152 | 1151 | published := map[string]interface{}{ | |
| 1153 | 1152 | "status": status, | |
| 1154 | 1153 | "exit_code": exitCode, |
| ... | ... | @@ -1173,6 +1172,10 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str | |
| 1173 | 1172 | } | |
| 1174 | 1173 | } else { | |
| 1175 | 1174 | log.Debug("job still running", "sessions", len(group)) | |
| 1175 | + | // Sync in-progress jobs every tick using the sessions we already know about. | |
| 1176 | + | if err := syncJobArtifacts(cfg, name, jobID, log); err != nil { | |
| 1177 | + | log.Error("sync artifacts", "err", err) | |
| 1178 | + | } | |
| 1176 | 1179 | // Publish running status only when --include-running is set | |
| 1177 | 1180 | if cfg.IncludeRunning { | |
| 1178 | 1181 | if cfg.HumanOutput { |
| ... | ... | @@ -1197,10 +1200,6 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str | |
| 1197 | 1200 | } | |
| 1198 | 1201 | } | |
| 1199 | 1202 | ||
| 1200 | - | if err := syncArtifacts(cfg, log); err != nil { | |
| 1201 | - | log.Error("sync artifacts", "err", err) | |
| 1202 | - | } | |
| 1203 | - | ||
| 1204 | 1203 | return nil | |
| 1205 | 1204 | } | |
| 1206 | 1205 |
| ... | ... | @@ -1499,6 +1498,10 @@ func syncJobArtifacts(cfg *Cfg, repoName, jobID string, log *slog.Logger) error | |
| 1499 | 1498 | eventPath := filepath.Join(jobDir, "artifacts", "event.json") | |
| 1500 | 1499 | data, err := os.ReadFile(eventPath) | |
| 1501 | 1500 | if err != nil { | |
| 1501 | + | if os.IsNotExist(err) { | |
| 1502 | + | log.Debug("event.json not found, skipping sync", "repo", repoName, "job_id", jobID) | |
| 1503 | + | return nil | |
| 1504 | + | } | |
| 1502 | 1505 | return fmt.Errorf("read event: %w", err) | |
| 1503 | 1506 | } | |
| 1504 | 1507 | var event Event |
| ... | ... | @@ -1533,42 +1536,6 @@ func syncJobArtifacts(cfg *Cfg, repoName, jobID string, log *slog.Logger) error | |
| 1533 | 1536 | return runCmd(cmd, log) | |
| 1534 | 1537 | } | |
| 1535 | 1538 | ||
| 1536 | - | func syncArtifacts(cfg *Cfg, log *slog.Logger) error { | |
| 1537 | - | entries, err := os.ReadDir(cfg.ArtifactDir) | |
| 1538 | - | if err != nil { | |
| 1539 | - | return fmt.Errorf("read artifact dir: %w", err) | |
| 1540 | - | } | |
| 1541 | - | ||
| 1542 | - | for _, entry := range entries { | |
| 1543 | - | if !entry.IsDir() { | |
| 1544 | - | continue | |
| 1545 | - | } | |
| 1546 | - | repoEntries, err := os.ReadDir(filepath.Join(cfg.ArtifactDir, entry.Name())) | |
| 1547 | - | if err != nil { | |
| 1548 | - | log.Error("read repo dir", "repo", entry.Name(), "err", err) | |
| 1549 | - | continue | |
| 1550 | - | } | |
| 1551 | - | for _, repoEntry := range repoEntries { | |
| 1552 | - | if !repoEntry.IsDir() { | |
| 1553 | - | continue | |
| 1554 | - | } | |
| 1555 | - | jobDir := filepath.Join(cfg.ArtifactDir, entry.Name(), repoEntry.Name()) | |
| 1556 | - | publishedPath := filepath.Join(jobDir, "artifacts", "published.json") | |
| 1557 | - | ||
| 1558 | - | // Skip if job is complete (published.json exists) | |
| 1559 | - | // In-progress jobs are synced every tick; completed jobs are skipped. | |
| 1560 | - | if _, err := os.Stat(publishedPath); err == nil { | |
| 1561 | - | continue | |
| 1562 | - | } | |
| 1563 | - | ||
| 1564 | - | if err := syncJobArtifacts(cfg, entry.Name(), repoEntry.Name(), log); err != nil { | |
| 1565 | - | log.Error("sync artifacts", "repo", entry.Name(), "job_id", repoEntry.Name(), "err", err) | |
| 1566 | - | } | |
| 1567 | - | } | |
| 1568 | - | } | |
| 1569 | - | return nil | |
| 1570 | - | } | |
| 1571 | - | ||
| 1572 | 1539 | func allCompleted(sessions []SessionInfo) bool { | |
| 1573 | 1540 | for _, s := range sessions { | |
| 1574 | 1541 | if s.Ended == "" { |
+15,
-5
| ... | ... | @@ -30,8 +30,8 @@ h2 { | |
| 30 | 30 | } | |
| 31 | 31 | ||
| 32 | 32 | .meta { | |
| 33 | - | color: #6c7086; | |
| 34 | - | font-size: 0.8rem; | |
| 33 | + | color: #bac2de; | |
| 34 | + | font-size: 0.85rem; | |
| 35 | 35 | margin-bottom: 1rem; | |
| 36 | 36 | display: flex; | |
| 37 | 37 | gap: 1.5rem; |
| ... | ... | @@ -66,7 +66,7 @@ th { | |
| 66 | 66 | border-bottom: 2px solid #313244; | |
| 67 | 67 | font-size: 0.8rem; | |
| 68 | 68 | text-transform: uppercase; | |
| 69 | - | color: #6c7086; | |
| 69 | + | color: #a6adc8; | |
| 70 | 70 | } | |
| 71 | 71 | ||
| 72 | 72 | td { |
| ... | ... | @@ -86,10 +86,20 @@ pre { | |
| 86 | 86 | ||
| 87 | 87 | pre code { font-size: 13px; } | |
| 88 | 88 | ||
| 89 | - | .zmx-output { white-space: pre-wrap; word-break: break-word; } | |
| 89 | + | .zmx-output { | |
| 90 | + | white-space: pre-wrap; | |
| 91 | + | word-break: break-word; | |
| 92 | + | background: #11111b; | |
| 93 | + | border: 1px solid #313244; | |
| 94 | + | border-radius: 8px; | |
| 95 | + | padding: 1rem; | |
| 96 | + | overflow-x: auto; | |
| 97 | + | margin: 1rem 0; | |
| 98 | + | font-size: 13px; | |
| 99 | + | } | |
| 90 | 100 | ||
| 91 | 101 | /* Links */ | |
| 92 | 102 | a { color: #89b4fa; text-decoration: none; } | |
| 93 | 103 | a:hover { text-decoration: underline; } | |
| 94 | 104 | ||
| 95 | - | .links { margin-top: 1rem; color: #6c7086; font-size: 0.85rem; } | |
| 105 | + | .links { margin-top: 1rem; color: #a6adc8; font-size: 0.85rem; } |