Skip to content

Commit f1de208

Browse files
committed
add admin / user level + api add correct registration token endpoint
1 parent 0655965 commit f1de208

File tree

10 files changed

+593
-13
lines changed

10 files changed

+593
-13
lines changed

options/locale/locale_en-US.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3756,6 +3756,7 @@ runners.update_runner_failed = Failed to update runner
37563756
runners.delete_runner = Delete this runner
37573757
runners.delete_runner_success = Runner deleted successfully
37583758
runners.delete_runner_failed = Failed to delete runner
3759+
runners.delete_runner_failed_runner_active = Failed to delete active runner
37593760
runners.delete_runner_header = Confirm to delete this runner
37603761
runners.delete_runner_notice = If a task is running on this runner, it will be terminated and mark as failed. It may break building workflow.
37613762
runners.none = No runners available

routers/api/v1/admin/runners.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,81 @@ func GetRegistrationToken(ctx *context.APIContext) {
2424

2525
shared.GetRegistrationToken(ctx, 0, 0)
2626
}
27+
28+
// CreateRegistrationToken returns the token to register global runners
29+
func CreateRegistrationToken(ctx *context.APIContext) {
30+
// swagger:operation POST /admin/actions/runners/registration-token admin adminCreateRunnerRegistrationToken
31+
// ---
32+
// summary: Get an global actions runner registration token
33+
// produces:
34+
// - application/json
35+
// parameters:
36+
// responses:
37+
// "200":
38+
// "$ref": "#/responses/RegistrationToken"
39+
40+
shared.GetRegistrationToken(ctx, 0, 0)
41+
}
42+
43+
// ListRunners get global runners
44+
func ListRunners(ctx *context.APIContext) {
45+
// swagger:operation GET /admin/actions/runners admin getRunners
46+
// ---
47+
// summary: Get global runners
48+
// produces:
49+
// - application/json
50+
// responses:
51+
// "200":
52+
// "$ref": "#/definitions/RunnerList"
53+
// "400":
54+
// "$ref": "#/responses/error"
55+
// "404":
56+
// "$ref": "#/responses/notFound"
57+
shared.ListRunners(ctx, 0, 0)
58+
}
59+
60+
// GetRunner get an global runner
61+
func GetRunner(ctx *context.APIContext) {
62+
// swagger:operation GET /admin/actions/runners/{runner_id} admin getRunner
63+
// ---
64+
// summary: Get an global runner
65+
// produces:
66+
// - application/json
67+
// parameters:
68+
// - name: runner_id
69+
// in: path
70+
// description: id of the runner
71+
// type: string
72+
// required: true
73+
// responses:
74+
// "200":
75+
// "$ref": "#/definitions/Runner"
76+
// "400":
77+
// "$ref": "#/responses/error"
78+
// "404":
79+
// "$ref": "#/responses/notFound"
80+
shared.GetRunner(ctx, 0, 0, ctx.PathParamInt64("runner_id"))
81+
}
82+
83+
// DeleteRunner delete an global runner
84+
func DeleteRunner(ctx *context.APIContext) {
85+
// swagger:operation DELETE /admin/actions/runners/{runner_id} admin deleteRunner
86+
// ---
87+
// summary: Delete an global runner
88+
// produces:
89+
// - application/json
90+
// parameters:
91+
// - name: runner_id
92+
// in: path
93+
// description: id of the runner
94+
// type: string
95+
// required: true
96+
// responses:
97+
// "204":
98+
// description: runner has been deleted
99+
// "400":
100+
// "$ref": "#/responses/error"
101+
// "404":
102+
// "$ref": "#/responses/notFound"
103+
shared.DeleteRunner(ctx, 0, 0, ctx.PathParamInt64("runner_id"))
104+
}

routers/api/v1/api.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -912,8 +912,9 @@ func Routes() *web.Router {
912912
})
913913

914914
m.Group("/runners", func() {
915-
m.Get("", reqToken(), reqChecker, act.GetRunners)
915+
m.Get("", reqToken(), reqChecker, act.ListRunners)
916916
m.Get("/registration-token", reqToken(), reqChecker, act.GetRegistrationToken)
917+
m.Get("/registration-token", reqToken(), reqChecker, act.CreateRegistrationToken)
917918
m.Get("/{runner_id}", reqToken(), reqChecker, act.GetRunner)
918919
m.Delete("/{runner_id}", reqToken(), reqChecker, act.DeleteRunner)
919920
})
@@ -1046,7 +1047,11 @@ func Routes() *web.Router {
10461047
})
10471048

10481049
m.Group("/runners", func() {
1050+
m.Get("", reqToken(), user.ListRunners)
10491051
m.Get("/registration-token", reqToken(), user.GetRegistrationToken)
1052+
m.Post("/registration-token", reqToken(), user.CreateRegistrationToken)
1053+
m.Get("/{runner_id}", reqToken(), user.GetRunner)
1054+
m.Delete("/{runner_id}", reqToken(), user.DeleteRunner)
10501055
})
10511056
})
10521057

@@ -1683,6 +1688,12 @@ func Routes() *web.Router {
16831688
Patch(bind(api.EditHookOption{}), admin.EditHook).
16841689
Delete(admin.DeleteHook)
16851690
})
1691+
m.Group("/actions/runners", func() {
1692+
m.Get("", admin.ListRunners)
1693+
m.Post("/registration-token", admin.CreateRegistrationToken)
1694+
m.Get("/{runner_id}", admin.GetRunner)
1695+
m.Delete("/{runner_id}", admin.DeleteRunner)
1696+
})
16861697
m.Group("/runners", func() {
16871698
m.Get("/registration-token", admin.GetRegistrationToken)
16881699
})

routers/api/v1/org/action.go

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,27 @@ func (Action) GetRegistrationToken(ctx *context.APIContext) {
189189
shared.GetRegistrationToken(ctx, ctx.Org.Organization.ID, 0)
190190
}
191191

192+
// https://docs.github.com/en/rest/actions/self-hosted-runners?apiVersion=2022-11-28#create-a-registration-token-for-an-organization
193+
// CreateRegistrationToken returns the token to register org runners
194+
func (Action) CreateRegistrationToken(ctx *context.APIContext) {
195+
// swagger:operation POST /orgs/{org}/actions/runners/registration-token organization orgCreateRunnerRegistrationToken
196+
// ---
197+
// summary: Get an organization's actions runner registration token
198+
// produces:
199+
// - application/json
200+
// parameters:
201+
// - name: org
202+
// in: path
203+
// description: name of the organization
204+
// type: string
205+
// required: true
206+
// responses:
207+
// "200":
208+
// "$ref": "#/responses/RegistrationToken"
209+
210+
shared.GetRegistrationToken(ctx, ctx.Org.Organization.ID, 0)
211+
}
212+
192213
// ListVariables list org-level variables
193214
func (Action) ListVariables(ctx *context.APIContext) {
194215
// swagger:operation GET /orgs/{org}/actions/variables organization getOrgVariablesList
@@ -466,8 +487,8 @@ func (Action) UpdateVariable(ctx *context.APIContext) {
466487
ctx.Status(http.StatusNoContent)
467488
}
468489

469-
// GetRunners get org-level runners
470-
func (Action) GetRunners(ctx *context.APIContext) {
490+
// ListRunners get org-level runners
491+
func (Action) ListRunners(ctx *context.APIContext) {
471492
// swagger:operation GET /orgs/{org}/actions/runners organization getRunners
472493
// ---
473494
// summary: Get org-level runners
@@ -486,7 +507,7 @@ func (Action) GetRunners(ctx *context.APIContext) {
486507
// "$ref": "#/responses/error"
487508
// "404":
488509
// "$ref": "#/responses/notFound"
489-
shared.GetRunners(ctx, ctx.Org.Organization.ID, 0)
510+
shared.ListRunners(ctx, ctx.Org.Organization.ID, 0)
490511
}
491512

492513
// GetRunner get an org-level runner
@@ -519,7 +540,7 @@ func (Action) GetRunner(ctx *context.APIContext) {
519540

520541
// DeleteRunner delete an org-level runner
521542
func (Action) DeleteRunner(ctx *context.APIContext) {
522-
// swagger:operation GET /orgs/{org}/actions/runners/{runner_id} organization deleteRunner
543+
// swagger:operation DELETE /orgs/{org}/actions/runners/{runner_id} organization deleteRunner
523544
// ---
524545
// summary: Delete an org-level runner
525546
// produces:

routers/api/v1/repo/action.go

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -526,8 +526,33 @@ func (Action) GetRegistrationToken(ctx *context.APIContext) {
526526
shared.GetRegistrationToken(ctx, 0, ctx.Repo.Repository.ID)
527527
}
528528

529-
// GetRunners get repo-level runners
530-
func (Action) GetRunners(ctx *context.APIContext) {
529+
// CreateRegistrationToken returns the token to register repo runners
530+
func (Action) CreateRegistrationToken(ctx *context.APIContext) {
531+
// swagger:operation POST /repos/{owner}/{repo}/actions/runners/registration-token repository repoCreateRunnerRegistrationToken
532+
// ---
533+
// summary: Get a repository's actions runner registration token
534+
// produces:
535+
// - application/json
536+
// parameters:
537+
// - name: owner
538+
// in: path
539+
// description: owner of the repo
540+
// type: string
541+
// required: true
542+
// - name: repo
543+
// in: path
544+
// description: name of the repo
545+
// type: string
546+
// required: true
547+
// responses:
548+
// "200":
549+
// "$ref": "#/responses/RegistrationToken"
550+
551+
shared.GetRegistrationToken(ctx, 0, ctx.Repo.Repository.ID)
552+
}
553+
554+
// ListRunners get repo-level runners
555+
func (Action) ListRunners(ctx *context.APIContext) {
531556
// swagger:operation GET /repos/{owner}/{repo}/actions/runners organization getRunners
532557
// ---
533558
// summary: Get repo-level runners
@@ -551,7 +576,7 @@ func (Action) GetRunners(ctx *context.APIContext) {
551576
// "$ref": "#/responses/error"
552577
// "404":
553578
// "$ref": "#/responses/notFound"
554-
shared.GetRunners(ctx, 0, ctx.Repo.Repository.ID)
579+
shared.ListRunners(ctx, 0, ctx.Repo.Repository.ID)
555580
}
556581

557582
// GetRunner get an repo-level runner
@@ -589,7 +614,7 @@ func (Action) GetRunner(ctx *context.APIContext) {
589614

590615
// DeleteRunner delete an repo-level runner
591616
func (Action) DeleteRunner(ctx *context.APIContext) {
592-
// swagger:operation GET /repos/{owner}/{repo}/actions/runners/{runner_id} organization deleteRunner
617+
// swagger:operation DELETE /repos/{owner}/{repo}/actions/runners/{runner_id} organization deleteRunner
593618
// ---
594619
// summary: Delete an repo-level runner
595620
// produces:

routers/api/v1/shared/runners.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@ import (
77
"errors"
88
"net/http"
99

10-
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
1110
actions_model "code.gitea.io/gitea/models/actions"
1211
"code.gitea.io/gitea/models/db"
1312
api "code.gitea.io/gitea/modules/structs"
1413
"code.gitea.io/gitea/modules/util"
1514
"code.gitea.io/gitea/routers/api/v1/utils"
1615
"code.gitea.io/gitea/services/context"
1716
"code.gitea.io/gitea/services/convert"
17+
"xorm.io/builder"
1818
)
1919

2020
// RegistrationToken is response related to registration token
@@ -36,7 +36,7 @@ func GetRegistrationToken(ctx *context.APIContext, ownerID, repoID int64) {
3636
ctx.JSON(http.StatusOK, RegistrationToken{Token: token.Token})
3737
}
3838

39-
func GetRunners(ctx *context.APIContext, ownerID, repoID int64) {
39+
func ListRunners(ctx *context.APIContext, ownerID, repoID int64) {
4040
runners, total, err := db.FindAndCount[actions_model.ActionRunner](ctx, &actions_model.FindRunnerOptions{
4141
OwnerID: ownerID,
4242
RepoID: repoID,
@@ -81,10 +81,16 @@ func DeleteRunner(ctx *context.APIContext, ownerID, repoID, runnerID int64) {
8181
ctx.APIErrorNotFound("No permission to delete this runner")
8282
return
8383
}
84-
if runner.Status() == runnerv1.RunnerStatus_RUNNER_STATUS_ACTIVE {
84+
exist, err := db.Exist[actions_model.ActionTask](ctx, builder.Eq{"`runner_id`": runner.ID}.And(builder.In("`status`", actions_model.StatusWaiting, actions_model.StatusRunning, actions_model.StatusBlocked)))
85+
if err != nil {
86+
ctx.APIErrorInternal(err)
87+
return
88+
}
89+
if exist {
8590
ctx.APIError(http.StatusConflict, "Runner is active")
8691
return
8792
}
93+
8894
err = actions_model.DeleteRunner(ctx, runner.ID)
8995
if err != nil {
9096
ctx.APIErrorInternal(err)

routers/api/v1/user/runners.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,81 @@ func GetRegistrationToken(ctx *context.APIContext) {
2424

2525
shared.GetRegistrationToken(ctx, ctx.Doer.ID, 0)
2626
}
27+
28+
// CreateRegistrationToken returns the token to register user runners
29+
func CreateRegistrationToken(ctx *context.APIContext) {
30+
// swagger:operation POST /user/actions/runners/registration-token user userCreateRunnerRegistrationToken
31+
// ---
32+
// summary: Get an user's actions runner registration token
33+
// produces:
34+
// - application/json
35+
// parameters:
36+
// responses:
37+
// "200":
38+
// "$ref": "#/responses/RegistrationToken"
39+
40+
shared.GetRegistrationToken(ctx, ctx.Doer.ID, 0)
41+
}
42+
43+
// ListRunners get user-level runners
44+
func ListRunners(ctx *context.APIContext) {
45+
// swagger:operation GET /user/actions/runners user getRunners
46+
// ---
47+
// summary: Get user-level runners
48+
// produces:
49+
// - application/json
50+
// responses:
51+
// "200":
52+
// "$ref": "#/definitions/RunnerList"
53+
// "400":
54+
// "$ref": "#/responses/error"
55+
// "404":
56+
// "$ref": "#/responses/notFound"
57+
shared.ListRunners(ctx, ctx.Doer.ID, 0)
58+
}
59+
60+
// GetRunner get an user-level runner
61+
func GetRunner(ctx *context.APIContext) {
62+
// swagger:operation GET /user/actions/runners/{runner_id} user getRunner
63+
// ---
64+
// summary: Get an user-level runner
65+
// produces:
66+
// - application/json
67+
// parameters:
68+
// - name: runner_id
69+
// in: path
70+
// description: id of the runner
71+
// type: string
72+
// required: true
73+
// responses:
74+
// "200":
75+
// "$ref": "#/definitions/Runner"
76+
// "400":
77+
// "$ref": "#/responses/error"
78+
// "404":
79+
// "$ref": "#/responses/notFound"
80+
shared.GetRunner(ctx, ctx.Doer.ID, 0, ctx.PathParamInt64("runner_id"))
81+
}
82+
83+
// DeleteRunner delete an user-level runner
84+
func DeleteRunner(ctx *context.APIContext) {
85+
// swagger:operation DELETE /user/actions/runners/{runner_id} user deleteRunner
86+
// ---
87+
// summary: Delete an user-level runner
88+
// produces:
89+
// - application/json
90+
// parameters:
91+
// - name: runner_id
92+
// in: path
93+
// description: id of the runner
94+
// type: string
95+
// required: true
96+
// responses:
97+
// "204":
98+
// description: runner has been deleted
99+
// "400":
100+
// "$ref": "#/responses/error"
101+
// "404":
102+
// "$ref": "#/responses/notFound"
103+
shared.DeleteRunner(ctx, ctx.Doer.ID, 0, ctx.PathParamInt64("runner_id"))
104+
}

routers/web/shared/actions/runners.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
shared_user "code.gitea.io/gitea/routers/web/shared/user"
1919
"code.gitea.io/gitea/services/context"
2020
"code.gitea.io/gitea/services/forms"
21+
"xorm.io/builder"
2122
)
2223

2324
const (
@@ -313,6 +314,22 @@ func RunnerDeletePost(ctx *context.Context) {
313314
successRedirectTo := rCtx.RedirectLink
314315
failedRedirectTo := rCtx.RedirectLink + url.PathEscape(ctx.PathParam("runnerid"))
315316

317+
exist, err := db.Exist[actions_model.ActionTask](ctx, builder.Eq{"`runner_id`": runner.ID}.And(builder.In("`status`", actions_model.StatusWaiting, actions_model.StatusRunning, actions_model.StatusBlocked)))
318+
if err != nil {
319+
log.Warn("DeleteRunnerPost.Exist failed: %v, url: %s", err, ctx.Req.URL)
320+
ctx.Flash.Warning(ctx.Tr("actions.runners.delete_runner_failed"))
321+
322+
ctx.JSONRedirect(failedRedirectTo)
323+
return
324+
}
325+
if exist {
326+
log.Warn("DeleteRunnerPost.Exist failed: cannot delete active runner")
327+
ctx.Flash.Warning(ctx.Tr("actions.runners.delete_runner_failed_runner_active"))
328+
329+
ctx.JSONRedirect(failedRedirectTo)
330+
return
331+
}
332+
316333
if err := actions_model.DeleteRunner(ctx, runner.ID); err != nil {
317334
log.Warn("DeleteRunnerPost.UpdateRunner failed: %v, url: %s", err, ctx.Req.URL)
318335
ctx.Flash.Warning(ctx.Tr("actions.runners.delete_runner_failed"))

0 commit comments

Comments
 (0)