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  }