Skip to content

Commit ecc73be

Browse files
committed
Fix: disable interactive TUI picker when --output-file is set
When --output-file is used, the command is intended for non-interactive use (keeping stdout clean for callers). Previously, the interactive job picker could still activate if there were multiple ambiguous jobs, causing scripts to hang waiting for input. This fix ensures that logTargetResolutionOptionsForOutput also checks if outputFile is set and disables interactive mode accordingly, just like it does for JSON output mode.
1 parent 8db1e71 commit ecc73be

2 files changed

Lines changed: 32 additions & 4 deletions

File tree

pkg/cmd/ci/logs.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ ID, use --job and --workflow to disambiguate by workflow job key.`,
129129
reporter := newLogFollowReporter(reporterWriter, reporterInteractive)
130130

131131
// First, try resolving as a run ID (or job ID — the API accepts both).
132-
resolutionOptions := logTargetResolutionOptionsForOutput(outputOptions)
132+
resolutionOptions := logTargetResolutionOptionsForOutput(outputOptions, outputFile)
133133
resp, runErr := ciGetRunStatus(ctx, tokenVal, orgID, id)
134134
if runErr == nil {
135135
target, err := resolveLogTargetWithOptions(resp, id, job, workflow, resolutionOptions)
@@ -807,8 +807,8 @@ type logTargetResolutionOptions struct {
807807
allowInteractive bool
808808
}
809809

810-
func logTargetResolutionOptionsForOutput(outputOptions logOutputOptions) logTargetResolutionOptions {
811-
return logTargetResolutionOptions{allowInteractive: !outputOptions.json()}
810+
func logTargetResolutionOptionsForOutput(outputOptions logOutputOptions, outputFile string) logTargetResolutionOptions {
811+
return logTargetResolutionOptions{allowInteractive: !outputOptions.json() && outputFile == ""}
812812
}
813813

814814
// jobKeyShort returns the short form of a job key (after the first colon),

pkg/cmd/ci/logs_test.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ func TestResolveLogTargetJSONOptionsReturnNonInteractiveAmbiguity(t *testing.T)
7575
},
7676
}
7777

78-
options := logTargetResolutionOptionsForOutput(logOutputOptions{output: logOutputJSON})
78+
options := logTargetResolutionOptionsForOutput(logOutputOptions{output: logOutputJSON}, "")
7979
if options.allowInteractive {
8080
t.Fatal("json output should disable interactive job resolution")
8181
}
@@ -89,6 +89,34 @@ func TestResolveLogTargetJSONOptionsReturnNonInteractiveAmbiguity(t *testing.T)
8989
}
9090
}
9191

92+
func TestResolveLogTargetOutputFileOptionsReturnNonInteractiveAmbiguity(t *testing.T) {
93+
resp := &civ1.GetRunStatusResponse{
94+
RunId: "run-1",
95+
Workflows: []*civ1.WorkflowStatus{
96+
{
97+
WorkflowPath: ".depot/workflows/ci.yml",
98+
Jobs: []*civ1.JobStatus{
99+
{JobId: "job-1", JobKey: "build", Status: "finished"},
100+
{JobId: "job-2", JobKey: "test", Status: "running"},
101+
},
102+
},
103+
},
104+
}
105+
106+
options := logTargetResolutionOptionsForOutput(logOutputOptions{output: logOutputText}, "/tmp/logs.txt")
107+
if options.allowInteractive {
108+
t.Fatal("output-file should disable interactive job resolution")
109+
}
110+
111+
_, err := resolveLogTargetWithOptions(resp, "run-1", "", "", options)
112+
if err == nil {
113+
t.Fatal("expected ambiguity error")
114+
}
115+
if !strings.Contains(err.Error(), "run has multiple jobs, specify one with --job") {
116+
t.Fatalf("expected multiple-jobs ambiguity error, got: %v", err)
117+
}
118+
}
119+
92120
func TestFindLogsJob_MatchByJobKey(t *testing.T) {
93121
resp := &civ1.GetRunStatusResponse{
94122
RunId: "run-1",

0 commit comments

Comments
 (0)