code.gitea.io/gitea@v1.22.3/models/actions/variable.go (about) 1 // Copyright 2023 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package actions 5 6 import ( 7 "context" 8 "errors" 9 "strings" 10 11 "code.gitea.io/gitea/models/db" 12 "code.gitea.io/gitea/modules/log" 13 "code.gitea.io/gitea/modules/timeutil" 14 15 "xorm.io/builder" 16 ) 17 18 type ActionVariable struct { 19 ID int64 `xorm:"pk autoincr"` 20 OwnerID int64 `xorm:"UNIQUE(owner_repo_name)"` 21 RepoID int64 `xorm:"INDEX UNIQUE(owner_repo_name)"` 22 Name string `xorm:"UNIQUE(owner_repo_name) NOT NULL"` 23 Data string `xorm:"LONGTEXT NOT NULL"` 24 CreatedUnix timeutil.TimeStamp `xorm:"created NOT NULL"` 25 UpdatedUnix timeutil.TimeStamp `xorm:"updated"` 26 } 27 28 func init() { 29 db.RegisterModel(new(ActionVariable)) 30 } 31 32 func (v *ActionVariable) Validate() error { 33 if v.OwnerID != 0 && v.RepoID != 0 { 34 return errors.New("a variable should not be bound to an owner and a repository at the same time") 35 } 36 return nil 37 } 38 39 func InsertVariable(ctx context.Context, ownerID, repoID int64, name, data string) (*ActionVariable, error) { 40 variable := &ActionVariable{ 41 OwnerID: ownerID, 42 RepoID: repoID, 43 Name: strings.ToUpper(name), 44 Data: data, 45 } 46 if err := variable.Validate(); err != nil { 47 return variable, err 48 } 49 return variable, db.Insert(ctx, variable) 50 } 51 52 type FindVariablesOpts struct { 53 db.ListOptions 54 OwnerID int64 55 RepoID int64 56 Name string 57 } 58 59 func (opts FindVariablesOpts) ToConds() builder.Cond { 60 cond := builder.NewCond() 61 // Since we now support instance-level variables, 62 // there is no need to check for null values for `owner_id` and `repo_id` 63 cond = cond.And(builder.Eq{"owner_id": opts.OwnerID}) 64 cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) 65 66 if opts.Name != "" { 67 cond = cond.And(builder.Eq{"name": strings.ToUpper(opts.Name)}) 68 } 69 return cond 70 } 71 72 func FindVariables(ctx context.Context, opts FindVariablesOpts) ([]*ActionVariable, error) { 73 return db.Find[ActionVariable](ctx, opts) 74 } 75 76 func UpdateVariable(ctx context.Context, variable *ActionVariable) (bool, error) { 77 count, err := db.GetEngine(ctx).ID(variable.ID).Cols("name", "data"). 78 Update(&ActionVariable{ 79 Name: variable.Name, 80 Data: variable.Data, 81 }) 82 return count != 0, err 83 } 84 85 func DeleteVariable(ctx context.Context, id int64) error { 86 if _, err := db.DeleteByID[ActionVariable](ctx, id); err != nil { 87 return err 88 } 89 return nil 90 } 91 92 func GetVariablesOfRun(ctx context.Context, run *ActionRun) (map[string]string, error) { 93 variables := map[string]string{} 94 95 if err := run.LoadRepo(ctx); err != nil { 96 log.Error("LoadRepo: %v", err) 97 return nil, err 98 } 99 100 // Global 101 globalVariables, err := db.Find[ActionVariable](ctx, FindVariablesOpts{}) 102 if err != nil { 103 log.Error("find global variables: %v", err) 104 return nil, err 105 } 106 107 // Org / User level 108 ownerVariables, err := db.Find[ActionVariable](ctx, FindVariablesOpts{OwnerID: run.Repo.OwnerID}) 109 if err != nil { 110 log.Error("find variables of org: %d, error: %v", run.Repo.OwnerID, err) 111 return nil, err 112 } 113 114 // Repo level 115 repoVariables, err := db.Find[ActionVariable](ctx, FindVariablesOpts{RepoID: run.RepoID}) 116 if err != nil { 117 log.Error("find variables of repo: %d, error: %v", run.RepoID, err) 118 return nil, err 119 } 120 121 // Level precedence: Repo > Org / User > Global 122 for _, v := range append(globalVariables, append(ownerVariables, repoVariables...)...) { 123 variables[v.Name] = v.Data 124 } 125 126 return variables, nil 127 }