X Tutup
Skip to content

Commit e28fa3c

Browse files
bak1ansamcoe
andauthored
Add branch and actor filters to run list (cli#4100)
* Add branch and actor filters to `run list` * Simplify what FilterOptions can do * Check not only limit in TestNewCmdList * Verify that branch/actor params are parsed properly * Verify that API requests have proper query parameters * Change flag name from actor to user Co-authored-by: Sam Coe <samcoe@users.noreply.github.com>
1 parent a564909 commit e28fa3c

File tree

7 files changed

+107
-13
lines changed

7 files changed

+107
-13
lines changed

pkg/cmd/run/cancel/cancel.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ func runCancel(opts *CancelOptions) error {
7474
var run *shared.Run
7575

7676
if opts.Prompt {
77-
runs, err := shared.GetRunsWithFilter(client, repo, 10, func(run shared.Run) bool {
77+
runs, err := shared.GetRunsWithFilter(client, repo, nil, 10, func(run shared.Run) bool {
7878
return run.Status != shared.Completed
7979
})
8080
if err != nil {

pkg/cmd/run/list/list.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ type ListOptions struct {
2929

3030
Limit int
3131
WorkflowSelector string
32+
Branch string
33+
Actor string
3234
}
3335

3436
func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Command {
@@ -62,6 +64,8 @@ func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Comman
6264

6365
cmd.Flags().IntVarP(&opts.Limit, "limit", "L", defaultLimit, "Maximum number of runs to fetch")
6466
cmd.Flags().StringVarP(&opts.WorkflowSelector, "workflow", "w", "", "Filter runs by workflow")
67+
cmd.Flags().StringVarP(&opts.Branch, "branch", "b", "", "Filter runs by branch")
68+
cmd.Flags().StringVarP(&opts.Actor, "user", "u", "", "Filter runs by user who triggered the run")
6569
cmdutil.AddJSONFlags(cmd, &opts.Exporter, shared.RunFields)
6670

6771
return cmd
@@ -82,16 +86,21 @@ func listRun(opts *ListOptions) error {
8286
var runs []shared.Run
8387
var workflow *workflowShared.Workflow
8488

89+
filters := &shared.FilterOptions{
90+
Branch: opts.Branch,
91+
Actor: opts.Actor,
92+
}
93+
8594
opts.IO.StartProgressIndicator()
8695
if opts.WorkflowSelector != "" {
8796
states := []workflowShared.WorkflowState{workflowShared.Active}
8897
workflow, err = workflowShared.ResolveWorkflow(
8998
opts.IO, client, baseRepo, false, opts.WorkflowSelector, states)
9099
if err == nil {
91-
runs, err = shared.GetRunsByWorkflow(client, baseRepo, opts.Limit, workflow.ID)
100+
runs, err = shared.GetRunsByWorkflow(client, baseRepo, filters, opts.Limit, workflow.ID)
92101
}
93102
} else {
94-
runs, err = shared.GetRuns(client, baseRepo, opts.Limit)
103+
runs, err = shared.GetRuns(client, baseRepo, filters, opts.Limit)
95104
}
96105
opts.IO.StopProgressIndicator()
97106
if err != nil {

pkg/cmd/run/list/list_test.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"io/ioutil"
77
"net/http"
8+
"net/url"
89
"testing"
910

1011
"github.com/cli/cli/v2/internal/ghrepo"
@@ -51,6 +52,22 @@ func TestNewCmdList(t *testing.T) {
5152
WorkflowSelector: "foo.yml",
5253
},
5354
},
55+
{
56+
name: "branch",
57+
cli: "--branch new-cool-stuff",
58+
wants: ListOptions{
59+
Limit: defaultLimit,
60+
Branch: "new-cool-stuff",
61+
},
62+
},
63+
{
64+
name: "user",
65+
cli: "--user bak1an",
66+
wants: ListOptions{
67+
Limit: defaultLimit,
68+
Actor: "bak1an",
69+
},
70+
},
5471
}
5572

5673
for _, tt := range tests {
@@ -83,11 +100,32 @@ func TestNewCmdList(t *testing.T) {
83100
}
84101

85102
assert.Equal(t, tt.wants.Limit, gotOpts.Limit)
103+
assert.Equal(t, tt.wants.WorkflowSelector, gotOpts.WorkflowSelector)
104+
assert.Equal(t, tt.wants.Branch, gotOpts.Branch)
105+
assert.Equal(t, tt.wants.Actor, gotOpts.Actor)
86106
})
87107
}
88108
}
89109

90110
func TestListRun(t *testing.T) {
111+
// helper to match mocked requests by their query params along with method and path
112+
queryMatcher := func(method string, path string, query url.Values) httpmock.Matcher {
113+
return func(req *http.Request) bool {
114+
if !httpmock.REST(method, path)(req) {
115+
return false
116+
}
117+
118+
actualQuery := req.URL.Query()
119+
120+
for param := range query {
121+
if !(actualQuery.Get(param) == query.Get(param)) {
122+
return false
123+
}
124+
}
125+
126+
return true
127+
}
128+
}
91129
tests := []struct {
92130
name string
93131
opts *ListOptions
@@ -198,6 +236,40 @@ func TestListRun(t *testing.T) {
198236
},
199237
wantOut: "STATUS NAME WORKFLOW BRANCH EVENT ID ELAPSED AGE\n* cool commit in progress trunk push 2 4m34s Feb 23, 2021\n✓ cool commit successful trunk push 3 4m34s Feb 23, 2021\nX cool commit failed trunk push 1234 4m34s Feb 23, 2021\n\nFor details on a run, try: gh run view <run-id>\n",
200238
},
239+
{
240+
name: "branch filter applied",
241+
opts: &ListOptions{
242+
Limit: defaultLimit,
243+
Branch: "the-branch",
244+
},
245+
stubs: func(reg *httpmock.Registry) {
246+
reg.Register(
247+
queryMatcher("GET", "repos/OWNER/REPO/actions/runs", url.Values{
248+
"branch": []string{"the-branch"},
249+
}),
250+
httpmock.JSONResponse(shared.RunsPayload{}),
251+
)
252+
},
253+
wantOut: "",
254+
wantErrOut: "No runs found\n",
255+
},
256+
{
257+
name: "actor filter applied",
258+
opts: &ListOptions{
259+
Limit: defaultLimit,
260+
Actor: "bak1an",
261+
},
262+
stubs: func(reg *httpmock.Registry) {
263+
reg.Register(
264+
queryMatcher("GET", "repos/OWNER/REPO/actions/runs", url.Values{
265+
"actor": []string{"bak1an"},
266+
}),
267+
httpmock.JSONResponse(shared.RunsPayload{}),
268+
)
269+
},
270+
wantOut: "",
271+
wantErrOut: "No runs found\n",
272+
},
201273
}
202274

203275
for _, tt := range tests {

pkg/cmd/run/rerun/rerun.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ func runRerun(opts *RerunOptions) error {
7171

7272
if opts.Prompt {
7373
cs := opts.IO.ColorScheme()
74-
runs, err := shared.GetRunsWithFilter(client, repo, 10, func(run shared.Run) bool {
74+
runs, err := shared.GetRunsWithFilter(client, repo, nil, 10, func(run shared.Run) bool {
7575
if run.Status != shared.Completed {
7676
return false
7777
}

pkg/cmd/run/shared/shared.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -205,9 +205,14 @@ type RunsPayload struct {
205205
WorkflowRuns []Run `json:"workflow_runs"`
206206
}
207207

208-
func GetRunsWithFilter(client *api.Client, repo ghrepo.Interface, limit int, f func(Run) bool) ([]Run, error) {
208+
type FilterOptions struct {
209+
Branch string
210+
Actor string
211+
}
212+
213+
func GetRunsWithFilter(client *api.Client, repo ghrepo.Interface, opts *FilterOptions, limit int, f func(Run) bool) ([]Run, error) {
209214
path := fmt.Sprintf("repos/%s/actions/runs", ghrepo.FullName(repo))
210-
runs, err := getRuns(client, repo, path, 50)
215+
runs, err := getRuns(client, repo, path, opts, 50)
211216
if err != nil {
212217
return nil, err
213218
}
@@ -224,17 +229,17 @@ func GetRunsWithFilter(client *api.Client, repo ghrepo.Interface, limit int, f f
224229
return filtered, nil
225230
}
226231

227-
func GetRunsByWorkflow(client *api.Client, repo ghrepo.Interface, limit int, workflowID int64) ([]Run, error) {
232+
func GetRunsByWorkflow(client *api.Client, repo ghrepo.Interface, opts *FilterOptions, limit int, workflowID int64) ([]Run, error) {
228233
path := fmt.Sprintf("repos/%s/actions/workflows/%d/runs", ghrepo.FullName(repo), workflowID)
229-
return getRuns(client, repo, path, limit)
234+
return getRuns(client, repo, path, opts, limit)
230235
}
231236

232-
func GetRuns(client *api.Client, repo ghrepo.Interface, limit int) ([]Run, error) {
237+
func GetRuns(client *api.Client, repo ghrepo.Interface, opts *FilterOptions, limit int) ([]Run, error) {
233238
path := fmt.Sprintf("repos/%s/actions/runs", ghrepo.FullName(repo))
234-
return getRuns(client, repo, path, limit)
239+
return getRuns(client, repo, path, opts, limit)
235240
}
236241

237-
func getRuns(client *api.Client, repo ghrepo.Interface, path string, limit int) ([]Run, error) {
242+
func getRuns(client *api.Client, repo ghrepo.Interface, path string, opts *FilterOptions, limit int) ([]Run, error) {
238243
perPage := limit
239244
page := 1
240245
if limit > 100 {
@@ -253,6 +258,14 @@ func getRuns(client *api.Client, repo ghrepo.Interface, path string, limit int)
253258
query := parsed.Query()
254259
query.Set("per_page", fmt.Sprintf("%d", perPage))
255260
query.Set("page", fmt.Sprintf("%d", page))
261+
if opts != nil {
262+
if opts.Branch != "" {
263+
query.Set("branch", opts.Branch)
264+
}
265+
if opts.Actor != "" {
266+
query.Set("actor", opts.Actor)
267+
}
268+
}
256269
parsed.RawQuery = query.Encode()
257270
pagedPath := parsed.String()
258271

pkg/cmd/run/view/view.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ func runView(opts *ViewOptions) error {
197197
if opts.Prompt {
198198
// TODO arbitrary limit
199199
opts.IO.StartProgressIndicator()
200-
runs, err := shared.GetRuns(client, repo, 10)
200+
runs, err := shared.GetRuns(client, repo, nil, 10)
201201
opts.IO.StopProgressIndicator()
202202
if err != nil {
203203
return fmt.Errorf("failed to get runs: %w", err)

pkg/cmd/run/watch/watch.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func watchRun(opts *WatchOptions) error {
9393
var run *shared.Run
9494

9595
if opts.Prompt {
96-
runs, err := shared.GetRunsWithFilter(client, repo, 10, func(run shared.Run) bool {
96+
runs, err := shared.GetRunsWithFilter(client, repo, nil, 10, func(run shared.Run) bool {
9797
return run.Status != shared.Completed
9898
})
9999
if err != nil {

0 commit comments

Comments
 (0)
X Tutup