diff --git a/models/actions/run_list.go b/models/actions/run_list.go index 496cb669b1..726157b12e 100644 --- a/models/actions/run_list.go +++ b/models/actions/run_list.go @@ -85,7 +85,7 @@ func (opts FindRunOptions) ToConds() builder.Cond { 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"}) + cond = cond.And(builder.Neq{"`action_run`.trigger_event": string(webhook_module.HookEventPullRequest)}) } if len(opts.ConcurrencyGroup) > 0 { if opts.RepoID == 0 { diff --git a/routers/api/v1/repo/action.go b/routers/api/v1/repo/action.go index 143f4b64bd..b05a4e3ad1 100644 --- a/routers/api/v1/repo/action.go +++ b/routers/api/v1/repo/action.go @@ -1028,21 +1028,28 @@ func ActionsListWorkflowRuns(ctx *context.APIContext) { // "$ref": "#/responses/notFound" workflowID := ctx.PathParam("workflow_id") - runExists, err := db.GetEngine(ctx). - Where("repo_id = ? AND workflow_id = ?", ctx.Repo.Repository.ID, workflowID). - Exist(&actions_model.ActionRun{}) + // Existing runs prove the workflow is/was valid and cover historical workflows + // whose file was later removed. Fall back to a git lookup for never-run workflows. + runExists, err := db.Exist[actions_model.ActionRun](ctx, actions_model.FindRunOptions{ + RepoID: ctx.Repo.Repository.ID, + WorkflowID: workflowID, + }.ToConds()) if err != nil { ctx.APIErrorInternal(err) return } if !runExists { - ctx.APIError(http.StatusNotFound, util.NewNotExistErrorf("workflow %q not found", workflowID)) - return + 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 - - shared.ListRuns(ctx, 0, repoID, workflowID) + shared.ListRuns(ctx, 0, ctx.Repo.Repository.ID, workflowID) } func ActionsDisableWorkflow(ctx *context.APIContext) { diff --git a/routers/api/v1/shared/action.go b/routers/api/v1/shared/action.go index 9a1e807865..dde724c6ee 100644 --- a/routers/api/v1/shared/action.go +++ b/routers/api/v1/shared/action.go @@ -156,9 +156,7 @@ func ListRuns(ctx *context.APIContext, ownerID, repoID int64, workflowID string) if headSHA := ctx.FormString("head_sha"); headSHA != "" { opts.CommitSHA = headSHA } - if ctx.FormString("exclude_pull_requests") == "true" { - opts.ExcludePullRequests = true - } + opts.ExcludePullRequests = ctx.FormBool("exclude_pull_requests") runs, total, err := db.FindAndCount[actions_model.ActionRun](ctx, opts) if err != nil { diff --git a/tests/integration/workflow_run_api_check_test.go b/tests/integration/workflow_run_api_check_test.go index f518c161a0..db0a8d074a 100644 --- a/tests/integration/workflow_run_api_check_test.go +++ b/tests/integration/workflow_run_api_check_test.go @@ -58,6 +58,19 @@ func testAPIWorkflowRunsByWorkflowID(t *testing.T, owner, repo, workflowID, user } assert.True(t, found, "expected to find run with ID %d in workflow %s runs", expectedRunID, workflowID) + req = NewRequest(t, "GET", workflowRunsURL+"?exclude_pull_requests=true").AddTokenAuth(token) + resp = MakeRequest(t, req, http.StatusOK) + excludedList := api.ActionWorkflowRunsResponse{} + DecodeJSON(t, resp, &excludedList) + excludedFound := false + for _, run := range excludedList.Entries { + assert.NotEqual(t, "pull_request", run.Event) + if run.ID == expectedRunID { + excludedFound = true + } + } + assert.True(t, excludedFound, "expected to find run with ID %d when excluding pull requests", expectedRunID) + req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/actions/workflows/nonexistent.yaml/runs", owner, repo)).AddTokenAuth(token) MakeRequest(t, req, http.StatusNotFound) }