Commit 4eaacc1

Eric Bower  ·  2026-05-08 10:34:18 -0400 EDT
parent 6048817
fix: timing issue
1 files changed,  +45, -38
+45, -38
......@@ -1075,6 +1075,10 @@ func monitorTick(cfg *Cfg, log *slog.Logger, output io.Writer, jobStates map[str
10751075 log.Error("publish final status", "err", err)
10761076 }
10771077 }
1078+ // Sync artifacts before writing sentinel — syncArtifacts skips jobs with published.json
1079+ if err := syncJobArtifacts(cfg, name, jobID, log); err != nil {
1080+ log.Error("sync artifacts", "err", err)
1081+ }
10781082 // Write sentinel so we don't re-publish on subsequent ticks
10791083 published := map[string]interface{}{
10801084 "status": status,
......@@ -1464,6 +1468,46 @@ func stageArtifact(dir, name, jobID, short, content, ext string) error {
14641468 return os.WriteFile(path, []byte(content), 0644)
14651469 }
14661470
1471+// syncJobArtifacts syncs artifacts for a single job.
1472+func syncJobArtifacts(cfg *Cfg, repoName, jobID string, log *slog.Logger) error {
1473+ jobDir := filepath.Join(cfg.ArtifactDir, repoName, jobID)
1474+ eventPath := filepath.Join(jobDir, "event.json")
1475+ data, err := os.ReadFile(eventPath)
1476+ if err != nil {
1477+ return fmt.Errorf("read event: %w", err)
1478+ }
1479+ var event Event
1480+ if err := json.Unmarshal(data, &event); err != nil || event.ArtifactDest == "" {
1481+ return fmt.Errorf("invalid event")
1482+ }
1483+ log.Debug("syncing artifacts", "repo", repoName, "job_id", jobID, "dest", event.ArtifactDest)
1484+ var sshArgs string
1485+ if cfg.KeyLocation != "" {
1486+ certFile := ""
1487+ if cfg.CertificateLocation != "" {
1488+ certFile = fmt.Sprintf(" -o CertificateFile %s", cfg.CertificateLocation)
1489+ }
1490+ sshArgs = fmt.Sprintf("-F ~/.ssh/config -i %s%s", cfg.KeyLocation, certFile)
1491+ }
1492+ // Append "/" so rsync copies into the destination directory,
1493+ // not as a subdirectory named after the source.
1494+ dest := event.ArtifactDest
1495+ if !strings.HasSuffix(dest, "/") {
1496+ dest += "/"
1497+ }
1498+ var cmd *exec.Cmd
1499+ if sshArgs != "" {
1500+ cmd = exec.Command("rsync", "-e", sshArgs, "-rv", jobDir+"/", dest)
1501+ } else {
1502+ cmd = exec.Command("rsync", "-rv", jobDir+"/", dest)
1503+ }
1504+ rsyncCmd := fmt.Sprintf("rsync %s %s %s",
1505+ strings.TrimLeft(cmd.Args[1], "-"),
1506+ jobDir+"/", dest)
1507+ log.Info("rsync", "cmd", rsyncCmd)
1508+ return runCmd(cmd, log)
1509+}
1510+
14671511 func syncArtifacts(cfg *Cfg, log *slog.Logger) error {
14681512 entries, err := os.ReadDir(cfg.ArtifactDir)
14691513 if err != nil {
......@@ -1484,7 +1528,6 @@ func syncArtifacts(cfg *Cfg, log *slog.Logger) error {
14841528 continue
14851529 }
14861530 jobDir := filepath.Join(cfg.ArtifactDir, entry.Name(), repoEntry.Name())
1487- eventPath := filepath.Join(jobDir, "event.json")
14881531 publishedPath := filepath.Join(jobDir, "published.json")
14891532
14901533 // Skip if already published (job is complete)
......@@ -1492,43 +1535,7 @@ func syncArtifacts(cfg *Cfg, log *slog.Logger) error {
14921535 continue
14931536 }
14941537
1495- data, err := os.ReadFile(eventPath)
1496- if err != nil {
1497- continue // no event yet, skip
1498- }
1499- var event Event
1500- if err := json.Unmarshal(data, &event); err != nil || event.ArtifactDest == "" {
1501- continue
1502- }
1503- log.Debug("syncing artifacts", "repo", entry.Name(), "job_id", repoEntry.Name(), "dest", event.ArtifactDest)
1504- var sshArgs string
1505- if cfg.KeyLocation != "" {
1506- certFile := ""
1507- if cfg.CertificateLocation != "" {
1508- certFile = fmt.Sprintf(" -o CertificateFile %s", cfg.CertificateLocation)
1509- }
1510- sshArgs = fmt.Sprintf("-F ~/.ssh/config -i %s%s", cfg.KeyLocation, certFile)
1511- }
1512- srcDir := jobDir
1513- // Append "/" so rsync copies into the destination directory,
1514- // not as a subdirectory named after the source.
1515- dest := event.ArtifactDest
1516- if !strings.HasSuffix(dest, "/") {
1517- dest += "/"
1518- }
1519-
1520- // Build rsync command, omitting -e if no ssh args
1521- var cmd *exec.Cmd
1522- if sshArgs != "" {
1523- cmd = exec.Command("rsync", "-e", sshArgs, "-rv", srcDir+"/", dest)
1524- } else {
1525- cmd = exec.Command("rsync", "-rv", srcDir+"/", dest)
1526- }
1527- rsyncCmd := fmt.Sprintf("rsync %s %s %s",
1528- strings.TrimLeft(cmd.Args[1], "-"),
1529- srcDir+"/", dest)
1530- log.Info("rsync", "cmd", rsyncCmd)
1531- if err := runCmd(cmd, log); err != nil {
1538+ if err := syncJobArtifacts(cfg, entry.Name(), repoEntry.Name(), log); err != nil {
15321539 log.Error("sync artifacts", "repo", entry.Name(), "job_id", repoEntry.Name(), "err", err)
15331540 }
15341541 }