aboutsummaryrefslogtreecommitdiffstats
path: root/models/actions/runner.go
diff options
context:
space:
mode:
Diffstat (limited to 'models/actions/runner.go')
-rw-r--r--models/actions/runner.go66
1 files changed, 62 insertions, 4 deletions
diff --git a/models/actions/runner.go b/models/actions/runner.go
index 0d5464a5be..81d4249ae0 100644
--- a/models/actions/runner.go
+++ b/models/actions/runner.go
@@ -5,6 +5,7 @@ package actions
import (
"context"
+ "errors"
"fmt"
"strings"
"time"
@@ -14,6 +15,7 @@ import (
"code.gitea.io/gitea/models/shared/types"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/optional"
+ "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/timeutil"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/util"
@@ -57,6 +59,8 @@ type ActionRunner struct {
// Store labels defined in state file (default: .runner file) of `act_runner`
AgentLabels []string `xorm:"TEXT"`
+ // Store if this is a runner that only ever get one single job assigned
+ Ephemeral bool `xorm:"ephemeral NOT NULL DEFAULT false"`
Created timeutil.TimeStamp `xorm:"created"`
Updated timeutil.TimeStamp `xorm:"updated"`
@@ -84,9 +88,10 @@ func (r *ActionRunner) BelongsToOwnerType() types.OwnerType {
return types.OwnerTypeRepository
}
if r.OwnerID != 0 {
- if r.Owner.Type == user_model.UserTypeOrganization {
+ switch r.Owner.Type {
+ case user_model.UserTypeOrganization:
return types.OwnerTypeOrganization
- } else if r.Owner.Type == user_model.UserTypeIndividual {
+ case user_model.UserTypeIndividual:
return types.OwnerTypeIndividual
}
}
@@ -120,8 +125,15 @@ func (r *ActionRunner) IsOnline() bool {
return false
}
-// Editable checks if the runner is editable by the user
-func (r *ActionRunner) Editable(ownerID, repoID int64) bool {
+// EditableInContext checks if the runner is editable by the "context" owner/repo
+// ownerID == 0 and repoID == 0 means "admin" context, any runner including global runners could be edited
+// ownerID == 0 and repoID != 0 means "repo" context, any runner belonging to the given repo could be edited
+// ownerID != 0 and repoID == 0 means "owner(org/user)" context, any runner belonging to the given user/org could be edited
+// ownerID != 0 and repoID != 0 means "owner" OR "repo" context, legacy behavior, but we should forbid using it
+func (r *ActionRunner) EditableInContext(ownerID, repoID int64) bool {
+ if ownerID != 0 && repoID != 0 {
+ setting.PanicInDevOrTesting("ownerID and repoID should not be both set")
+ }
if ownerID == 0 && repoID == 0 {
return true
}
@@ -165,8 +177,15 @@ func init() {
db.RegisterModel(&ActionRunner{})
}
+// FindRunnerOptions
+// ownerID == 0 and repoID == 0 means any runner including global runners
+// repoID != 0 and WithAvailable == false means any runner for the given repo
+// repoID != 0 and WithAvailable == true means any runner for the given repo, parent user/org, and global runners
+// ownerID != 0 and repoID == 0 and WithAvailable == false means any runner for the given user/org
+// ownerID != 0 and repoID == 0 and WithAvailable == true means any runner for the given user/org and global runners
type FindRunnerOptions struct {
db.ListOptions
+ IDs []int64
RepoID int64
OwnerID int64 // it will be ignored if RepoID is set
Sort string
@@ -178,6 +197,14 @@ type FindRunnerOptions struct {
func (opts FindRunnerOptions) ToConds() builder.Cond {
cond := builder.NewCond()
+ if len(opts.IDs) > 0 {
+ if len(opts.IDs) == 1 {
+ cond = cond.And(builder.Eq{"id": opts.IDs[0]})
+ } else {
+ cond = cond.And(builder.In("id", opts.IDs))
+ }
+ }
+
if opts.RepoID > 0 {
c := builder.NewCond().And(builder.Eq{"repo_id": opts.RepoID})
if opts.WithAvailable {
@@ -272,6 +299,23 @@ func DeleteRunner(ctx context.Context, id int64) error {
return err
}
+// DeleteEphemeralRunner deletes a ephemeral runner by given ID.
+func DeleteEphemeralRunner(ctx context.Context, id int64) error {
+ runner, err := GetRunnerByID(ctx, id)
+ if err != nil {
+ if errors.Is(err, util.ErrNotExist) {
+ return nil
+ }
+ return err
+ }
+ if !runner.Ephemeral {
+ return nil
+ }
+
+ _, err = db.DeleteByID[ActionRunner](ctx, id)
+ return err
+}
+
// CreateRunner creates new runner.
func CreateRunner(ctx context.Context, t *ActionRunner) error {
if t.OwnerID != 0 && t.RepoID != 0 {
@@ -328,3 +372,17 @@ func FixRunnersWithoutBelongingRepo(ctx context.Context) (int64, error) {
}
return res.RowsAffected()
}
+
+func CountWrongRepoLevelRunners(ctx context.Context) (int64, error) {
+ var result int64
+ _, err := db.GetEngine(ctx).SQL("SELECT count(`id`) FROM `action_runner` WHERE `repo_id` > 0 AND `owner_id` > 0").Get(&result)
+ return result, err
+}
+
+func UpdateWrongRepoLevelRunners(ctx context.Context) (int64, error) {
+ result, err := db.GetEngine(ctx).Exec("UPDATE `action_runner` SET `owner_id` = 0 WHERE `repo_id` > 0 AND `owner_id` > 0")
+ if err != nil {
+ return 0, err
+ }
+ return result.RowsAffected()
+}