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
 1@@ -1146,9 +1146,8 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str
 2 				}
 3 			}
 4 			// Write published.json, then sync to include it in the rsync.
 5-			// syncArtifacts at end-of-tick will skip this job (has published.json),
 6-			// so this is the only sync for completed jobs. In-progress jobs are
 7-			// synced every tick by syncArtifacts (no published.json yet).
 8+			// This is the only sync for completed jobs. In-progress jobs are
 9+			// synced every tick in the else branch below.
10 			published := map[string]interface{}{
11 				"status":      status,
12 				"exit_code":   exitCode,
13@@ -1173,6 +1172,10 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str
14 			}
15 		} else {
16 			log.Debug("job still running", "sessions", len(group))
17+			// Sync in-progress jobs every tick using the sessions we already know about.
18+			if err := syncJobArtifacts(cfg, name, jobID, log); err != nil {
19+				log.Error("sync artifacts", "err", err)
20+			}
21 			// Publish running status only when --include-running is set
22 			if cfg.IncludeRunning {
23 				if cfg.HumanOutput {
24@@ -1197,10 +1200,6 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str
25 		}
26 	}
27 
28-	if err := syncArtifacts(cfg, log); err != nil {
29-		log.Error("sync artifacts", "err", err)
30-	}
31-
32 	return nil
33 }
34 
35@@ -1499,6 +1498,10 @@ func syncJobArtifacts(cfg *Cfg, repoName, jobID string, log *slog.Logger) error
36 	eventPath := filepath.Join(jobDir, "artifacts", "event.json")
37 	data, err := os.ReadFile(eventPath)
38 	if err != nil {
39+		if os.IsNotExist(err) {
40+			log.Debug("event.json not found, skipping sync", "repo", repoName, "job_id", jobID)
41+			return nil
42+		}
43 		return fmt.Errorf("read event: %w", err)
44 	}
45 	var event Event
46@@ -1533,42 +1536,6 @@ func syncJobArtifacts(cfg *Cfg, repoName, jobID string, log *slog.Logger) error
47 	return runCmd(cmd, log)
48 }
49 
50-func syncArtifacts(cfg *Cfg, log *slog.Logger) error {
51-	entries, err := os.ReadDir(cfg.ArtifactDir)
52-	if err != nil {
53-		return fmt.Errorf("read artifact dir: %w", err)
54-	}
55-
56-	for _, entry := range entries {
57-		if !entry.IsDir() {
58-			continue
59-		}
60-		repoEntries, err := os.ReadDir(filepath.Join(cfg.ArtifactDir, entry.Name()))
61-		if err != nil {
62-			log.Error("read repo dir", "repo", entry.Name(), "err", err)
63-			continue
64-		}
65-		for _, repoEntry := range repoEntries {
66-			if !repoEntry.IsDir() {
67-				continue
68-			}
69-			jobDir := filepath.Join(cfg.ArtifactDir, entry.Name(), repoEntry.Name())
70-			publishedPath := filepath.Join(jobDir, "artifacts", "published.json")
71-
72-			// Skip if job is complete (published.json exists)
73-			// In-progress jobs are synced every tick; completed jobs are skipped.
74-			if _, err := os.Stat(publishedPath); err == nil {
75-				continue
76-			}
77-
78-			if err := syncJobArtifacts(cfg, entry.Name(), repoEntry.Name(), log); err != nil {
79-				log.Error("sync artifacts", "repo", entry.Name(), "job_id", repoEntry.Name(), "err", err)
80-			}
81-		}
82-	}
83-	return nil
84-}
85-
86 func allCompleted(sessions []SessionInfo) bool {
87 	for _, s := range sessions {
88 		if s.Ended == "" {
M tmpl/styles.css
+15, -5
 1@@ -30,8 +30,8 @@ h2 {
 2 }
 3 
 4 .meta {
 5-  color: #6c7086;
 6-  font-size: 0.8rem;
 7+  color: #bac2de;
 8+  font-size: 0.85rem;
 9   margin-bottom: 1rem;
10   display: flex;
11   gap: 1.5rem;
12@@ -66,7 +66,7 @@ th {
13   border-bottom: 2px solid #313244;
14   font-size: 0.8rem;
15   text-transform: uppercase;
16-  color: #6c7086;
17+  color: #a6adc8;
18 }
19 
20 td {
21@@ -86,10 +86,20 @@ pre {
22 
23 pre code { font-size: 13px; }
24 
25-.zmx-output { white-space: pre-wrap; word-break: break-word; }
26+.zmx-output {
27+  white-space: pre-wrap;
28+  word-break: break-word;
29+  background: #11111b;
30+  border: 1px solid #313244;
31+  border-radius: 8px;
32+  padding: 1rem;
33+  overflow-x: auto;
34+  margin: 1rem 0;
35+  font-size: 13px;
36+}
37 
38 /* Links */
39 a { color: #89b4fa; text-decoration: none; }
40 a:hover { text-decoration: underline; }
41 
42-.links { margin-top: 1rem; color: #6c7086; font-size: 0.85rem; }
43+.links { margin-top: 1rem; color: #a6adc8; font-size: 0.85rem; }