Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions pkg/api/ci.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,12 @@ func CIRetryJob(ctx context.Context, token, orgID, workflowID, jobID string) (*c
}

type CIListRunsOptions struct {
Statuses []string
Limit int32
Repo string
Sha string
Statuses []string
Limit int32
Repo string
Sha string
Trigger string
PullRequest string
}

// CIListRuns returns CI runs, paginating as needed to collect up to `Limit` results.
Expand All @@ -170,6 +172,8 @@ func CIListRuns(ctx context.Context, token, orgID string, options CIListRunsOpti
PageToken: pageToken,
Repo: options.Repo,
Sha: options.Sha,
Trigger: options.Trigger,
Pr: options.PullRequest,
}
resp, err := client.ListRuns(ctx, WithAuthenticationAndOrg(connect.NewRequest(req), token, orgID))
if err != nil {
Expand Down
22 changes: 18 additions & 4 deletions pkg/api/ci_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,12 @@ func TestCIListRunsPassesFiltersAcrossPages(t *testing.T) {
t.Cleanup(func() { baseURLFunc = originalBaseURLFunc })

runs, err := CIListRuns(context.Background(), "token", "org-123", CIListRunsOptions{
Statuses: []string{"failed"},
Limit: 2,
Repo: "depot/api",
Sha: "abc123",
Statuses: []string{"failed"},
Limit: 2,
Repo: "depot/api",
Sha: "abc123",
Trigger: "workflow_dispatch",
PullRequest: "42",
})
if err != nil {
t.Fatal(err)
Expand All @@ -183,6 +185,12 @@ func TestCIListRunsPassesFiltersAcrossPages(t *testing.T) {
if first.GetSha() != "abc123" {
t.Fatalf("first Sha = %q, want abc123", first.GetSha())
}
if first.GetTrigger() != "workflow_dispatch" {
t.Fatalf("first Trigger = %q, want workflow_dispatch", first.GetTrigger())
}
if first.GetPr() != "42" {
t.Fatalf("first Pr = %q, want 42", first.GetPr())
}
if first.GetPageSize() != 2 {
t.Fatalf("first PageSize = %d, want 2", first.GetPageSize())
}
Expand All @@ -200,6 +208,12 @@ func TestCIListRunsPassesFiltersAcrossPages(t *testing.T) {
if second.GetSha() != "abc123" {
t.Fatalf("second Sha = %q, want abc123", second.GetSha())
}
if second.GetTrigger() != "workflow_dispatch" {
t.Fatalf("second Trigger = %q, want workflow_dispatch", second.GetTrigger())
}
if second.GetPr() != "42" {
t.Fatalf("second Pr = %q, want 42", second.GetPr())
}
if second.GetPageSize() != 1 {
t.Fatalf("second PageSize = %d, want 1", second.GetPageSize())
}
Expand Down
23 changes: 19 additions & 4 deletions pkg/cmd/ci/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -772,6 +772,8 @@ func NewCmdRunList() *cobra.Command {
output string
repo string
sha string
trigger string
pr string
)

cmd := &cobra.Command{
Expand All @@ -787,6 +789,12 @@ func NewCmdRunList() *cobra.Command {
# List runs for a repository and commit SHA prefix
depot ci run list --repo depot/api --sha abc123

# List failed runs for a pull request
depot ci run list --repo depot/api --status failed --pr 42

# List workflow dispatch runs
depot ci run list --trigger workflow_dispatch

# List finished and failed runs
depot ci run list --status finished --status failed

Expand Down Expand Up @@ -820,12 +828,17 @@ func NewCmdRunList() *cobra.Command {
return err
}
}
if strings.TrimSpace(pr) != "" && strings.TrimSpace(repo) == "" {
return fmt.Errorf("--repo is required when --pr is set because pull request numbers are repository-scoped")
}

runs, err := ciListRuns(ctx, tokenVal, orgID, api.CIListRunsOptions{
Statuses: statuses,
Limit: n,
Repo: repo,
Sha: sha,
Statuses: statuses,
Limit: n,
Repo: repo,
Sha: sha,
Trigger: trigger,
PullRequest: pr,
})
if err != nil {
return fmt.Errorf("failed to list runs: %w", err)
Expand Down Expand Up @@ -891,6 +904,8 @@ func NewCmdRunList() *cobra.Command {
cmd.Flags().StringSliceVar(&statuses, "status", nil, "Filter by status (repeatable: queued, running, finished, failed, cancelled)")
cmd.Flags().StringVar(&repo, "repo", "", "Filter by repository (owner/repo)")
cmd.Flags().StringVar(&sha, "sha", "", "Filter by commit SHA prefix")
cmd.Flags().StringVar(&trigger, "trigger", "", "Filter by trigger, e.g. push or workflow_dispatch")
cmd.Flags().StringVar(&pr, "pr", "", "Filter by pull request number (requires --repo)")
cmd.Flags().Int32VarP(&n, "n", "n", 50, "Number of runs to return")
cmd.Flags().StringVarP(&output, "output", "o", "", "Output format (json)")

Expand Down
39 changes: 38 additions & 1 deletion pkg/cmd/ci/run_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ func captureStdout(t *testing.T, fn func() error) (string, error) {
return string(out), runErr
}

func TestRunListPassesRepoAndShaFilters(t *testing.T) {
func TestRunListPassesRecentDiscoveryFilters(t *testing.T) {
t.Setenv("DEPOT_TOKEN", "token-from-env")

originalCIListRuns := ciListRuns
Expand Down Expand Up @@ -67,6 +67,8 @@ func TestRunListPassesRepoAndShaFilters(t *testing.T) {
"--org", "org-123",
"--repo", "depot/api",
"--sha", "ABC123",
"--trigger", "workflow_dispatch",
"--pr", "42",
"--status", "failed",
"--output", "json",
})
Expand All @@ -90,6 +92,12 @@ func TestRunListPassesRepoAndShaFilters(t *testing.T) {
if capturedOptions.Sha != "ABC123" {
t.Fatalf("Sha = %q, want ABC123", capturedOptions.Sha)
}
if capturedOptions.Trigger != "workflow_dispatch" {
t.Fatalf("Trigger = %q, want workflow_dispatch", capturedOptions.Trigger)
}
if capturedOptions.PullRequest != "42" {
t.Fatalf("PullRequest = %q, want 42", capturedOptions.PullRequest)
}
if capturedOptions.Limit != 50 {
t.Fatalf("Limit = %d, want 50", capturedOptions.Limit)
}
Expand All @@ -106,3 +114,32 @@ func TestRunListPassesRepoAndShaFilters(t *testing.T) {
t.Fatalf("JSON output missing status field:\n%s", stdout)
}
}

func TestRunListRequiresRepoWithPullRequestFilter(t *testing.T) {
t.Setenv("DEPOT_TOKEN", "token-from-env")

originalCIListRuns := ciListRuns
t.Cleanup(func() { ciListRuns = originalCIListRuns })

ciListRuns = func(ctx context.Context, token, orgID string, options api.CIListRunsOptions) ([]*civ1.ListRunsResponseRun, error) {
t.Fatal("ciListRuns should not be called when --pr is missing --repo")
return nil, nil
}

cmd := NewCmdRunList()
cmd.SetArgs([]string{
"--org", "org-123",
"--pr", "42",
"--status", "failed",
})
cmd.SetOut(io.Discard)
cmd.SetErr(io.Discard)

err := cmd.Execute()
if err == nil {
t.Fatal("expected error")
}
if !strings.Contains(err.Error(), "--repo is required when --pr is set") {
t.Fatalf("error = %q, want missing repo message", err)
}
}
Loading
Loading