Commit a0e7733
Eric Bower
·
2026-08-18 11:48:07 -0400 EDT
parent b4c6cdb
fix: pici runner defaulting to ci. not local.
3 files changed,
+77,
-12
M
main.go
+14,
-7
| ... | ... | @@ -798,6 +798,7 @@ type JobEngine struct { | |
| 798 | 798 | Cfg *Cfg | |
| 799 | 799 | Ev *Event | |
| 800 | 800 | JobID string | |
| 801 | + | Domain string | |
| 801 | 802 | } | |
| 802 | 803 | ||
| 803 | 804 | type SessionInfo struct { |
| ... | ... | @@ -838,7 +839,9 @@ func getDomain(eventType string) string { | |
| 838 | 839 | ||
| 839 | 840 | func (eng *JobEngine) Run(manifest string) error { | |
| 840 | 841 | domain := "ci" | |
| 841 | - | if eng.Ev != nil { | |
| 842 | + | if eng.Domain != "" { | |
| 843 | + | domain = eng.Domain | |
| 844 | + | } else if eng.Ev != nil { | |
| 842 | 845 | domain = getDomain(eng.Ev.Type) | |
| 843 | 846 | } | |
| 844 | 847 | prefix := fmt.Sprintf("%s.%s.%s.", domain, eng.Ev.Name, eng.JobID) |
| ... | ... | @@ -936,6 +939,7 @@ func eventHandler(cfg *Cfg, eventData *Event) error { | |
| 936 | 939 | Wk: wk, | |
| 937 | 940 | Ev: eventData, | |
| 938 | 941 | JobID: jobID, | |
| 942 | + | Domain: domain, | |
| 939 | 943 | } | |
| 940 | 944 | var runErr error | |
| 941 | 945 | defer func() { |
| ... | ... | @@ -2421,6 +2425,7 @@ func runLocal(cfg *Cfg, dest string) error { | |
| 2421 | 2425 | Wk: wk, | |
| 2422 | 2426 | Ev: eventData, | |
| 2423 | 2427 | JobID: jobID, | |
| 2428 | + | Domain: "local", | |
| 2424 | 2429 | } | |
| 2425 | 2430 | ||
| 2426 | 2431 | defer func() { |
| ... | ... | @@ -2480,12 +2485,12 @@ func runLocal(cfg *Cfg, dest string) error { | |
| 2480 | 2485 | ||
| 2481 | 2486 | // Wait for completion & print live progress | |
| 2482 | 2487 | var waitErr error | |
| 2483 | - | if err := waitAndReport(cfg, log, eventData.Name, jobID, eventData.Type); err != nil { | |
| 2488 | + | if err := waitAndReport(cfg, log, eventData.Name, jobID, "local"); err != nil { | |
| 2484 | 2489 | waitErr = err | |
| 2485 | 2490 | } | |
| 2486 | 2491 | ||
| 2487 | 2492 | // Generate and stage full HTML/txt artifacts and index | |
| 2488 | - | if err := stageLocalArtifacts(cfg, log, eventData.Name, jobID, eventData.Type); err != nil { | |
| 2493 | + | if err := stageLocalArtifacts(cfg, log, eventData.Name, jobID, "local"); err != nil { | |
| 2489 | 2494 | log.Error("stage local artifacts", "err", err) | |
| 2490 | 2495 | } | |
| 2491 | 2496 |
| ... | ... | @@ -2502,8 +2507,7 @@ func runLocal(cfg *Cfg, dest string) error { | |
| 2502 | 2507 | } | |
| 2503 | 2508 | ||
| 2504 | 2509 | // Write published sentinel for local run (`pici`) | |
| 2505 | - | domain := getDomain(eventData.Type) | |
| 2506 | - | prefix := fmt.Sprintf("%s.%s.%s.", domain, eventData.Name, jobID) | |
| 2510 | + | prefix := fmt.Sprintf("local.%s.%s.", eventData.Name, jobID) | |
| 2507 | 2511 | if listOutput, err := exec.Command("zmx", "list").CombinedOutput(); err == nil { | |
| 2508 | 2512 | sessions := parseZMXList(string(listOutput)) | |
| 2509 | 2513 | var jobSessions []SessionInfo |
| ... | ... | @@ -2542,8 +2546,11 @@ func writePublishedSentinel(artifactDir, repoName, jobID, status string, exitCod | |
| 2542 | 2546 | return os.WriteFile(sentinel, publishedJSON, 0644) | |
| 2543 | 2547 | } | |
| 2544 | 2548 | ||
| 2545 | - | func stageLocalArtifacts(cfg *Cfg, log *slog.Logger, repoName, jobID, eventType string) error { | |
| 2546 | - | domain := getDomain(eventType) | |
| 2549 | + | func stageLocalArtifacts(cfg *Cfg, log *slog.Logger, repoName, jobID, domainOrEvent string) error { | |
| 2550 | + | domain := domainOrEvent | |
| 2551 | + | if domain != "local" && domain != "ci" { | |
| 2552 | + | domain = getDomain(domainOrEvent) | |
| 2553 | + | } | |
| 2547 | 2554 | prefix := fmt.Sprintf("%s.%s.%s.", domain, repoName, jobID) | |
| 2548 | 2555 | ||
| 2549 | 2556 | listOutput, err := exec.Command("zmx", "list").CombinedOutput() |
+49,
-0
| ... | ... | @@ -858,6 +858,55 @@ echo "hello from pico" | |
| 858 | 858 | } | |
| 859 | 859 | } | |
| 860 | 860 | ||
| 861 | + | func TestRunLocal_CustomPiciEvent_UsesLocalPrefix(t *testing.T) { | |
| 862 | + | if _, err := exec.LookPath("zmx"); err != nil { | |
| 863 | + | t.Skip("zmx not found, skipping test") | |
| 864 | + | } | |
| 865 | + | ||
| 866 | + | tempDir := t.TempDir() | |
| 867 | + | workDir := filepath.Join(tempDir, "event-repo") | |
| 868 | + | if err := os.MkdirAll(workDir, 0755); err != nil { | |
| 869 | + | t.Fatal(err) | |
| 870 | + | } | |
| 871 | + | origWd, _ := os.Getwd() | |
| 872 | + | defer func() { _ = os.Chdir(origWd) }() | |
| 873 | + | _ = os.Chdir(workDir) | |
| 874 | + | ||
| 875 | + | picoContent := `#!/usr/bin/env bash | |
| 876 | + | set -euo pipefail | |
| 877 | + | echo "PICI_EVENT=$PICI_EVENT" > event_out.txt | |
| 878 | + | echo "ZMX_SESSION_PREFIX=$ZMX_SESSION_PREFIX" >> event_out.txt | |
| 879 | + | ` | |
| 880 | + | if err := os.WriteFile("pico.sh", []byte(picoContent), 0755); err != nil { | |
| 881 | + | t.Fatal(err) | |
| 882 | + | } | |
| 883 | + | ||
| 884 | + | artifactDir := t.TempDir() | |
| 885 | + | cfg := &Cfg{ | |
| 886 | + | ArtifactDir: artifactDir, | |
| 887 | + | MonitorInterval: 100 * time.Millisecond, | |
| 888 | + | InPlace: true, | |
| 889 | + | EnvVars: envList{"PICI_EVENT=git.tag"}, | |
| 890 | + | } | |
| 891 | + | ||
| 892 | + | err := runLocal(cfg, "") | |
| 893 | + | if err != nil { | |
| 894 | + | t.Fatalf("expected runLocal to succeed, got %v", err) | |
| 895 | + | } | |
| 896 | + | ||
| 897 | + | data, err := os.ReadFile(filepath.Join(workDir, "event_out.txt")) | |
| 898 | + | if err != nil { | |
| 899 | + | t.Fatalf("failed to read event_out.txt: %v", err) | |
| 900 | + | } | |
| 901 | + | content := string(data) | |
| 902 | + | if !strings.Contains(content, "PICI_EVENT=git.tag") { | |
| 903 | + | t.Errorf("expected PICI_EVENT=git.tag in pico.sh environment, got: %s", content) | |
| 904 | + | } | |
| 905 | + | if !strings.Contains(content, "ZMX_SESSION_PREFIX=\"local.event-repo.") && !strings.Contains(content, "ZMX_SESSION_PREFIX=local.event-repo.") { | |
| 906 | + | t.Errorf("expected ZMX_SESSION_PREFIX to have local. prefix, got: %s", content) | |
| 907 | + | } | |
| 908 | + | } | |
| 909 | + | ||
| 861 | 910 | func TestDetectGitCommit(t *testing.T) { | |
| 862 | 911 | cwd, err := os.Getwd() | |
| 863 | 912 | if err != nil { |
+14,
-5
| ... | ... | @@ -43,6 +43,7 @@ type TaskUIState struct { | |
| 43 | 43 | ||
| 44 | 44 | type PipelineUIState struct { | |
| 45 | 45 | Repo string | |
| 46 | + | Domain string | |
| 46 | 47 | Branch string | |
| 47 | 48 | Commit string | |
| 48 | 49 | JobID string |
| ... | ... | @@ -479,13 +480,17 @@ func (ui *PipelineUIState) RenderSummary(reportPath string, exitCode int) string | |
| 479 | 480 | if reportPath != "" { | |
| 480 | 481 | fmt.Fprintf(&sb, " 📄 Report: %s\n", reportPath) | |
| 481 | 482 | } | |
| 483 | + | domain := ui.Domain | |
| 484 | + | if domain == "" { | |
| 485 | + | domain = "local" | |
| 486 | + | } | |
| 482 | 487 | if failedCount > 0 { | |
| 483 | 488 | if len(failedTasks) > 0 { | |
| 484 | 489 | for _, ft := range failedTasks { | |
| 485 | - | fmt.Fprintf(&sb, " 🔍 Debug: zmx attach local.%s.%s.step.%s\n", ui.Repo, ui.JobID, ft.Name) | |
| 490 | + | fmt.Fprintf(&sb, " 🔍 Debug: zmx attach %s.%s.%s.step.%s\n", domain, ui.Repo, ui.JobID, ft.Name) | |
| 486 | 491 | } | |
| 487 | 492 | } else { | |
| 488 | - | fmt.Fprintf(&sb, " 🔍 Debug: zmx attach local.%s.%s.runner\n", ui.Repo, ui.JobID) | |
| 493 | + | fmt.Fprintf(&sb, " 🔍 Debug: zmx attach %s.%s.%s.runner\n", domain, ui.Repo, ui.JobID) | |
| 489 | 494 | } | |
| 490 | 495 | } | |
| 491 | 496 |
| ... | ... | @@ -742,14 +747,18 @@ func isTerminal(w io.Writer) bool { | |
| 742 | 747 | } | |
| 743 | 748 | ||
| 744 | 749 | // waitAndReportUI executes the rich interactive reporting loop, updating stats.json. | |
| 745 | - | func waitAndReportUI(cfg *Cfg, log *slog.Logger, repoName, jobID, eventType, branch, commit string) error { | |
| 746 | - | domain := getDomain(eventType) | |
| 750 | + | func waitAndReportUI(cfg *Cfg, log *slog.Logger, repoName, jobID, domainOrEvent, branch, commit string) error { | |
| 751 | + | domain := domainOrEvent | |
| 752 | + | if domain != "local" && domain != "ci" { | |
| 753 | + | domain = getDomain(domainOrEvent) | |
| 754 | + | } | |
| 747 | 755 | prefix := fmt.Sprintf("%s.%s.%s.", domain, repoName, jobID) | |
| 748 | 756 | ||
| 749 | 757 | stats, _ := loadRepoStats(repoName) | |
| 750 | 758 | isTTY := isTerminal(os.Stdout) | |
| 751 | 759 | ||
| 752 | 760 | ctrl := newInteractiveController(cfg.Ctx, os.Stdout, repoName, branch, commit, jobID, stats, isTTY) | |
| 761 | + | ctrl.ui.Domain = domain | |
| 753 | 762 | ||
| 754 | 763 | lastStage := time.Now() | |
| 755 | 764 |
| ... | ... | @@ -796,7 +805,7 @@ func waitAndReportUI(cfg *Cfg, log *slog.Logger, repoName, jobID, eventType, bra | |
| 796 | 805 | ||
| 797 | 806 | // Stage local artifacts periodically (every 2 seconds) so reports stay updated live without disk trashing | |
| 798 | 807 | if time.Since(lastStage) >= 2*time.Second { | |
| 799 | - | _ = stageLocalArtifacts(cfg, log, repoName, jobID, eventType) | |
| 808 | + | _ = stageLocalArtifacts(cfg, log, repoName, jobID, domain) | |
| 800 | 809 | lastStage = time.Now() | |
| 801 | 810 | } | |
| 802 | 811 |