Skip to content

Commit d3981cc

Browse files
committed
move implementations to correct places
1 parent b0f5360 commit d3981cc

File tree

6 files changed

+367
-341
lines changed

6 files changed

+367
-341
lines changed

routers/api/v1/admin/action.go

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package admin
5+
6+
import (
7+
"code.gitea.io/gitea/routers/api/v1/shared"
8+
"code.gitea.io/gitea/services/context"
9+
)
10+
11+
// ListWorkflowJobs Lists all jobs
12+
func ListWorkflowJobs(ctx *context.APIContext) {
13+
// swagger:operation GET /admin/actions/jobs admin listAdminWorkflowJobs
14+
// ---
15+
// summary: Lists all jobs
16+
// produces:
17+
// - application/json
18+
// parameters:
19+
// - name: status
20+
// in: query
21+
// description: workflow status (pending, queued, in_progress, failure, success, skipped)
22+
// type: string
23+
// required: false
24+
// - name: page
25+
// in: query
26+
// description: page number of results to return (1-based)
27+
// type: integer
28+
// - name: limit
29+
// in: query
30+
// description: page size of results
31+
// type: integer
32+
// responses:
33+
// "200":
34+
// "$ref": "#/responses/WorkflowJobsList"
35+
// "400":
36+
// "$ref": "#/responses/error"
37+
// "404":
38+
// "$ref": "#/responses/notFound"
39+
40+
shared.ListJobs(ctx, 0, 0, 0)
41+
}
42+
43+
// ListWorkflowRuns Lists all runs
44+
func ListWorkflowRuns(ctx *context.APIContext) {
45+
// swagger:operation GET /admin/actions/runs admin listAdminWorkflowRuns
46+
// ---
47+
// summary: Lists all runs
48+
// produces:
49+
// - application/json
50+
// parameters:
51+
// - name: event
52+
// in: query
53+
// description: workflow event name
54+
// type: string
55+
// required: false
56+
// - name: branch
57+
// in: query
58+
// description: workflow branch
59+
// type: string
60+
// required: false
61+
// - name: status
62+
// in: query
63+
// description: workflow status (pending, queued, in_progress, failure, success, skipped)
64+
// type: string
65+
// required: false
66+
// - name: actor
67+
// in: query
68+
// description: triggered by user
69+
// type: string
70+
// required: false
71+
// - name: head_sha
72+
// in: query
73+
// description: triggering sha of the workflow run
74+
// type: string
75+
// required: false
76+
// - name: page
77+
// in: query
78+
// description: page number of results to return (1-based)
79+
// type: integer
80+
// - name: limit
81+
// in: query
82+
// description: page size of results
83+
// type: integer
84+
// responses:
85+
// "200":
86+
// "$ref": "#/responses/WorkflowRunsList"
87+
// "400":
88+
// "$ref": "#/responses/error"
89+
// "404":
90+
// "$ref": "#/responses/notFound"
91+
92+
shared.ListRuns(ctx, 0, 0)
93+
}

routers/api/v1/admin/runners.go

Lines changed: 0 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -102,87 +102,3 @@ func DeleteRunner(ctx *context.APIContext) {
102102
// "$ref": "#/responses/notFound"
103103
shared.DeleteRunner(ctx, 0, 0, ctx.PathParamInt64("runner_id"))
104104
}
105-
106-
// ListWorkflowJobs Lists all jobs
107-
func ListWorkflowJobs(ctx *context.APIContext) {
108-
// swagger:operation GET /admin/actions/jobs admin listAdminWorkflowJobs
109-
// ---
110-
// summary: Lists all jobs
111-
// produces:
112-
// - application/json
113-
// parameters:
114-
// - name: status
115-
// in: query
116-
// description: workflow status (pending, queued, in_progress, failure, success, skipped)
117-
// type: string
118-
// required: false
119-
// - name: page
120-
// in: query
121-
// description: page number of results to return (1-based)
122-
// type: integer
123-
// - name: limit
124-
// in: query
125-
// description: page size of results
126-
// type: integer
127-
// responses:
128-
// "200":
129-
// "$ref": "#/responses/WorkflowJobsList"
130-
// "400":
131-
// "$ref": "#/responses/error"
132-
// "404":
133-
// "$ref": "#/responses/notFound"
134-
135-
shared.ListJobs(ctx, 0, 0, 0)
136-
}
137-
138-
// ListWorkflowRuns Lists all runs
139-
func ListWorkflowRuns(ctx *context.APIContext) {
140-
// swagger:operation GET /admin/actions/runs admin listAdminWorkflowRuns
141-
// ---
142-
// summary: Lists all runs
143-
// produces:
144-
// - application/json
145-
// parameters:
146-
// - name: event
147-
// in: query
148-
// description: workflow event name
149-
// type: string
150-
// required: false
151-
// - name: branch
152-
// in: query
153-
// description: workflow branch
154-
// type: string
155-
// required: false
156-
// - name: status
157-
// in: query
158-
// description: workflow status (pending, queued, in_progress, failure, success, skipped)
159-
// type: string
160-
// required: false
161-
// - name: actor
162-
// in: query
163-
// description: triggered by user
164-
// type: string
165-
// required: false
166-
// - name: head_sha
167-
// in: query
168-
// description: triggering sha of the workflow run
169-
// type: string
170-
// required: false
171-
// - name: page
172-
// in: query
173-
// description: page number of results to return (1-based)
174-
// type: integer
175-
// - name: limit
176-
// in: query
177-
// description: page size of results
178-
// type: integer
179-
// responses:
180-
// "200":
181-
// "$ref": "#/responses/WorkflowRunsList"
182-
// "400":
183-
// "$ref": "#/responses/error"
184-
// "404":
185-
// "$ref": "#/responses/notFound"
186-
187-
shared.ListRuns(ctx, 0, 0)
188-
}

routers/api/v1/shared/action.go

Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package shared
5+
6+
import (
7+
"fmt"
8+
"net/http"
9+
10+
actions_model "code.gitea.io/gitea/models/actions"
11+
"code.gitea.io/gitea/models/db"
12+
repo_model "code.gitea.io/gitea/models/repo"
13+
user_model "code.gitea.io/gitea/models/user"
14+
"code.gitea.io/gitea/modules/git"
15+
"code.gitea.io/gitea/modules/setting"
16+
api "code.gitea.io/gitea/modules/structs"
17+
"code.gitea.io/gitea/modules/webhook"
18+
"code.gitea.io/gitea/routers/api/v1/utils"
19+
"code.gitea.io/gitea/services/context"
20+
"code.gitea.io/gitea/services/convert"
21+
)
22+
23+
// ListJobs lists jobs for api route validated ownerID and repoID
24+
// ownerID == 0 and repoID == 0 means all jobs
25+
// ownerID == 0 and repoID != 0 means all jobs for the given repo
26+
// ownerID != 0 and repoID == 0 means all jobs for the given user/org
27+
// ownerID != 0 and repoID != 0 undefined behavior
28+
// runID == 0 means all jobs
29+
// Access rights are checked at the API route level
30+
func ListJobs(ctx *context.APIContext, ownerID, repoID, runID int64) {
31+
if ownerID != 0 && repoID != 0 {
32+
setting.PanicInDevOrTesting("ownerID and repoID should not be both set")
33+
}
34+
opts := actions_model.FindRunJobOptions{
35+
OwnerID: ownerID,
36+
RepoID: repoID,
37+
RunID: runID,
38+
ListOptions: utils.GetListOptions(ctx),
39+
}
40+
if statuses, ok := ctx.Req.URL.Query()["status"]; ok {
41+
for _, status := range statuses {
42+
values, err := convertToInternal(status)
43+
if err != nil {
44+
ctx.APIError(http.StatusBadRequest, fmt.Errorf("Invalid status %s", status))
45+
return
46+
}
47+
opts.Statuses = append(opts.Statuses, values...)
48+
}
49+
}
50+
51+
jobs, total, err := db.FindAndCount[actions_model.ActionRunJob](ctx, opts)
52+
if err != nil {
53+
ctx.APIErrorInternal(err)
54+
return
55+
}
56+
57+
res := new(api.ActionWorkflowJobsResponse)
58+
res.TotalCount = total
59+
60+
res.Entries = make([]*api.ActionWorkflowJob, len(jobs))
61+
62+
isRepoLevel := repoID != 0 && ctx.Repo != nil && ctx.Repo.Repository != nil && ctx.Repo.Repository.ID == repoID
63+
for i := range jobs {
64+
var repository *repo_model.Repository
65+
if isRepoLevel {
66+
repository = ctx.Repo.Repository
67+
} else {
68+
repository, err = repo_model.GetRepositoryByID(ctx, jobs[i].RepoID)
69+
if err != nil {
70+
ctx.APIErrorInternal(err)
71+
return
72+
}
73+
}
74+
75+
convertedWorkflowJob, err := convert.ToActionWorkflowJob(ctx, repository, nil, jobs[i])
76+
if err != nil {
77+
ctx.APIErrorInternal(err)
78+
return
79+
}
80+
res.Entries[i] = convertedWorkflowJob
81+
}
82+
83+
ctx.JSON(http.StatusOK, &res)
84+
}
85+
86+
func convertToInternal(s string) ([]actions_model.Status, error) {
87+
switch s {
88+
case "pending", "waiting", "requested", "action_required":
89+
return []actions_model.Status{actions_model.StatusBlocked}, nil
90+
case "queued":
91+
return []actions_model.Status{actions_model.StatusWaiting}, nil
92+
case "in_progress":
93+
return []actions_model.Status{actions_model.StatusRunning}, nil
94+
case "completed":
95+
return []actions_model.Status{
96+
actions_model.StatusSuccess,
97+
actions_model.StatusFailure,
98+
actions_model.StatusSkipped,
99+
actions_model.StatusCancelled,
100+
}, nil
101+
case "failure":
102+
return []actions_model.Status{actions_model.StatusFailure}, nil
103+
case "success":
104+
return []actions_model.Status{actions_model.StatusSuccess}, nil
105+
case "skipped", "neutral":
106+
return []actions_model.Status{actions_model.StatusSkipped}, nil
107+
case "cancelled", "timed_out":
108+
return []actions_model.Status{actions_model.StatusCancelled}, nil
109+
default:
110+
return nil, fmt.Errorf("invalid status %s", s)
111+
}
112+
}
113+
114+
// ListRuns lists jobs for api route validated ownerID and repoID
115+
// ownerID == 0 and repoID == 0 means all runs
116+
// ownerID == 0 and repoID != 0 means all runs for the given repo
117+
// ownerID != 0 and repoID == 0 means all runs for the given user/org
118+
// ownerID != 0 and repoID != 0 undefined behavior
119+
// Access rights are checked at the API route level
120+
func ListRuns(ctx *context.APIContext, ownerID, repoID int64) {
121+
if ownerID != 0 && repoID != 0 {
122+
setting.PanicInDevOrTesting("ownerID and repoID should not be both set")
123+
}
124+
opts := actions_model.FindRunOptions{
125+
OwnerID: ownerID,
126+
RepoID: repoID,
127+
ListOptions: utils.GetListOptions(ctx),
128+
}
129+
130+
if event := ctx.Req.URL.Query().Get("event"); event != "" {
131+
opts.TriggerEvent = webhook.HookEventType(event)
132+
}
133+
if branch := ctx.Req.URL.Query().Get("branch"); branch != "" {
134+
opts.Ref = string(git.RefNameFromBranch(branch))
135+
}
136+
if statuses, ok := ctx.Req.URL.Query()["status"]; ok {
137+
for _, status := range statuses {
138+
values, err := convertToInternal(status)
139+
if err != nil {
140+
ctx.APIError(http.StatusBadRequest, fmt.Errorf("Invalid status %s", status))
141+
return
142+
}
143+
opts.Status = append(opts.Status, values...)
144+
}
145+
}
146+
if actor := ctx.Req.URL.Query().Get("actor"); actor != "" {
147+
user, err := user_model.GetUserByName(ctx, actor)
148+
if err != nil {
149+
ctx.APIErrorInternal(err)
150+
return
151+
}
152+
opts.TriggerUserID = user.ID
153+
}
154+
if headSHA := ctx.Req.URL.Query().Get("head_sha"); headSHA != "" {
155+
opts.CommitSHA = headSHA
156+
}
157+
158+
runs, total, err := db.FindAndCount[actions_model.ActionRun](ctx, opts)
159+
if err != nil {
160+
ctx.APIErrorInternal(err)
161+
return
162+
}
163+
164+
res := new(api.ActionWorkflowRunsResponse)
165+
res.TotalCount = total
166+
167+
res.Entries = make([]*api.ActionWorkflowRun, len(runs))
168+
isRepoLevel := repoID != 0 && ctx.Repo != nil && ctx.Repo.Repository != nil && ctx.Repo.Repository.ID == repoID
169+
for i := range runs {
170+
var repository *repo_model.Repository
171+
if isRepoLevel {
172+
repository = ctx.Repo.Repository
173+
} else {
174+
repository, err = repo_model.GetRepositoryByID(ctx, runs[i].RepoID)
175+
if err != nil {
176+
ctx.APIErrorInternal(err)
177+
return
178+
}
179+
}
180+
181+
convertedRun, err := convert.ToActionWorkflowRun(ctx, repository, runs[i])
182+
if err != nil {
183+
ctx.APIErrorInternal(err)
184+
return
185+
}
186+
res.Entries[i] = convertedRun
187+
}
188+
189+
ctx.JSON(http.StatusOK, &res)
190+
}

0 commit comments

Comments
 (0)