mirror of
https://github.com/go-gitea/gitea.git
synced 2026-10-18 22:36:43 +09:00
refactor(actions): pass secret and variable scope as a struct (#39719)
Secret and variable functions took an adjacent `ownerID, repoID int64` pair, so swapping the two compiled and only failed at runtime. They now take a `BelongingScope` value instead. `BelongingScope` also replaces the "drop OwnerID when RepoID is set" step that `InsertEncryptedSecret` and `InsertVariable` each implemented separately No behaviour change. It also makes adding another scope dimension, such as the environment ID in https://github.com/go-gitea/gitea/pull/38149, a one-field change. --------- Co-authored-by: wxiaoguang <wxiaoguang@gmail.com> Co-authored-by: Zettat123 <zettat123@gmail.com>
This commit is contained in:
13 files changed
+135
-163
No files matched your search
@@ -0,0 +1,28 @@
|
||||
// Copyright 2026 The Gitea Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package actions
|
||||
|
||||
// BelongingScope identifies the owner (user/org) or repository an Actions secret or variable belongs to.
|
||||
// Both zero values mean "global scope".
|
||||
// Always use the functions to create a BelongingScope, rather than creating one directly, to avoid accidentally creating an invalid scope.
|
||||
type BelongingScope struct {
|
||||
internalOwnerID int64
|
||||
internalRepoID int64
|
||||
}
|
||||
|
||||
func BelongingScopeOwner(ownerID int64) BelongingScope {
|
||||
return BelongingScope{internalOwnerID: ownerID}
|
||||
}
|
||||
|
||||
func BelongingScopeRepo(repoID int64) BelongingScope {
|
||||
return BelongingScope{internalRepoID: repoID}
|
||||
}
|
||||
|
||||
func BelongingScopeGlobal() BelongingScope {
|
||||
return BelongingScope{}
|
||||
}
|
||||
|
||||
func (scope BelongingScope) GetOwnerRepoIDs() (ownerID, repoID int64) {
|
||||
return scope.internalOwnerID, scope.internalRepoID
|
||||
}
|
||||
+13
-18
@@ -48,13 +48,7 @@ func init() {
|
||||
db.RegisterModel(new(ActionVariable))
|
||||
}
|
||||
|
||||
func InsertVariable(ctx context.Context, ownerID, repoID int64, name, data, description string) (*ActionVariable, error) {
|
||||
if ownerID != 0 && repoID != 0 {
|
||||
// It's trying to create a variable that belongs to a repository, but OwnerID has been set accidentally.
|
||||
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
|
||||
ownerID = 0
|
||||
}
|
||||
|
||||
func InsertVariable(ctx context.Context, scope BelongingScope, name, data, description string) (*ActionVariable, error) {
|
||||
if utf8.RuneCountInString(data) > VariableDataMaxLength {
|
||||
return nil, util.NewInvalidArgumentErrorf("data too long")
|
||||
}
|
||||
@@ -62,8 +56,8 @@ func InsertVariable(ctx context.Context, ownerID, repoID int64, name, data, desc
|
||||
description = util.TruncateRunes(description, VariableDescriptionMaxLength)
|
||||
|
||||
variable := &ActionVariable{
|
||||
OwnerID: ownerID,
|
||||
RepoID: repoID,
|
||||
OwnerID: scope.internalOwnerID,
|
||||
RepoID: scope.internalRepoID,
|
||||
Name: strings.ToUpper(name),
|
||||
Data: data,
|
||||
Description: description,
|
||||
@@ -73,10 +67,10 @@ func InsertVariable(ctx context.Context, ownerID, repoID int64, name, data, desc
|
||||
|
||||
type FindVariablesOpts struct {
|
||||
db.ListOptions
|
||||
IDs []int64
|
||||
RepoID int64
|
||||
OwnerID int64 // it will be ignored if RepoID is set
|
||||
Name string
|
||||
IDs []int64
|
||||
Name string
|
||||
|
||||
BelongingScope BelongingScope
|
||||
}
|
||||
|
||||
func (opts FindVariablesOpts) ToOrders() string {
|
||||
@@ -96,12 +90,13 @@ func (opts FindVariablesOpts) ToConds() builder.Cond {
|
||||
|
||||
// Since we now support instance-level variables,
|
||||
// there is no need to check for null values for `owner_id` and `repo_id`
|
||||
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
||||
if opts.RepoID != 0 { // if RepoID is set
|
||||
ownerID, repoID := opts.BelongingScope.GetOwnerRepoIDs()
|
||||
cond = cond.And(builder.Eq{"repo_id": repoID})
|
||||
if repoID != 0 { // if RepoID is set
|
||||
// ignore OwnerID and treat it as 0
|
||||
cond = cond.And(builder.Eq{"owner_id": 0})
|
||||
} else {
|
||||
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
|
||||
cond = cond.And(builder.Eq{"owner_id": ownerID})
|
||||
}
|
||||
|
||||
if opts.Name != "" {
|
||||
@@ -152,14 +147,14 @@ func GetVariablesOfRun(ctx context.Context, run *ActionRun) (map[string]string,
|
||||
}
|
||||
|
||||
// Org / User level
|
||||
ownerVariables, err := db.Find[ActionVariable](ctx, FindVariablesOpts{OwnerID: run.Repo.OwnerID})
|
||||
ownerVariables, err := db.Find[ActionVariable](ctx, FindVariablesOpts{BelongingScope: BelongingScopeOwner(run.Repo.OwnerID)})
|
||||
if err != nil {
|
||||
log.Error("find variables of org: %d, error: %v", run.Repo.OwnerID, err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Repo level
|
||||
repoVariables, err := db.Find[ActionVariable](ctx, FindVariablesOpts{RepoID: run.RepoID})
|
||||
repoVariables, err := db.Find[ActionVariable](ctx, FindVariablesOpts{BelongingScope: BelongingScopeRepo(run.RepoID)})
|
||||
if err != nil {
|
||||
log.Error("find variables of repo: %d, error: %v", run.RepoID, err)
|
||||
return nil, err
|
||||
|
||||
+13
-18
@@ -65,20 +65,15 @@ func (err ErrSecretNotFound) Unwrap() error {
|
||||
}
|
||||
|
||||
// InsertEncryptedSecret Creates, encrypts, and validates a new secret with yet unencrypted data and insert into database
|
||||
func InsertEncryptedSecret(ctx context.Context, ownerID, repoID int64, name, data, description string) (*Secret, error) {
|
||||
if ownerID != 0 && repoID != 0 {
|
||||
// It's trying to create a secret that belongs to a repository, but OwnerID has been set accidentally.
|
||||
// Remove OwnerID to avoid confusion; it's not worth returning an error here.
|
||||
ownerID = 0
|
||||
}
|
||||
if ownerID == 0 && repoID == 0 {
|
||||
return nil, fmt.Errorf("%w: ownerID and repoID cannot be both zero, global secrets are not supported", util.ErrInvalidArgument)
|
||||
}
|
||||
|
||||
func InsertEncryptedSecret(ctx context.Context, scope actions_model.BelongingScope, name, data, description string) (*Secret, error) {
|
||||
if len(data) > SecretDataMaxLength {
|
||||
return nil, util.NewInvalidArgumentErrorf("data too long")
|
||||
}
|
||||
|
||||
ownerID, repoID := scope.GetOwnerRepoIDs()
|
||||
if ownerID == 0 && repoID == 0 {
|
||||
return nil, fmt.Errorf("%w: ownerID and repoID cannot be both zero, global secrets are not supported", util.ErrInvalidArgument)
|
||||
}
|
||||
description = util.TruncateRunes(description, SecretDescriptionMaxLength)
|
||||
|
||||
encrypted, err := secret_module.EncryptSecret(setting.SecretKey, data)
|
||||
@@ -102,10 +97,10 @@ func init() {
|
||||
|
||||
type FindSecretsOptions struct {
|
||||
db.ListOptions
|
||||
RepoID int64
|
||||
OwnerID int64 // it will be ignored if RepoID is set
|
||||
SecretID int64
|
||||
Name string
|
||||
|
||||
BelongingScope actions_model.BelongingScope
|
||||
}
|
||||
|
||||
func (opts FindSecretsOptions) ToOrders() string {
|
||||
@@ -114,13 +109,13 @@ func (opts FindSecretsOptions) ToOrders() string {
|
||||
|
||||
func (opts FindSecretsOptions) ToConds() builder.Cond {
|
||||
cond := builder.NewCond()
|
||||
|
||||
cond = cond.And(builder.Eq{"repo_id": opts.RepoID})
|
||||
if opts.RepoID != 0 { // if RepoID is set
|
||||
ownerID, repoID := opts.BelongingScope.GetOwnerRepoIDs()
|
||||
cond = cond.And(builder.Eq{"repo_id": repoID})
|
||||
if repoID != 0 { // if RepoID is set
|
||||
// ignore OwnerID and treat it as 0
|
||||
cond = cond.And(builder.Eq{"owner_id": 0})
|
||||
} else {
|
||||
cond = cond.And(builder.Eq{"owner_id": opts.OwnerID})
|
||||
cond = cond.And(builder.Eq{"owner_id": ownerID})
|
||||
}
|
||||
|
||||
if opts.SecretID != 0 {
|
||||
@@ -170,12 +165,12 @@ func GetSecretsOfTask(ctx context.Context, task *actions_model.ActionTask) (map[
|
||||
return baseSecrets, nil
|
||||
}
|
||||
|
||||
ownerSecrets, err := db.Find[Secret](ctx, FindSecretsOptions{OwnerID: task.Job.Run.Repo.OwnerID})
|
||||
ownerSecrets, err := db.Find[Secret](ctx, FindSecretsOptions{BelongingScope: actions_model.BelongingScopeOwner(task.Job.Run.Repo.OwnerID)})
|
||||
if err != nil {
|
||||
log.Error("find secrets of owner %v: %v", task.Job.Run.Repo.OwnerID, err)
|
||||
return nil, err
|
||||
}
|
||||
repoSecrets, err := db.Find[Secret](ctx, FindSecretsOptions{RepoID: task.Job.Run.RepoID})
|
||||
repoSecrets, err := db.Find[Secret](ctx, FindSecretsOptions{BelongingScope: actions_model.BelongingScopeRepo(task.Job.Run.RepoID)})
|
||||
if err != nil {
|
||||
log.Error("find secrets of repo %v: %v", task.Job.Run.RepoID, err)
|
||||
return nil, err
|
||||
|
||||
Reference in new issue
Block a user