From 028df22aade0cd21485c7e2e28cb4edbc8acba28 Mon Sep 17 00:00:00 2001 From: Nicolas Bircks Date: Mon, 13 Apr 2026 13:11:57 +0200 Subject: [PATCH] add new api sub path --- routers/api/v1/admin/action.go | 2 +- routers/api/v1/api.go | 1 + routers/api/v1/org/action.go | 2 +- routers/api/v1/repo/action.go | 73 ++++++++++++++++++++++++++++++++- routers/api/v1/shared/action.go | 4 +- routers/api/v1/user/action.go | 2 +- 6 files changed, 79 insertions(+), 5 deletions(-) diff --git a/routers/api/v1/admin/action.go b/routers/api/v1/admin/action.go index 2fbb8e1a95..2f1c1a2b5c 100644 --- a/routers/api/v1/admin/action.go +++ b/routers/api/v1/admin/action.go @@ -89,5 +89,5 @@ func ListWorkflowRuns(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" - shared.ListRuns(ctx, 0, 0) + shared.ListRuns(ctx, 0, 0, "") } diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 2d80692fef..e6f8f8bc80 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1166,6 +1166,7 @@ func Routes() *web.Router { m.Group("/actions/workflows", func() { m.Get("", repo.ActionsListRepositoryWorkflows) m.Get("/{workflow_id}", repo.ActionsGetWorkflow) + m.Get("/{workflow_id}/runs", repo.ActionsListWorkflowRuns) m.Put("/{workflow_id}/disable", reqRepoWriter(unit.TypeActions), repo.ActionsDisableWorkflow) m.Put("/{workflow_id}/enable", reqRepoWriter(unit.TypeActions), repo.ActionsEnableWorkflow) m.Post("/{workflow_id}/dispatches", reqRepoWriter(unit.TypeActions), bind(api.CreateActionWorkflowDispatch{}), repo.ActionsDispatchWorkflow) diff --git a/routers/api/v1/org/action.go b/routers/api/v1/org/action.go index 01b57b3fac..bfc109e5e5 100644 --- a/routers/api/v1/org/action.go +++ b/routers/api/v1/org/action.go @@ -679,7 +679,7 @@ func (Action) ListWorkflowRuns(ctx *context.APIContext) { // "$ref": "#/responses/error" // "404": // "$ref": "#/responses/notFound" - shared.ListRuns(ctx, ctx.Org.Organization.ID, 0) + shared.ListRuns(ctx, ctx.Org.Organization.ID, 0, "") } var _ actions_service.API = new(Action) diff --git a/routers/api/v1/repo/action.go b/routers/api/v1/repo/action.go index 7ac8a10575..37ea45e14e 100644 --- a/routers/api/v1/repo/action.go +++ b/routers/api/v1/repo/action.go @@ -781,7 +781,7 @@ func (Action) ListWorkflowRuns(ctx *context.APIContext) { repoID := ctx.Repo.Repository.ID - shared.ListRuns(ctx, 0, repoID) + shared.ListRuns(ctx, 0, repoID, "") } var _ actions_service.API = new(Action) @@ -952,6 +952,77 @@ func ActionsGetWorkflow(ctx *context.APIContext) { ctx.JSON(http.StatusOK, workflow) } +func ActionsListWorkflowRuns(ctx *context.APIContext) { + // swagger:operation GET /repos/{owner}/{repo}/actions/workflows/{workflow_id}/runs repository ActionsListWorkflowRuns + // --- + // summary: List runs for a workflow + // produces: + // - application/json + // parameters: + // - name: owner + // in: path + // description: owner of the repo + // type: string + // required: true + // - name: repo + // in: path + // description: name of the repo + // type: string + // required: true + // - name: workflow_id + // in: path + // description: id of the workflow + // 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: head_sha + // in: query + // description: triggering sha of the workflow run + // 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" + // "400": + // "$ref": "#/responses/error" + // "403": + // "$ref": "#/responses/forbidden" + // "404": + // "$ref": "#/responses/notFound" + + workflowID := ctx.PathParam("workflow_id") + repoID := ctx.Repo.Repository.ID + + shared.ListRuns(ctx, 0, repoID, workflowID) +} + func ActionsDisableWorkflow(ctx *context.APIContext) { // swagger:operation PUT /repos/{owner}/{repo}/actions/workflows/{workflow_id}/disable repository ActionsDisableWorkflow // --- diff --git a/routers/api/v1/shared/action.go b/routers/api/v1/shared/action.go index 715e76c355..8f2db38f7c 100644 --- a/routers/api/v1/shared/action.go +++ b/routers/api/v1/shared/action.go @@ -117,8 +117,9 @@ func convertToInternal(s string) ([]actions_model.Status, error) { // ownerID == 0 and repoID != 0 means all runs for the given repo // ownerID != 0 and repoID == 0 means all runs for the given user/org // ownerID != 0 and repoID != 0 undefined behavior +// workflowID filters runs by workflow file name (e.g. "build.yml"), empty means no filter // Access rights are checked at the API route level -func ListRuns(ctx *context.APIContext, ownerID, repoID int64) { +func ListRuns(ctx *context.APIContext, ownerID, repoID int64, workflowID string) { if ownerID != 0 && repoID != 0 { setting.PanicInDevOrTesting("ownerID and repoID should not be both set") } @@ -126,6 +127,7 @@ func ListRuns(ctx *context.APIContext, ownerID, repoID int64) { opts := actions_model.FindRunOptions{ OwnerID: ownerID, RepoID: repoID, + WorkflowID: workflowID, ListOptions: listOptions, } diff --git a/routers/api/v1/user/action.go b/routers/api/v1/user/action.go index 573e2e4dd0..f105f1c956 100644 --- a/routers/api/v1/user/action.go +++ b/routers/api/v1/user/action.go @@ -407,7 +407,7 @@ func ListWorkflowRuns(ctx *context.APIContext) { // "$ref": "#/responses/error" // "404": // "$ref": "#/responses/notFound" - shared.ListRuns(ctx, ctx.Doer.ID, 0) + shared.ListRuns(ctx, ctx.Doer.ID, 0, "") } // ListWorkflowJobs lists workflow jobs