From 48379a2bb532d1da5a26239ce236334b6ea41f51 Mon Sep 17 00:00:00 2001 From: Christopher Homberger Date: Sat, 3 May 2025 17:44:23 +0200 Subject: [PATCH] improve tests and fix bugs --- models/actions/run_job_list.go | 10 +- models/actions/run_list.go | 14 +- models/fixtures/action_run.yml | 8 +- routers/api/v1/admin/runners.go | 43 ++++ routers/api/v1/org/action.go | 41 +++ routers/api/v1/repo/action.go | 39 +++ routers/api/v1/shared/runners.go | 57 +++-- routers/api/v1/user/runners.go | 52 ++++ services/convert/convert.go | 2 + templates/swagger/v1_json.tmpl | 236 ++++++++++++++++++ .../workflow_run_api_check_test.go | 74 +++++- 11 files changed, 548 insertions(+), 28 deletions(-) diff --git a/models/actions/run_job_list.go b/models/actions/run_job_list.go index 17f4339a53..5f7bb62878 100644 --- a/models/actions/run_job_list.go +++ b/models/actions/run_job_list.go @@ -80,19 +80,19 @@ type FindRunJobOptions struct { func (opts FindRunJobOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.RunID > 0 { - cond = cond.And(builder.Eq{"run_id": opts.RunID}) + cond = cond.And(builder.Eq{"`action_run_job`.run_id": opts.RunID}) } if opts.RepoID > 0 { - cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) + cond = cond.And(builder.Eq{"`action_run_job`.repo_id": opts.RepoID}) } if opts.CommitSHA != "" { - cond = cond.And(builder.Eq{"commit_sha": opts.CommitSHA}) + cond = cond.And(builder.Eq{"`action_run_job`.commit_sha": opts.CommitSHA}) } if len(opts.Statuses) > 0 { - cond = cond.And(builder.In("status", opts.Statuses)) + cond = cond.And(builder.In("`action_run_job`.status", opts.Statuses)) } if opts.UpdatedBefore > 0 { - cond = cond.And(builder.Lt{"updated": opts.UpdatedBefore}) + cond = cond.And(builder.Lt{"`action_run_job`.updated": opts.UpdatedBefore}) } return cond } diff --git a/models/actions/run_list.go b/models/actions/run_list.go index d7c0854dcd..bbc30fd888 100644 --- a/models/actions/run_list.go +++ b/models/actions/run_list.go @@ -77,25 +77,25 @@ type FindRunOptions struct { func (opts FindRunOptions) ToConds() builder.Cond { cond := builder.NewCond() if opts.RepoID > 0 { - cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) + cond = cond.And(builder.Eq{"`action_run`.repo_id": opts.RepoID}) } if opts.WorkflowID != "" { - cond = cond.And(builder.Eq{"workflow_id": opts.WorkflowID}) + cond = cond.And(builder.Eq{"`action_run`.workflow_id": opts.WorkflowID}) } if opts.TriggerUserID > 0 { - cond = cond.And(builder.Eq{"trigger_user_id": opts.TriggerUserID}) + cond = cond.And(builder.Eq{"`action_run`.trigger_user_id": opts.TriggerUserID}) } if opts.Approved { - cond = cond.And(builder.Gt{"approved_by": 0}) + cond = cond.And(builder.Gt{"`action_run`.approved_by": 0}) } if len(opts.Status) > 0 { - cond = cond.And(builder.In("status", opts.Status)) + cond = cond.And(builder.In("`action_run`.status", opts.Status)) } if opts.Ref != "" { - cond = cond.And(builder.Eq{"ref": opts.Ref}) + cond = cond.And(builder.Eq{"`action_run`.ref": opts.Ref}) } if opts.TriggerEvent != "" { - cond = cond.And(builder.Eq{"trigger_event": opts.TriggerEvent}) + cond = cond.And(builder.Eq{"`action_run`.trigger_event": opts.TriggerEvent}) } return cond } diff --git a/models/fixtures/action_run.yml b/models/fixtures/action_run.yml index f285750482..dfe09ca7a5 100644 --- a/models/fixtures/action_run.yml +++ b/models/fixtures/action_run.yml @@ -9,6 +9,7 @@ ref: "refs/heads/master" commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0" event: "push" + trigger_event: "push" is_fork_pull_request: 0 status: 1 started: 1683636528 @@ -28,6 +29,7 @@ ref: "refs/heads/master" commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0" event: "push" + trigger_event: "push" is_fork_pull_request: 0 status: 1 started: 1683636528 @@ -47,6 +49,7 @@ ref: "refs/heads/master" commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0" event: "push" + trigger_event: "push" is_fork_pull_request: 0 status: 1 started: 1683636528 @@ -66,6 +69,7 @@ ref: "refs/heads/test" commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0" event: "push" + trigger_event: "push" is_fork_pull_request: 0 status: 1 started: 1683636528 @@ -85,6 +89,7 @@ ref: "refs/heads/test" commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0" event: "push" + trigger_event: "push" is_fork_pull_request: 0 status: 1 started: 1683636528 @@ -99,11 +104,12 @@ repo_id: 2 owner_id: 0 workflow_id: "test.yaml" - index: 191 + index: 192 trigger_user_id: 1 ref: "refs/heads/test" commit_sha: "c2d72f548424103f01ee1dc02889c1e2bff816b0" event: "push" + trigger_event: "push" is_fork_pull_request: 0 status: 1 started: 1683636528 diff --git a/routers/api/v1/admin/runners.go b/routers/api/v1/admin/runners.go index 97e80d59a9..865b791283 100644 --- a/routers/api/v1/admin/runners.go +++ b/routers/api/v1/admin/runners.go @@ -110,6 +110,20 @@ func ListWorkflowJobs(ctx *context.APIContext) { // summary: Lists all jobs // produces: // - application/json + // parameters: + // - name: status + // in: query + // description: workflow status (pending, queued, in_progress, failure, success, skipped) + // type: string + // required: false + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer // responses: // "200": // "$ref": "#/responses/WorkflowJobsList" @@ -128,6 +142,35 @@ func ListWorkflowRuns(ctx *context.APIContext) { // summary: Lists all runs // produces: // - application/json + // parameters: + // - name: event + // in: query + // description: workflow event name + // type: string + // required: false + // - name: branch + // in: query + // description: workflow branch + // type: string + // required: false + // - name: status + // in: query + // description: workflow status (pending, queued, in_progress, failure, success, skipped) + // type: string + // required: false + // - name: actor + // in: query + // description: triggered by user + // type: string + // required: false + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer // responses: // "200": // "$ref": "#/responses/WorkflowRunsList" diff --git a/routers/api/v1/org/action.go b/routers/api/v1/org/action.go index 2785312df6..2c4b66f017 100644 --- a/routers/api/v1/org/action.go +++ b/routers/api/v1/org/action.go @@ -582,6 +582,19 @@ func (Action) ListWorkflowJobs(ctx *context.APIContext) { // description: name of the organization // type: string // required: true + // - name: status + // in: query + // description: workflow status (pending, queued, in_progress, failure, success, skipped) + // type: string + // required: false + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer // responses: // "200": // "$ref": "#/responses/WorkflowJobsList" @@ -604,6 +617,34 @@ func (Action) ListWorkflowRuns(ctx *context.APIContext) { // description: name of the organization // type: string // required: true + // - name: event + // in: query + // description: workflow event name + // type: string + // required: false + // - name: branch + // in: query + // description: workflow branch + // type: string + // required: false + // - name: status + // in: query + // description: workflow status (pending, queued, in_progress, failure, success, skipped) + // type: string + // required: false + // - name: actor + // in: query + // description: triggered by user + // type: string + // required: false + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer // responses: // "200": // "$ref": "#/responses/WorkflowRunsList" diff --git a/routers/api/v1/repo/action.go b/routers/api/v1/repo/action.go index 7370471ac0..e1468cb67a 100644 --- a/routers/api/v1/repo/action.go +++ b/routers/api/v1/repo/action.go @@ -668,6 +668,19 @@ func (Action) ListWorkflowJobs(ctx *context.APIContext) { // description: name of the repository // type: string // required: true + // - name: status + // in: query + // description: workflow status (pending, queued, in_progress, failure, success, skipped) + // type: string + // required: false + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer // responses: // "200": // "$ref": "#/responses/WorkflowJobsList" @@ -714,6 +727,19 @@ func (Action) ListWorkflowRuns(ctx *context.APIContext) { // description: workflow status (pending, queued, in_progress, failure, success, skipped) // type: string // required: false + // - name: actor + // in: query + // description: triggered by user + // type: string + // required: false + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer // responses: // "200": // "$ref": "#/responses/ArtifactsList" @@ -1138,6 +1164,19 @@ func ListWorkflowRunJobs(ctx *context.APIContext) { // description: runid of the workflow run // type: integer // required: true + // - name: status + // in: query + // description: workflow status (pending, queued, in_progress, failure, success, skipped) + // type: string + // required: false + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer // responses: // "200": // "$ref": "#/responses/WorkflowJobsList" diff --git a/routers/api/v1/shared/runners.go b/routers/api/v1/shared/runners.go index 68310cf078..dd9b92155d 100644 --- a/routers/api/v1/shared/runners.go +++ b/routers/api/v1/shared/runners.go @@ -5,6 +5,7 @@ package shared import ( "errors" + "fmt" "net/http" actions_model "code.gitea.io/gitea/models/actions" @@ -132,12 +133,24 @@ func ListJobs(ctx *context.APIContext, ownerID, repoID, runID int64) { if ownerID != 0 && repoID != 0 { setting.PanicInDevOrTesting("ownerID and repoID should not be both set") } - jobs, total, err := db.FindAndCount[actions_model.ActionRunJob](ctx, actions_model.FindRunJobOptions{ + opts := actions_model.FindRunJobOptions{ OwnerID: ownerID, RepoID: repoID, RunID: runID, ListOptions: utils.GetListOptions(ctx), - }) + } + if statuses, ok := ctx.Req.URL.Query()["status"]; ok { + for _, status := range statuses { + values, err := convertToInternal(status) + if err != nil { + ctx.APIError(http.StatusBadRequest, fmt.Errorf("Invalid status %s", status)) + return + } + opts.Statuses = append(opts.Statuses, values...) + } + } + + jobs, total, err := db.FindAndCount[actions_model.ActionRunJob](ctx, opts) if err != nil { ctx.APIErrorInternal(err) return @@ -172,22 +185,31 @@ func ListJobs(ctx *context.APIContext, ownerID, repoID, runID int64) { ctx.JSON(http.StatusOK, &res) } -func convertToInternal(s string) actions_model.Status { +func convertToInternal(s string) ([]actions_model.Status, error) { switch s { - case "pending": - return actions_model.StatusBlocked + case "pending", "waiting", "requested", "action_required": + return []actions_model.Status{actions_model.StatusBlocked}, nil case "queued": - return actions_model.StatusWaiting + return []actions_model.Status{actions_model.StatusWaiting}, nil case "in_progress": - return actions_model.StatusRunning + return []actions_model.Status{actions_model.StatusRunning}, nil + case "completed": + return []actions_model.Status{ + actions_model.StatusSuccess, + actions_model.StatusFailure, + actions_model.StatusSkipped, + actions_model.StatusCancelled, + }, nil case "failure": - return actions_model.StatusFailure + return []actions_model.Status{actions_model.StatusFailure}, nil case "success": - return actions_model.StatusSuccess - case "skipped": - return actions_model.StatusSkipped + return []actions_model.Status{actions_model.StatusSuccess}, nil + case "skipped", "neutral": + return []actions_model.Status{actions_model.StatusSkipped}, nil + case "cancelled", "timed_out": + return []actions_model.Status{actions_model.StatusCancelled}, nil default: - return actions_model.StatusUnknown + return nil, fmt.Errorf("invalid status %s", s) } } @@ -213,8 +235,15 @@ func ListRuns(ctx *context.APIContext, ownerID, repoID int64) { if branch := ctx.Req.URL.Query().Get("branch"); branch != "" { opts.Ref = string(git.RefNameFromBranch(branch)) } - if status := ctx.Req.URL.Query().Get("status"); status != "" { - opts.Status = []actions_model.Status{convertToInternal(status)} + if statuses, ok := ctx.Req.URL.Query()["status"]; ok { + for _, status := range statuses { + values, err := convertToInternal(status) + if err != nil { + ctx.APIError(http.StatusBadRequest, fmt.Errorf("Invalid status %s", status)) + return + } + opts.Status = append(opts.Status, values...) + } } if actor := ctx.Req.URL.Query().Get("actor"); actor != "" { user, err := user_model.GetUserByName(ctx, actor) diff --git a/routers/api/v1/user/runners.go b/routers/api/v1/user/runners.go index 60d0948977..3fc8973585 100644 --- a/routers/api/v1/user/runners.go +++ b/routers/api/v1/user/runners.go @@ -108,11 +108,44 @@ func ListWorkflowRuns(ctx *context.APIContext) { // swagger:operation GET /user/actions/runs user getUserWorkflowRuns // --- // summary: Get workflow runs + // parameters: + // - name: event + // in: query + // description: workflow event name + // type: string + // required: false + // - name: branch + // in: query + // description: workflow branch + // type: string + // required: false + // - name: status + // in: query + // description: workflow status (pending, queued, in_progress, failure, success, skipped) + // type: string + // required: false + // - name: actor + // in: query + // description: triggered by user + // type: string + // required: false + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer // produces: // - application/json // responses: // "200": // "$ref": "#/responses/WorkflowRunsList" + // "400": + // "$ref": "#/responses/error" + // "404": + // "$ref": "#/responses/notFound" shared.ListRuns(ctx, ctx.Doer.ID, 0) } @@ -121,10 +154,29 @@ func ListWorkflowJobs(ctx *context.APIContext) { // swagger:operation GET /user/actions/jobs user getUserWorkflowJobs // --- // summary: Get workflow jobs + // parameters: + // - name: status + // in: query + // description: workflow status (pending, queued, in_progress, failure, success, skipped) + // type: string + // required: false + // - name: page + // in: query + // description: page number of results to return (1-based) + // type: integer + // - name: limit + // in: query + // description: page size of results + // type: integer // produces: // - application/json // responses: // "200": // "$ref": "#/responses/WorkflowJobsList" + // "400": + // "$ref": "#/responses/error" + // "404": + // "$ref": "#/responses/notFound" + shared.ListJobs(ctx, ctx.Doer.ID, 0, 0) } diff --git a/services/convert/convert.go b/services/convert/convert.go index 75b3f1baa0..a30ab7b658 100644 --- a/services/convert/convert.go +++ b/services/convert/convert.go @@ -306,6 +306,8 @@ func ToActionsStatus(status actions_model.Status) (string, string) { conclusion = "cancelled" case actions_model.StatusFailure: conclusion = "failure" + case actions_model.StatusSkipped: + conclusion = "skipped" } } return action, conclusion diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 5bf4d41fab..2e163c5468 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -85,6 +85,26 @@ ], "summary": "Lists all jobs", "operationId": "listAdminWorkflowJobs", + "parameters": [ + { + "type": "string", + "description": "workflow status (pending, queued, in_progress, failure, success, skipped)", + "name": "status", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], "responses": { "200": { "$ref": "#/responses/WorkflowJobsList" @@ -210,6 +230,44 @@ ], "summary": "Lists all runs", "operationId": "listAdminWorkflowRuns", + "parameters": [ + { + "type": "string", + "description": "workflow event name", + "name": "event", + "in": "query" + }, + { + "type": "string", + "description": "workflow branch", + "name": "branch", + "in": "query" + }, + { + "type": "string", + "description": "workflow status (pending, queued, in_progress, failure, success, skipped)", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "triggered by user", + "name": "actor", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], "responses": { "200": { "$ref": "#/responses/WorkflowRunsList" @@ -1862,6 +1920,24 @@ "name": "org", "in": "path", "required": true + }, + { + "type": "string", + "description": "workflow status (pending, queued, in_progress, failure, success, skipped)", + "name": "status", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" } ], "responses": { @@ -2052,6 +2128,42 @@ "name": "org", "in": "path", "required": true + }, + { + "type": "string", + "description": "workflow event name", + "name": "event", + "in": "query" + }, + { + "type": "string", + "description": "workflow branch", + "name": "branch", + "in": "query" + }, + { + "type": "string", + "description": "workflow status (pending, queued, in_progress, failure, success, skipped)", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "triggered by user", + "name": "actor", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" } ], "responses": { @@ -4653,6 +4765,24 @@ "name": "repo", "in": "path", "required": true + }, + { + "type": "string", + "description": "workflow status (pending, queued, in_progress, failure, success, skipped)", + "name": "status", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" } ], "responses": { @@ -4995,6 +5125,24 @@ "description": "workflow status (pending, queued, in_progress, failure, success, skipped)", "name": "status", "in": "query" + }, + { + "type": "string", + "description": "triggered by user", + "name": "actor", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" } ], "responses": { @@ -5139,6 +5287,24 @@ "name": "run", "in": "path", "required": true + }, + { + "type": "string", + "description": "workflow status (pending, queued, in_progress, failure, success, skipped)", + "name": "status", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" } ], "responses": { @@ -17821,9 +17987,35 @@ ], "summary": "Get workflow jobs", "operationId": "getUserWorkflowJobs", + "parameters": [ + { + "type": "string", + "description": "workflow status (pending, queued, in_progress, failure, success, skipped)", + "name": "status", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], "responses": { "200": { "$ref": "#/responses/WorkflowJobsList" + }, + "400": { + "$ref": "#/responses/error" + }, + "404": { + "$ref": "#/responses/notFound" } } } @@ -17955,9 +18147,53 @@ ], "summary": "Get workflow runs", "operationId": "getUserWorkflowRuns", + "parameters": [ + { + "type": "string", + "description": "workflow event name", + "name": "event", + "in": "query" + }, + { + "type": "string", + "description": "workflow branch", + "name": "branch", + "in": "query" + }, + { + "type": "string", + "description": "workflow status (pending, queued, in_progress, failure, success, skipped)", + "name": "status", + "in": "query" + }, + { + "type": "string", + "description": "triggered by user", + "name": "actor", + "in": "query" + }, + { + "type": "integer", + "description": "page number of results to return (1-based)", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "description": "page size of results", + "name": "limit", + "in": "query" + } + ], "responses": { "200": { "$ref": "#/responses/WorkflowRunsList" + }, + "400": { + "$ref": "#/responses/error" + }, + "404": { + "$ref": "#/responses/notFound" } } } diff --git a/tests/integration/workflow_run_api_check_test.go b/tests/integration/workflow_run_api_check_test.go index 618830512a..cd6d49d622 100644 --- a/tests/integration/workflow_run_api_check_test.go +++ b/tests/integration/workflow_run_api_check_test.go @@ -6,6 +6,7 @@ package integration import ( "fmt" "net/http" + "net/url" "testing" auth_model "code.gitea.io/gitea/models/auth" @@ -44,6 +45,11 @@ func testAPIWorkflowRunBasic(t *testing.T, runAPIURL string, itemCount int, user foundRun := false for _, run := range runnerList.Entries { + verifyWorkflowRunCanbeFoundWithStatusFilter(t, runAPIURL, token, run.ID, "", run.Status, "", "") + verifyWorkflowRunCanbeFoundWithStatusFilter(t, runAPIURL, token, run.ID, run.Conclusion, "", "", "") + verifyWorkflowRunCanbeFoundWithStatusFilter(t, runAPIURL, token, run.ID, "", "", "", run.HeadBranch) + verifyWorkflowRunCanbeFoundWithStatusFilter(t, runAPIURL, token, run.ID, "", "", run.Event, "") + req := NewRequest(t, "GET", fmt.Sprintf("%s/%s", run.URL, "jobs")).AddTokenAuth(token) jobsResp := MakeRequest(t, req, http.StatusOK) jobList := api.ActionWorkflowJobsResponse{} @@ -53,6 +59,9 @@ func testAPIWorkflowRunBasic(t *testing.T, runAPIURL string, itemCount int, user foundRun = true assert.Len(t, jobList.Entries, 1) for _, job := range jobList.Entries { + verifyWorkflowJobCanbeFoundWithStatusFilter(t, fmt.Sprintf("%s/%s", run.URL, "jobs"), token, job.ID, "", job.Status) + verifyWorkflowJobCanbeFoundWithStatusFilter(t, fmt.Sprintf("%s/%s", run.URL, "jobs"), token, job.ID, job.Conclusion, "") + req := NewRequest(t, "GET", job.URL).AddTokenAuth(token) jobsResp := MakeRequest(t, req, http.StatusOK) apiJob := api.ActionWorkflowJob{} @@ -64,5 +73,68 @@ func testAPIWorkflowRunBasic(t *testing.T, runAPIURL string, itemCount int, user } } } - assert.True(t, foundRun, "Expected to find run with ID 802") + assert.True(t, foundRun, "Expected to find run with ID %d", runID) +} + +func verifyWorkflowRunCanbeFoundWithStatusFilter(t *testing.T, runAPIURL, token string, id int64, conclusion, status, event, branch string) { + filter := url.Values{} + if conclusion != "" { + filter.Add("status", conclusion) + } + if status != "" { + filter.Add("status", status) + } + if event != "" { + filter.Set("event", event) + } + if branch != "" { + filter.Set("branch", branch) + } + req := NewRequest(t, "GET", runAPIURL+"?"+filter.Encode()).AddTokenAuth(token) + runResp := MakeRequest(t, req, http.StatusOK) + runList := api.ActionWorkflowRunsResponse{} + DecodeJSON(t, runResp, &runList) + + found := false + for _, run := range runList.Entries { + if conclusion != "" { + assert.Equal(t, conclusion, run.Conclusion) + } + if status != "" { + assert.Equal(t, status, run.Status) + } + if event != "" { + assert.Equal(t, event, run.Event) + } + if branch != "" { + assert.Equal(t, branch, run.HeadBranch) + } + found = found || run.ID == id + } + assert.True(t, found, "Expected to find run with ID %d", id) +} + +func verifyWorkflowJobCanbeFoundWithStatusFilter(t *testing.T, runAPIURL, token string, id int64, conclusion, status string) { + filter := conclusion + if filter == "" { + filter = status + } + if filter == "" { + return + } + req := NewRequest(t, "GET", runAPIURL+"?status="+filter).AddTokenAuth(token) + jobListResp := MakeRequest(t, req, http.StatusOK) + jobList := api.ActionWorkflowJobsResponse{} + DecodeJSON(t, jobListResp, &jobList) + + found := false + for _, job := range jobList.Entries { + if conclusion != "" { + assert.Equal(t, conclusion, job.Conclusion) + } else { + assert.Equal(t, status, job.Status) + } + found = found || job.ID == id + } + assert.True(t, found, "Expected to find job with ID %d", id) }