Commit 4eaacc1
Eric Bower
·
2026-05-08 10:34:18 -0400 EDT
parent 6048817
fix: timing issue
1 files changed,
+45,
-38
M
main.go
M
main.go
+45,
-38
1@@ -1075,6 +1075,10 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str
2 log.Error("publish final status", "err", err)
3 }
4 }
5+ // Sync artifacts before writing sentinel — syncArtifacts skips jobs with published.json
6+ if err := syncJobArtifacts(cfg, name, jobID, log); err != nil {
7+ log.Error("sync artifacts", "err", err)
8+ }
9 // Write sentinel so we don't re-publish on subsequent ticks
10 published := map[string]interface{}{
11 "status": status,
12@@ -1464,6 +1468,46 @@ func stageArtifact(dir, name, jobID, short, content, ext string) error {
13 return os.WriteFile(path, []byte(content), 0644)
14 }
15
16+// syncJobArtifacts syncs artifacts for a single job.
17+func syncJobArtifacts(cfg *Cfg, repoName, jobID string, log *slog.Logger) error {
18+ jobDir := filepath.Join(cfg.ArtifactDir, repoName, jobID)
19+ eventPath := filepath.Join(jobDir, "event.json")
20+ data, err := os.ReadFile(eventPath)
21+ if err != nil {
22+ return fmt.Errorf("read event: %w", err)
23+ }
24+ var event Event
25+ if err := json.Unmarshal(data, &event); err != nil || event.ArtifactDest == "" {
26+ return fmt.Errorf("invalid event")
27+ }
28+ log.Debug("syncing artifacts", "repo", repoName, "job_id", jobID, "dest", event.ArtifactDest)
29+ var sshArgs string
30+ if cfg.KeyLocation != "" {
31+ certFile := ""
32+ if cfg.CertificateLocation != "" {
33+ certFile = fmt.Sprintf(" -o CertificateFile %s", cfg.CertificateLocation)
34+ }
35+ sshArgs = fmt.Sprintf("-F ~/.ssh/config -i %s%s", cfg.KeyLocation, certFile)
36+ }
37+ // Append "/" so rsync copies into the destination directory,
38+ // not as a subdirectory named after the source.
39+ dest := event.ArtifactDest
40+ if !strings.HasSuffix(dest, "/") {
41+ dest += "/"
42+ }
43+ var cmd *exec.Cmd
44+ if sshArgs != "" {
45+ cmd = exec.Command("rsync", "-e", sshArgs, "-rv", jobDir+"/", dest)
46+ } else {
47+ cmd = exec.Command("rsync", "-rv", jobDir+"/", dest)
48+ }
49+ rsyncCmd := fmt.Sprintf("rsync %s %s %s",
50+ strings.TrimLeft(cmd.Args[1], "-"),
51+ jobDir+"/", dest)
52+ log.Info("rsync", "cmd", rsyncCmd)
53+ return runCmd(cmd, log)
54+}
55+
56 func syncArtifacts(cfg *Cfg, log *slog.Logger) error {
57 entries, err := os.ReadDir(cfg.ArtifactDir)
58 if err != nil {
59@@ -1484,7 +1528,6 @@ func syncArtifacts(cfg *Cfg, log *slog.Logger) error {
60 continue
61 }
62 jobDir := filepath.Join(cfg.ArtifactDir, entry.Name(), repoEntry.Name())
63- eventPath := filepath.Join(jobDir, "event.json")
64 publishedPath := filepath.Join(jobDir, "published.json")
65
66 // Skip if already published (job is complete)
67@@ -1492,43 +1535,7 @@ func syncArtifacts(cfg *Cfg, log *slog.Logger) error {
68 continue
69 }
70
71- data, err := os.ReadFile(eventPath)
72- if err != nil {
73- continue // no event yet, skip
74- }
75- var event Event
76- if err := json.Unmarshal(data, &event); err != nil || event.ArtifactDest == "" {
77- continue
78- }
79- log.Debug("syncing artifacts", "repo", entry.Name(), "job_id", repoEntry.Name(), "dest", event.ArtifactDest)
80- var sshArgs string
81- if cfg.KeyLocation != "" {
82- certFile := ""
83- if cfg.CertificateLocation != "" {
84- certFile = fmt.Sprintf(" -o CertificateFile %s", cfg.CertificateLocation)
85- }
86- sshArgs = fmt.Sprintf("-F ~/.ssh/config -i %s%s", cfg.KeyLocation, certFile)
87- }
88- srcDir := jobDir
89- // Append "/" so rsync copies into the destination directory,
90- // not as a subdirectory named after the source.
91- dest := event.ArtifactDest
92- if !strings.HasSuffix(dest, "/") {
93- dest += "/"
94- }
95-
96- // Build rsync command, omitting -e if no ssh args
97- var cmd *exec.Cmd
98- if sshArgs != "" {
99- cmd = exec.Command("rsync", "-e", sshArgs, "-rv", srcDir+"/", dest)
100- } else {
101- cmd = exec.Command("rsync", "-rv", srcDir+"/", dest)
102- }
103- rsyncCmd := fmt.Sprintf("rsync %s %s %s",
104- strings.TrimLeft(cmd.Args[1], "-"),
105- srcDir+"/", dest)
106- log.Info("rsync", "cmd", rsyncCmd)
107- if err := runCmd(cmd, log); err != nil {
108+ if err := syncJobArtifacts(cfg, entry.Name(), repoEntry.Name(), log); err != nil {
109 log.Error("sync artifacts", "repo", entry.Name(), "job_id", repoEntry.Name(), "err", err)
110 }
111 }