Commit 97d87a6
Eric Bower
·
2026-05-08 15:43:31 -0400 EDT
parent 377fb0b
chore: restructure
3 files changed,
+19,
-18
M
main.go
+15,
-14
1@@ -599,10 +599,11 @@ func eventHandler(cfg *Cfg, eventData *Event) error {
2
3 // Store the event in the artifact directory so the monitor can access it
4 eventDir := filepath.Join(cfg.ArtifactDir, eventData.Name, jobID)
5- if err := os.MkdirAll(eventDir, 0755); err != nil {
6- log.Error("create event dir", "err", err)
7+ artifactsDir := filepath.Join(eventDir, "artifacts")
8+ if err := os.MkdirAll(artifactsDir, 0755); err != nil {
9+ log.Error("create artifacts dir", "err", err)
10 } else {
11- if err := os.WriteFile(filepath.Join(eventDir, "event.json"), eventBytes, 0644); err != nil {
12+ if err := os.WriteFile(filepath.Join(artifactsDir, "event.json"), eventBytes, 0644); err != nil {
13 log.Error("write event", "err", err)
14 }
15 }
16@@ -623,7 +624,7 @@ func eventHandler(cfg *Cfg, eventData *Event) error {
17 "workspace_checksum": eng.Wk.Checksum(),
18 }
19 attestationBytes, _ := json.Marshal(attestation)
20- if err := os.WriteFile(filepath.Join(eventDir, "attestation.json"), attestationBytes, 0644); err != nil {
21+ if err := os.WriteFile(filepath.Join(artifactsDir, "attestation.json"), attestationBytes, 0644); err != nil {
22 log.Error("write attestation", "err", err)
23 }
24
25@@ -1061,7 +1062,7 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str
26 log.Error("fetch history html", "session", s.Name, "err", err)
27 continue
28 }
29- if err := stageArtifact(cfg.ArtifactDir, name, jobID, filepath.Join("sessions", s.Short), html, ".html"); err != nil {
30+ if err := stageArtifact(cfg.ArtifactDir, name, jobID, s.Short, html, ".html"); err != nil {
31 log.Error("stage html artifact", "session", s.Short, "err", err)
32 }
33
34@@ -1070,7 +1071,7 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str
35 log.Error("fetch history plain", "session", s.Name, "err", err)
36 continue
37 }
38- if err := stageArtifact(cfg.ArtifactDir, name, jobID, filepath.Join("sessions", s.Short), plain, ".txt"); err != nil {
39+ if err := stageArtifact(cfg.ArtifactDir, name, jobID, s.Short, plain, ".txt"); err != nil {
40 log.Error("stage txt artifact", "session", s.Short, "err", err)
41 }
42 }
43@@ -1098,7 +1099,7 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str
44
45 if allCompleted(group) {
46 // Check sentinel — publish terminal status exactly once
47- sentinel := filepath.Join(cfg.ArtifactDir, name, jobID, "published.json")
48+ sentinel := filepath.Join(cfg.ArtifactDir, name, jobID, "artifacts", "published.json")
49 log.Debug("checking completion", "all_completed", true, "sentinel", sentinel)
50 if _, err := os.Stat(sentinel); err == nil {
51 log.Debug("terminal status already published, skipping", "sentinel", sentinel)
52@@ -1190,7 +1191,7 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str
53 // loadEvent reads the event.json for a job from the artifact directory.
54 func loadEvent(dir, name, jobID string) (Event, error) {
55 var event Event
56- data, err := os.ReadFile(filepath.Join(dir, name, jobID, "event.json"))
57+ data, err := os.ReadFile(filepath.Join(dir, name, jobID, "artifacts", "event.json"))
58 if err != nil {
59 return event, err
60 }
61@@ -1479,7 +1480,7 @@ func stageArtifact(dir, name, jobID, short, content, ext string) error {
62 // syncJobArtifacts syncs artifacts for a single job.
63 func syncJobArtifacts(cfg *Cfg, repoName, jobID string, log *slog.Logger) error {
64 jobDir := filepath.Join(cfg.ArtifactDir, repoName, jobID)
65- eventPath := filepath.Join(jobDir, "event.json")
66+ eventPath := filepath.Join(jobDir, "artifacts", "event.json")
67 data, err := os.ReadFile(eventPath)
68 if err != nil {
69 return fmt.Errorf("read event: %w", err)
70@@ -1536,7 +1537,7 @@ func syncArtifacts(cfg *Cfg, log *slog.Logger) error {
71 continue
72 }
73 jobDir := filepath.Join(cfg.ArtifactDir, entry.Name(), repoEntry.Name())
74- publishedPath := filepath.Join(jobDir, "published.json")
75+ publishedPath := filepath.Join(jobDir, "artifacts", "published.json")
76
77 // Skip if job is complete (published.json exists)
78 // In-progress jobs are synced every tick; completed jobs are skipped.
79@@ -1819,14 +1820,14 @@ func generateJobIndex(artifactDir, name, jobID string, sessions []SessionInfo) (
80 rows = append(rows, row)
81 }
82
83- // Gather artifacts by scanning the job directory (excluding sessions/)
84+ // Gather artifacts by scanning the artifacts/ subfolder
85 var artifacts []artifactRow
86- jobDir := filepath.Join(artifactDir, name, jobID)
87+ artifactsDir := filepath.Join(artifactDir, name, jobID, "artifacts")
88
89- if entries, err := os.ReadDir(jobDir); err == nil {
90+ if entries, err := os.ReadDir(artifactsDir); err == nil {
91 for _, entry := range entries {
92 if entry.IsDir() {
93- continue // skip subdirectories (e.g. sessions/)
94+ continue
95 }
96 info, err := entry.Info()
97 if err != nil {
+3,
-3
1@@ -126,8 +126,8 @@ zmx run step2 echo "hello from step2"
2
3 // Track per-session artifacts
4 for _, s := range p.Sessions {
5- htmlPath := filepath.Join(artifactDir, p.Name, p.JobID, "sessions", s.Short+".html")
6- txtPath := filepath.Join(artifactDir, p.Name, p.JobID, "sessions", s.Short+".txt")
7+ htmlPath := filepath.Join(artifactDir, p.Name, p.JobID, s.Short+".html")
8+ txtPath := filepath.Join(artifactDir, p.Name, p.JobID, s.Short+".txt")
9 if _, err := os.Stat(htmlPath); err == nil {
10 sessionArtifactShorts[s.Short+"_html"] = true
11 }
12@@ -215,7 +215,7 @@ zmx run step2 echo "hello from step2"
13
14 // 8. Assert HTML artifacts were staged for each session
15 for _, s := range finalPayload.Sessions {
16- artifactPath := filepath.Join(cfg.ArtifactDir, finalPayload.Name, finalPayload.JobID, "sessions", s.Short+".html")
17+ artifactPath := filepath.Join(cfg.ArtifactDir, finalPayload.Name, finalPayload.JobID, s.Short+".html")
18 data, err := os.ReadFile(artifactPath)
19 if err != nil {
20 t.Errorf("read artifact %s: %v", artifactPath, err)
+1,
-1
1@@ -37,7 +37,7 @@
2 <tbody>
3 {{range .Artifacts}}
4 <tr>
5- <td><a href="{{.Name}}">{{.Name}}</a></td>
6+ <td><a href="artifacts/{{.Name}}">{{.Name}}</a></td>
7 <td>{{.Size}}</td>
8 <td>{{.ModTime}}</td>
9 </tr>