1
1
mirror of https://github.com/go-gitea/gitea synced 2025-07-22 18:28:37 +00:00

Enhance routers for the Actions runner operations (#33549)

- Find the runner before deleting
- Move the main logic from `routers/web/repo/setting/runners.go` to
`routers/web/shared/actions/runners.go`.

---------

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
This commit is contained in:
Jason Song
2025-02-11 09:39:10 +08:00
committed by GitHub
parent 217ffe5492
commit e9b98aef44
5 changed files with 387 additions and 207 deletions

View File

@@ -5,18 +5,131 @@ package actions
import (
"errors"
"net/http"
"net/url"
actions_model "code.gitea.io/gitea/models/actions"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/templates"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/web"
shared_user "code.gitea.io/gitea/routers/web/shared/user"
"code.gitea.io/gitea/services/context"
"code.gitea.io/gitea/services/forms"
)
// RunnersList prepares data for runners list
func RunnersList(ctx *context.Context, opts actions_model.FindRunnerOptions) {
const (
// TODO: Separate secrets from runners when layout is ready
tplRepoRunners templates.TplName = "repo/settings/actions"
tplOrgRunners templates.TplName = "org/settings/actions"
tplAdminRunners templates.TplName = "admin/actions"
tplUserRunners templates.TplName = "user/settings/actions"
tplRepoRunnerEdit templates.TplName = "repo/settings/runner_edit"
tplOrgRunnerEdit templates.TplName = "org/settings/runners_edit"
tplAdminRunnerEdit templates.TplName = "admin/runners/edit"
tplUserRunnerEdit templates.TplName = "user/settings/runner_edit"
)
type runnersCtx struct {
OwnerID int64
RepoID int64
IsRepo bool
IsOrg bool
IsAdmin bool
IsUser bool
RunnersTemplate templates.TplName
RunnerEditTemplate templates.TplName
RedirectLink string
}
func getRunnersCtx(ctx *context.Context) (*runnersCtx, error) {
if ctx.Data["PageIsRepoSettings"] == true {
return &runnersCtx{
RepoID: ctx.Repo.Repository.ID,
OwnerID: 0,
IsRepo: true,
RunnersTemplate: tplRepoRunners,
RunnerEditTemplate: tplRepoRunnerEdit,
RedirectLink: ctx.Repo.RepoLink + "/settings/actions/runners/",
}, nil
}
if ctx.Data["PageIsOrgSettings"] == true {
err := shared_user.LoadHeaderCount(ctx)
if err != nil {
ctx.ServerError("LoadHeaderCount", err)
return nil, nil
}
return &runnersCtx{
RepoID: 0,
OwnerID: ctx.Org.Organization.ID,
IsOrg: true,
RunnersTemplate: tplOrgRunners,
RunnerEditTemplate: tplOrgRunnerEdit,
RedirectLink: ctx.Org.OrgLink + "/settings/actions/runners/",
}, nil
}
if ctx.Data["PageIsAdmin"] == true {
return &runnersCtx{
RepoID: 0,
OwnerID: 0,
IsAdmin: true,
RunnersTemplate: tplAdminRunners,
RunnerEditTemplate: tplAdminRunnerEdit,
RedirectLink: setting.AppSubURL + "/-/admin/actions/runners/",
}, nil
}
if ctx.Data["PageIsUserSettings"] == true {
return &runnersCtx{
OwnerID: ctx.Doer.ID,
RepoID: 0,
IsUser: true,
RunnersTemplate: tplUserRunners,
RunnerEditTemplate: tplUserRunnerEdit,
RedirectLink: setting.AppSubURL + "/user/settings/actions/runners/",
}, nil
}
return nil, errors.New("unable to set Runners context")
}
// Runners render settings/actions/runners page for repo level
func Runners(ctx *context.Context) {
ctx.Data["PageIsSharedSettingsRunners"] = true
ctx.Data["Title"] = ctx.Tr("actions.actions")
ctx.Data["PageType"] = "runners"
rCtx, err := getRunnersCtx(ctx)
if err != nil {
ctx.ServerError("getRunnersCtx", err)
return
}
page := ctx.FormInt("page")
if page <= 1 {
page = 1
}
opts := actions_model.FindRunnerOptions{
ListOptions: db.ListOptions{
Page: page,
PageSize: 100,
},
Sort: ctx.Req.URL.Query().Get("sort"),
Filter: ctx.Req.URL.Query().Get("q"),
}
if rCtx.IsRepo {
opts.RepoID = rCtx.RepoID
opts.WithAvailable = true
} else if rCtx.IsOrg || rCtx.IsUser {
opts.OwnerID = rCtx.OwnerID
opts.WithAvailable = true
}
runners, count, err := db.FindAndCount[actions_model.ActionRunner](ctx, opts)
if err != nil {
ctx.ServerError("CountRunners", err)
@@ -53,10 +166,29 @@ func RunnersList(ctx *context.Context, opts actions_model.FindRunnerOptions) {
pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5)
ctx.Data["Page"] = pager
ctx.HTML(http.StatusOK, rCtx.RunnersTemplate)
}
// RunnerDetails prepares data for runners edit page
func RunnerDetails(ctx *context.Context, page int, runnerID, ownerID, repoID int64) {
// RunnersEdit renders runner edit page for repository level
func RunnersEdit(ctx *context.Context) {
ctx.Data["PageIsSharedSettingsRunners"] = true
ctx.Data["Title"] = ctx.Tr("actions.runners.edit_runner")
rCtx, err := getRunnersCtx(ctx)
if err != nil {
ctx.ServerError("getRunnersCtx", err)
return
}
page := ctx.FormInt("page")
if page <= 1 {
page = 1
}
runnerID := ctx.PathParamInt64("runnerid")
ownerID := rCtx.OwnerID
repoID := rCtx.RepoID
runner, err := actions_model.GetRunnerByID(ctx, runnerID)
if err != nil {
ctx.ServerError("GetRunnerByID", err)
@@ -97,10 +229,22 @@ func RunnerDetails(ctx *context.Context, page int, runnerID, ownerID, repoID int
ctx.Data["Tasks"] = tasks
pager := context.NewPagination(int(count), opts.PageSize, opts.Page, 5)
ctx.Data["Page"] = pager
ctx.HTML(http.StatusOK, rCtx.RunnerEditTemplate)
}
// RunnerDetailsEditPost response for edit runner details
func RunnerDetailsEditPost(ctx *context.Context, runnerID, ownerID, repoID int64, redirectTo string) {
func RunnersEditPost(ctx *context.Context) {
rCtx, err := getRunnersCtx(ctx)
if err != nil {
ctx.ServerError("getRunnersCtx", err)
return
}
runnerID := ctx.PathParamInt64("runnerid")
ownerID := rCtx.OwnerID
repoID := rCtx.RepoID
redirectTo := rCtx.RedirectLink
runner, err := actions_model.GetRunnerByID(ctx, runnerID)
if err != nil {
log.Warn("RunnerDetailsEditPost.GetRunnerByID failed: %v, url: %s", err, ctx.Req.URL)
@@ -129,10 +273,18 @@ func RunnerDetailsEditPost(ctx *context.Context, runnerID, ownerID, repoID int64
ctx.Redirect(redirectTo)
}
// RunnerResetRegistrationToken reset registration token
func RunnerResetRegistrationToken(ctx *context.Context, ownerID, repoID int64, redirectTo string) {
_, err := actions_model.NewRunnerToken(ctx, ownerID, repoID)
func ResetRunnerRegistrationToken(ctx *context.Context) {
rCtx, err := getRunnersCtx(ctx)
if err != nil {
ctx.ServerError("getRunnersCtx", err)
return
}
ownerID := rCtx.OwnerID
repoID := rCtx.RepoID
redirectTo := rCtx.RedirectLink
if _, err := actions_model.NewRunnerToken(ctx, ownerID, repoID); err != nil {
ctx.ServerError("ResetRunnerRegistrationToken", err)
return
}
@@ -140,11 +292,28 @@ func RunnerResetRegistrationToken(ctx *context.Context, ownerID, repoID int64, r
ctx.JSONRedirect(redirectTo)
}
// RunnerDeletePost response for deleting a runner
func RunnerDeletePost(ctx *context.Context, runnerID int64,
successRedirectTo, failedRedirectTo string,
) {
if err := actions_model.DeleteRunner(ctx, runnerID); err != nil {
// RunnerDeletePost response for deleting runner
func RunnerDeletePost(ctx *context.Context) {
rCtx, err := getRunnersCtx(ctx)
if err != nil {
ctx.ServerError("getRunnersCtx", err)
return
}
runner := findActionsRunner(ctx, rCtx)
if ctx.Written() {
return
}
if !runner.Editable(rCtx.OwnerID, rCtx.RepoID) {
ctx.NotFound("RunnerDeletePost", util.NewPermissionDeniedErrorf("no permission to delete this runner"))
return
}
successRedirectTo := rCtx.RedirectLink
failedRedirectTo := rCtx.RedirectLink + url.PathEscape(ctx.PathParam("runnerid"))
if err := actions_model.DeleteRunner(ctx, runner.ID); err != nil {
log.Warn("DeleteRunnerPost.UpdateRunner failed: %v, url: %s", err, ctx.Req.URL)
ctx.Flash.Warning(ctx.Tr("actions.runners.delete_runner_failed"))
@@ -158,3 +327,41 @@ func RunnerDeletePost(ctx *context.Context, runnerID int64,
ctx.JSONRedirect(successRedirectTo)
}
func RedirectToDefaultSetting(ctx *context.Context) {
ctx.Redirect(ctx.Repo.RepoLink + "/settings/actions/runners")
}
func findActionsRunner(ctx *context.Context, rCtx *runnersCtx) *actions_model.ActionRunner {
runnerID := ctx.PathParamInt64("runnerid")
opts := &actions_model.FindRunnerOptions{
IDs: []int64{runnerID},
}
switch {
case rCtx.IsRepo:
opts.RepoID = rCtx.RepoID
if opts.RepoID == 0 {
panic("repoID is 0")
}
case rCtx.IsOrg, rCtx.IsUser:
opts.OwnerID = rCtx.OwnerID
if opts.OwnerID == 0 {
panic("ownerID is 0")
}
case rCtx.IsAdmin:
// do nothing
default:
panic("invalid actions runner context")
}
got, err := db.Find[actions_model.ActionRunner](ctx, opts)
if err != nil {
ctx.ServerError("FindRunner", err)
return nil
} else if len(got) == 0 {
ctx.NotFound("FindRunner", errors.New("runner not found"))
return nil
}
return got[0]
}