0
0
mirror of https://github.com/go-gitea/gitea.git synced 2026-05-20 00:50:10 +02:00

address review comments on workflow runs API

- Update workflow_id swagger description to clarify filename-only
- Add exclude_pull_requests query parameter
- Return 404 for nonexistent workflow in ActionsListWorkflowRuns
- Remove break from test loop so all runs are verified
- Add actor and head_sha filter coverage to testAPIWorkflowRunsByWorkflowID
- Update nonexistent workflow test to expect 404
This commit is contained in:
Nicolas 2026-04-13 20:55:23 +02:00
parent 808930be8d
commit e15b1c2add
5 changed files with 53 additions and 17 deletions

View File

@ -64,16 +64,17 @@ func (runs RunList) LoadRepos(ctx context.Context) error {
type FindRunOptions struct { type FindRunOptions struct {
db.ListOptions db.ListOptions
RepoID int64 RepoID int64
OwnerID int64 OwnerID int64
WorkflowID string WorkflowID string
Ref string // the commit/tag/… that caused this workflow Ref string // the commit/tag/… that caused this workflow
TriggerUserID int64 TriggerUserID int64
TriggerEvent webhook_module.HookEventType TriggerEvent webhook_module.HookEventType
Approved bool // not util.OptionalBool, it works only when it's true Approved bool // not util.OptionalBool, it works only when it's true
Status []Status Status []Status
ConcurrencyGroup string ConcurrencyGroup string
CommitSHA string CommitSHA string
ExcludePullRequests bool
} }
func (opts FindRunOptions) ToConds() builder.Cond { func (opts FindRunOptions) ToConds() builder.Cond {
@ -102,6 +103,9 @@ func (opts FindRunOptions) ToConds() builder.Cond {
if opts.CommitSHA != "" { if opts.CommitSHA != "" {
cond = cond.And(builder.Eq{"`action_run`.commit_sha": opts.CommitSHA}) cond = cond.And(builder.Eq{"`action_run`.commit_sha": opts.CommitSHA})
} }
if opts.ExcludePullRequests {
cond = cond.And(builder.Neq{"`action_run`.trigger_event": "pull_request"})
}
if len(opts.ConcurrencyGroup) > 0 { if len(opts.ConcurrencyGroup) > 0 {
if opts.RepoID == 0 { if opts.RepoID == 0 {
panic("Invalid FindRunOptions: repo_id is required") panic("Invalid FindRunOptions: repo_id is required")

View File

@ -763,6 +763,11 @@ func (Action) ListWorkflowRuns(ctx *context.APIContext) {
// description: triggering sha of the workflow run // description: triggering sha of the workflow run
// type: string // type: string
// required: false // required: false
// - name: exclude_pull_requests
// in: query
// description: if true, pull request events are omitted from the results
// type: boolean
// required: false
// - name: page // - name: page
// in: query // in: query
// description: page number of results to return (1-based) // description: page number of results to return (1-based)
@ -971,7 +976,7 @@ func ActionsListWorkflowRuns(ctx *context.APIContext) {
// required: true // required: true
// - name: workflow_id // - name: workflow_id
// in: path // in: path
// description: id of the workflow // description: id of the workflow, must be the workflow file name (e.g. `build.yml`)
// type: string // type: string
// required: true // required: true
// - name: event // - name: event
@ -999,6 +1004,11 @@ func ActionsListWorkflowRuns(ctx *context.APIContext) {
// description: triggering sha of the workflow run // description: triggering sha of the workflow run
// type: string // type: string
// required: false // required: false
// - name: exclude_pull_requests
// in: query
// description: if true, pull request events are omitted from the results
// type: boolean
// required: false
// - name: page // - name: page
// in: query // in: query
// description: page number of results to return (1-based) // description: page number of results to return (1-based)
@ -1018,6 +1028,15 @@ func ActionsListWorkflowRuns(ctx *context.APIContext) {
// "$ref": "#/responses/notFound" // "$ref": "#/responses/notFound"
workflowID := ctx.PathParam("workflow_id") workflowID := ctx.PathParam("workflow_id")
if _, err := convert.GetActionWorkflow(ctx, ctx.Repo.GitRepo, ctx.Repo.Repository, workflowID); err != nil {
if errors.Is(err, util.ErrNotExist) {
ctx.APIError(http.StatusNotFound, err)
} else {
ctx.APIErrorInternal(err)
}
return
}
repoID := ctx.Repo.Repository.ID repoID := ctx.Repo.Repository.ID
shared.ListRuns(ctx, 0, repoID, workflowID) shared.ListRuns(ctx, 0, repoID, workflowID)

View File

@ -156,6 +156,9 @@ func ListRuns(ctx *context.APIContext, ownerID, repoID int64, workflowID string)
if headSHA := ctx.FormString("head_sha"); headSHA != "" { if headSHA := ctx.FormString("head_sha"); headSHA != "" {
opts.CommitSHA = headSHA opts.CommitSHA = headSHA
} }
if ctx.FormString("exclude_pull_requests") == "true" {
opts.ExcludePullRequests = true
}
runs, total, err := db.FindAndCount[actions_model.ActionRun](ctx, opts) runs, total, err := db.FindAndCount[actions_model.ActionRun](ctx, opts)
if err != nil { if err != nil {

View File

@ -5305,6 +5305,12 @@
"name": "head_sha", "name": "head_sha",
"in": "query" "in": "query"
}, },
{
"type": "boolean",
"description": "if true, pull request events are omitted from the results",
"name": "exclude_pull_requests",
"in": "query"
},
{ {
"type": "integer", "type": "integer",
"description": "page number of results to return (1-based)", "description": "page number of results to return (1-based)",
@ -6471,7 +6477,7 @@
}, },
{ {
"type": "string", "type": "string",
"description": "id of the workflow", "description": "id of the workflow, must be the workflow file name (e.g. `build.yml`)",
"name": "workflow_id", "name": "workflow_id",
"in": "path", "in": "path",
"required": true "required": true
@ -6506,6 +6512,12 @@
"name": "head_sha", "name": "head_sha",
"in": "query" "in": "query"
}, },
{
"type": "boolean",
"description": "if true, pull request events are omitted from the results",
"name": "exclude_pull_requests",
"in": "query"
},
{ {
"type": "integer", "type": "integer",
"description": "page number of results to return (1-based)", "description": "page number of results to return (1-based)",

View File

@ -50,18 +50,16 @@ func testAPIWorkflowRunsByWorkflowID(t *testing.T, owner, repo, workflowID, user
verifyWorkflowRunCanbeFoundWithStatusFilter(t, workflowRunsURL, token, run.ID, "", run.Status, "", "", "", "") verifyWorkflowRunCanbeFoundWithStatusFilter(t, workflowRunsURL, token, run.ID, "", run.Status, "", "", "", "")
verifyWorkflowRunCanbeFoundWithStatusFilter(t, workflowRunsURL, token, run.ID, "", "", "", run.HeadBranch, "", "") verifyWorkflowRunCanbeFoundWithStatusFilter(t, workflowRunsURL, token, run.ID, "", "", "", run.HeadBranch, "", "")
verifyWorkflowRunCanbeFoundWithStatusFilter(t, workflowRunsURL, token, run.ID, "", "", run.Event, "", "", "") verifyWorkflowRunCanbeFoundWithStatusFilter(t, workflowRunsURL, token, run.ID, "", "", run.Event, "", "", "")
verifyWorkflowRunCanbeFoundWithStatusFilter(t, workflowRunsURL, token, run.ID, "", "", "", "", run.TriggerActor.UserName, "")
verifyWorkflowRunCanbeFoundWithStatusFilter(t, workflowRunsURL, token, run.ID, "", "", "", "", run.TriggerActor.UserName, run.HeadSha)
if run.ID == expectedRunID { if run.ID == expectedRunID {
found = true found = true
break
} }
} }
assert.True(t, found, "expected to find run with ID %d in workflow %s runs", expectedRunID, workflowID) assert.True(t, found, "expected to find run with ID %d in workflow %s runs", expectedRunID, workflowID)
req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/actions/workflows/nonexistent.yaml/runs", owner, repo)).AddTokenAuth(token) req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/actions/workflows/nonexistent.yaml/runs", owner, repo)).AddTokenAuth(token)
resp = MakeRequest(t, req, http.StatusOK) MakeRequest(t, req, http.StatusNotFound)
emptyList := api.ActionWorkflowRunsResponse{}
DecodeJSON(t, resp, &emptyList)
assert.Empty(t, emptyList.Entries, "nonexistent workflow should return no runs")
} }
func testAPIWorkflowRunBasic(t *testing.T, apiRootURL, userUsername string, runID int64, scope ...auth_model.AccessTokenScope) { func testAPIWorkflowRunBasic(t *testing.T, apiRootURL, userUsername string, runID int64, scope ...auth_model.AccessTokenScope) {