From 852bc0035474026cc95e842d0708ba251403429a Mon Sep 17 00:00:00 2001 From: Alex Petrov Date: Wed, 29 Mar 2023 18:39:11 -0400 Subject: [PATCH 1/2] feat: allow filtering workflow runs by statuses --- pkg/cmd/run/list/list.go | 3 +++ pkg/cmd/run/list/list_test.go | 25 +++++++++++++++++++++++++ pkg/cmd/run/shared/shared.go | 21 +++++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/pkg/cmd/run/list/list.go b/pkg/cmd/run/list/list.go index 2b2b78109..4b085a1a1 100644 --- a/pkg/cmd/run/list/list.go +++ b/pkg/cmd/run/list/list.go @@ -31,6 +31,7 @@ type ListOptions struct { WorkflowSelector string Branch string Actor string + Status string now time.Time } @@ -67,6 +68,7 @@ func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Comman cmd.Flags().StringVarP(&opts.WorkflowSelector, "workflow", "w", "", "Filter runs by workflow") cmd.Flags().StringVarP(&opts.Branch, "branch", "b", "", "Filter runs by branch") cmd.Flags().StringVarP(&opts.Actor, "user", "u", "", "Filter runs by user who triggered the run") + cmdutil.StringEnumFlag(cmd, &opts.Status, "status", "s", "", shared.AllStatuses, "Filter runs by status") cmdutil.AddJSONFlags(cmd, &opts.Exporter, shared.RunFields) _ = cmdutil.RegisterBranchCompletionFlags(f.GitClient, cmd, "branch") @@ -89,6 +91,7 @@ func listRun(opts *ListOptions) error { filters := &shared.FilterOptions{ Branch: opts.Branch, Actor: opts.Actor, + Status: opts.Status, } opts.IO.StartProgressIndicator() diff --git a/pkg/cmd/run/list/list_test.go b/pkg/cmd/run/list/list_test.go index aa7fe993c..96a9ab912 100644 --- a/pkg/cmd/run/list/list_test.go +++ b/pkg/cmd/run/list/list_test.go @@ -69,6 +69,14 @@ func TestNewCmdList(t *testing.T) { Actor: "bak1an", }, }, + { + name: "status", + cli: "--status completed", + wants: ListOptions{ + Limit: defaultLimit, + Status: "completed", + }, + }, } for _, tt := range tests { @@ -394,6 +402,23 @@ func TestListRun(t *testing.T) { }, wantErr: true, }, + { + name: "status filter applied", + opts: &ListOptions{ + Limit: defaultLimit, + Status: "queued", + }, + isTTY: true, + stubs: func(reg *httpmock.Registry) { + reg.Register( + httpmock.QueryMatcher("GET", "repos/OWNER/REPO/actions/runs", url.Values{ + "status": []string{"queued"}, + }), + httpmock.JSONResponse(shared.RunsPayload{}), + ) + }, + wantErr: true, + }, } for _, tt := range tests { diff --git a/pkg/cmd/run/shared/shared.go b/pkg/cmd/run/shared/shared.go index db347eee5..a165f94a3 100644 --- a/pkg/cmd/run/shared/shared.go +++ b/pkg/cmd/run/shared/shared.go @@ -44,6 +44,23 @@ type Status string type Conclusion string type Level string +var AllStatuses = []string{ + "queued", + "completed", + "in_progress", + "requested", + "waiting", + "action_required", + "cancelled", + "failure", + "neutral", + "skipped", + "stale", + "startup_failure", + "success", + "timed_out", +} + var RunFields = []string{ "name", "displayTitle", @@ -284,6 +301,7 @@ type FilterOptions struct { WorkflowID int64 // avoid loading workflow name separately and use the provided one WorkflowName string + Status string } // GetRunsWithFilter fetches 50 runs from the API and filters them in-memory @@ -326,6 +344,9 @@ func GetRuns(client *api.Client, repo ghrepo.Interface, opts *FilterOptions, lim if opts.Actor != "" { path += fmt.Sprintf("&actor=%s", url.QueryEscape(opts.Actor)) } + if opts.Status != "" { + path += fmt.Sprintf("&status=%s", url.QueryEscape(opts.Status)) + } } var result *RunsPayload From 1fb12a98ea8afcf4dc7a1bf1b4b3a2da8b2d3b4a Mon Sep 17 00:00:00 2001 From: nate smith Date: Wed, 29 Mar 2023 06:25:35 -0700 Subject: [PATCH 2/2] improve test resiliency --- pkg/cmd/run/list/list_test.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/pkg/cmd/run/list/list_test.go b/pkg/cmd/run/list/list_test.go index 96a9ab912..d33af7167 100644 --- a/pkg/cmd/run/list/list_test.go +++ b/pkg/cmd/run/list/list_test.go @@ -123,6 +123,7 @@ func TestListRun(t *testing.T) { wantErr bool wantOut string wantErrOut string + wantErrMsg string stubs func(*httpmock.Registry) isTTY bool }{ @@ -343,7 +344,8 @@ func TestListRun(t *testing.T) { httpmock.JSONResponse(shared.RunsPayload{}), ) }, - wantErr: true, + wantErr: true, + wantErrMsg: "no runs found", }, { name: "workflow selector", @@ -384,7 +386,8 @@ func TestListRun(t *testing.T) { httpmock.JSONResponse(shared.RunsPayload{}), ) }, - wantErr: true, + wantErr: true, + wantErrMsg: "no runs found", }, { name: "actor filter applied", @@ -400,7 +403,8 @@ func TestListRun(t *testing.T) { httpmock.JSONResponse(shared.RunsPayload{}), ) }, - wantErr: true, + wantErr: true, + wantErrMsg: "no runs found", }, { name: "status filter applied", @@ -417,7 +421,8 @@ func TestListRun(t *testing.T) { httpmock.JSONResponse(shared.RunsPayload{}), ) }, - wantErr: true, + wantErr: true, + wantErrMsg: "no runs found", }, } @@ -441,6 +446,7 @@ func TestListRun(t *testing.T) { err := listRun(tt.opts) if tt.wantErr { assert.Error(t, err) + assert.Equal(t, tt.wantErrMsg, err.Error()) } else { assert.NoError(t, err) }