Skip to content

Commit c062f18

Browse files
committed
WIP ActionRunner Org + Repo Api
1 parent 91610a9 commit c062f18

File tree

7 files changed

+149
-0
lines changed

7 files changed

+149
-0
lines changed

modules/structs/repo_actions.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,3 +133,27 @@ type ActionWorkflowJob struct {
133133
// swagger:strfmt date-time
134134
CompletedAt time.Time `json:"completed_at,omitempty"`
135135
}
136+
137+
// ActionRunnerLabel represents a Runner Label
138+
type ActionRunnerLabel struct {
139+
ID int64 `json:"id"`
140+
Name string `json:"name"`
141+
Type string `json:"type"`
142+
}
143+
144+
// ActionRunner represents a Runner
145+
type ActionRunner struct {
146+
ID int64 `json:"id"`
147+
Name string `json:"name"`
148+
OS string `json:"os"`
149+
Status string `json:"status"`
150+
Busy bool `json:"busy"`
151+
Ephemeral bool `json:"ephemeral"`
152+
Labels []*ActionRunnerLabel `json:"labels"`
153+
}
154+
155+
// ActionRunnersResponse returns Runners
156+
type ActionRunnersResponse struct {
157+
Entries []*ActionRunner `json:"runners"`
158+
TotalCount int64 `json:"total_count"`
159+
}

routers/api/v1/api.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -912,7 +912,10 @@ func Routes() *web.Router {
912912
})
913913

914914
m.Group("/runners", func() {
915+
m.Get("", reqToken(), reqChecker, act.GetRunners)
915916
m.Get("/registration-token", reqToken(), reqChecker, act.GetRegistrationToken)
917+
m.Get("/{runner_id}", reqToken(), reqChecker, act.GetRunner)
918+
m.Delete("/{runner_id}", reqToken(), reqChecker, act.DeleteRunner)
916919
})
917920
})
918921
}

routers/api/v1/org/action.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -466,6 +466,18 @@ func (Action) UpdateVariable(ctx *context.APIContext) {
466466
ctx.Status(http.StatusNoContent)
467467
}
468468

469+
func (Action) GetRunners(ctx *context.APIContext) {
470+
shared.GetRunners(ctx, ctx.Org.Organization.ID, 0)
471+
}
472+
473+
func (Action) GetRunner(ctx *context.APIContext) {
474+
shared.GetRunner(ctx, ctx.Org.Organization.ID, 0, ctx.PathParamInt64("runner_id"))
475+
}
476+
477+
func (Action) DeleteRunner(ctx *context.APIContext) {
478+
shared.DeleteRunner(ctx, ctx.Org.Organization.ID, 0, ctx.PathParamInt64("runner_id"))
479+
}
480+
469481
var _ actions_service.API = new(Action)
470482

471483
// Action implements actions_service.API

routers/api/v1/repo/action.go

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

529+
func (Action) GetRunners(ctx *context.APIContext) {
530+
shared.GetRunners(ctx, 0, ctx.Repo.Repository.ID)
531+
}
532+
533+
func (Action) GetRunner(ctx *context.APIContext) {
534+
shared.GetRunner(ctx, 0, ctx.Repo.Repository.ID, ctx.PathParamInt64("runner_id"))
535+
}
536+
537+
func (Action) DeleteRunner(ctx *context.APIContext) {
538+
shared.DeleteRunner(ctx, 0, ctx.Repo.Repository.ID, ctx.PathParamInt64("runner_id"))
539+
}
540+
529541
var _ actions_service.API = new(Action)
530542

531543
// Action implements actions_service.API

routers/api/v1/shared/runners.go

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

10+
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
1011
actions_model "code.gitea.io/gitea/models/actions"
12+
"code.gitea.io/gitea/models/db"
13+
api "code.gitea.io/gitea/modules/structs"
1114
"code.gitea.io/gitea/modules/util"
15+
"code.gitea.io/gitea/routers/api/v1/utils"
1216
"code.gitea.io/gitea/services/context"
17+
"code.gitea.io/gitea/services/convert"
1318
)
1419

1520
// RegistrationToken is response related to registration token
@@ -30,3 +35,67 @@ func GetRegistrationToken(ctx *context.APIContext, ownerID, repoID int64) {
3035

3136
ctx.JSON(http.StatusOK, RegistrationToken{Token: token.Token})
3237
}
38+
39+
func GetRunners(ctx *context.APIContext, ownerID, repoID int64) {
40+
runners, total, err := db.FindAndCount[actions_model.ActionRunner](ctx, &actions_model.FindRunnerOptions{
41+
OwnerID: ownerID,
42+
RepoID: repoID,
43+
ListOptions: utils.GetListOptions(ctx),
44+
})
45+
if err != nil {
46+
ctx.APIErrorInternal(err)
47+
return
48+
}
49+
50+
res := new(api.ActionRunnersResponse)
51+
res.TotalCount = total
52+
53+
res.Entries = make([]*api.ActionRunner, len(runners))
54+
for i, runner := range runners {
55+
res.Entries[i] = convert.ToActionRunner(ctx, runner)
56+
}
57+
58+
ctx.JSON(http.StatusOK, &res)
59+
}
60+
61+
func GetRunner(ctx *context.APIContext, ownerID, repoID, runnerID int64) {
62+
runner, exists, err := db.GetByID[actions_model.ActionRunner](ctx, runnerID)
63+
if err != nil {
64+
ctx.APIErrorInternal(err)
65+
return
66+
}
67+
if !exists {
68+
ctx.APIErrorNotFound("Runner does not exist")
69+
return
70+
}
71+
if !runner.Editable(ownerID, repoID) {
72+
ctx.APIErrorNotFound("No permission to get this runner")
73+
return
74+
}
75+
ctx.JSON(http.StatusOK, convert.ToActionRunner(ctx, runner))
76+
}
77+
78+
func DeleteRunner(ctx *context.APIContext, ownerID, repoID, runnerID int64) {
79+
runner, exists, err := db.GetByID[actions_model.ActionRunner](ctx, runnerID)
80+
if err != nil {
81+
ctx.APIErrorInternal(err)
82+
return
83+
}
84+
if !exists {
85+
ctx.APIErrorNotFound("Runner does not exist")
86+
return
87+
}
88+
if !runner.Editable(ownerID, repoID) {
89+
ctx.APIErrorNotFound("No permission to delete this runner")
90+
return
91+
}
92+
if runner.Status() == runnerv1.RunnerStatus_RUNNER_STATUS_ACTIVE {
93+
ctx.APIError(http.StatusConflict, "Runner is active")
94+
return
95+
}
96+
err = actions_model.DeleteRunner(ctx, runner.ID)
97+
if err != nil {
98+
ctx.APIErrorInternal(err)
99+
}
100+
ctx.Status(http.StatusNoContent)
101+
}

services/actions/interface.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,7 @@ type API interface {
2525
UpdateVariable(*context.APIContext)
2626
// GetRegistrationToken get registration token
2727
GetRegistrationToken(*context.APIContext)
28+
GetRunners(*context.APIContext)
29+
GetRunner(*context.APIContext)
30+
DeleteRunner(*context.APIContext)
2831
}

services/convert/convert.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"strings"
1212
"time"
1313

14+
runnerv1 "code.gitea.io/actions-proto-go/runner/v1"
1415
actions_model "code.gitea.io/gitea/models/actions"
1516
asymkey_model "code.gitea.io/gitea/models/asymkey"
1617
"code.gitea.io/gitea/models/auth"
@@ -252,6 +253,31 @@ func ToActionArtifact(repo *repo_model.Repository, art *actions_model.ActionArti
252253
}, nil
253254
}
254255

256+
func ToActionRunner(ctx context.Context, runner *actions_model.ActionRunner) *api.ActionRunner {
257+
status := runner.Status()
258+
apiStatus := "offline"
259+
if runner.IsOnline() {
260+
apiStatus = "online"
261+
}
262+
labels := make([]*api.ActionRunnerLabel, len(runner.AgentLabels))
263+
for i, label := range runner.AgentLabels {
264+
labels = append(labels, &api.ActionRunnerLabel{
265+
ID: int64(i),
266+
Name: label,
267+
Type: "custom",
268+
})
269+
}
270+
return &api.ActionRunner{
271+
ID: runner.ID,
272+
Name: runner.Name,
273+
OS: "Unknown",
274+
Status: apiStatus,
275+
Busy: status == runnerv1.RunnerStatus_RUNNER_STATUS_ACTIVE,
276+
Ephemeral: runner.Ephemeral,
277+
Labels: labels,
278+
}
279+
}
280+
255281
// ToVerification convert a git.Commit.Signature to an api.PayloadCommitVerification
256282
func ToVerification(ctx context.Context, c *git.Commit) *api.PayloadCommitVerification {
257283
verif := asymkey_service.ParseCommitWithSignature(ctx, c)

0 commit comments

Comments
 (0)