Make runs-on support variable expression (#29468)
As title. Close issue: https://gitea.com/gitea/act_runner/issues/445 Follow: https://gitea.com/gitea/act/pulls/91 Move `getSecretsOfTask` and `getVariablesOfTask` under `models` because of circular dependency issues. (cherry picked from commit a1f5dd767729e30d07ab42fda80c19f30a72679f)
This commit is contained in:
parent
1090734255
commit
6cb9e8d869
6 changed files with 99 additions and 72 deletions
2
go.mod
2
go.mod
|
@ -299,7 +299,7 @@ replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
|
||||||
|
|
||||||
replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0
|
replace github.com/shurcooL/vfsgen => github.com/lunny/vfsgen v0.0.0-20220105142115-2c99e1ffdfa0
|
||||||
|
|
||||||
replace github.com/nektos/act => gitea.com/gitea/act v0.2.51
|
replace github.com/nektos/act => gitea.com/gitea/act v0.259.1
|
||||||
|
|
||||||
replace github.com/gorilla/feeds => github.com/yardenshoham/feeds v0.0.0-20240110072658-f3d0c21c0bd5
|
replace github.com/gorilla/feeds => github.com/yardenshoham/feeds v0.0.0-20240110072658-f3d0c21c0bd5
|
||||||
|
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -52,8 +52,8 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
|
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078 h1:cliQ4HHsCo6xi2oWZYKWW4bly/Ory9FuTpFPRxj/mAg=
|
||||||
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
|
git.sr.ht/~mariusor/go-xsd-duration v0.0.0-20220703122237-02e73435a078/go.mod h1:g/V2Hjas6Z1UHUp4yIx6bATpNzJ7DYtD0FG3+xARWxs=
|
||||||
gitea.com/gitea/act v0.2.51 h1:gXc/B4OlTciTTzAx9cmNyw04n2SDO7exPjAsR5Idu+c=
|
gitea.com/gitea/act v0.259.1 h1:8GG1o/xtUHl3qjn5f0h/2FXrT5ubBn05TJOM5ry+FBw=
|
||||||
gitea.com/gitea/act v0.2.51/go.mod h1:CoaX2053jqBlD6JMgu4d4UgFL/rp2I14Kt5mMqcs0Z0=
|
gitea.com/gitea/act v0.259.1/go.mod h1:UxZWRYqQG2Yj4+4OqfGWW5a3HELwejyWFQyU7F1jUD8=
|
||||||
gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669 h1:RUBX+MK/TsDxpHmymaOaydfigEbbzqUnG1OTZU/HAeo=
|
gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669 h1:RUBX+MK/TsDxpHmymaOaydfigEbbzqUnG1OTZU/HAeo=
|
||||||
gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669/go.mod h1:77TZu701zMXWJFvB8gvTbQ92zQ3DQq/H7l5wAEjQRKc=
|
gitea.com/go-chi/binding v0.0.0-20230415142243-04b515c6d669/go.mod h1:77TZu701zMXWJFvB8gvTbQ92zQ3DQq/H7l5wAEjQRKc=
|
||||||
gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e/go.mod h1:k2V/gPDEtXGjjMGuBJiapffAXTv76H4snSmlJRLUhH0=
|
gitea.com/go-chi/cache v0.0.0-20210110083709-82c4c9ce2d5e/go.mod h1:k2V/gPDEtXGjjMGuBJiapffAXTv76H4snSmlJRLUhH0=
|
||||||
|
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
|
@ -82,3 +83,35 @@ func UpdateVariable(ctx context.Context, variable *ActionVariable) (bool, error)
|
||||||
})
|
})
|
||||||
return count != 0, err
|
return count != 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetVariablesOfRun(ctx context.Context, run *ActionRun) (map[string]string, error) {
|
||||||
|
variables := map[string]string{}
|
||||||
|
|
||||||
|
// Global
|
||||||
|
globalVariables, err := db.Find[ActionVariable](ctx, FindVariablesOpts{})
|
||||||
|
if err != nil {
|
||||||
|
log.Error("find global variables: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Org / User level
|
||||||
|
ownerVariables, err := db.Find[ActionVariable](ctx, FindVariablesOpts{OwnerID: 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})
|
||||||
|
if err != nil {
|
||||||
|
log.Error("find variables of repo: %d, error: %v", run.RepoID, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Level precedence: Repo > Org / User > Global
|
||||||
|
for _, v := range append(globalVariables, append(ownerVariables, repoVariables...)...) {
|
||||||
|
variables[v.Name] = v.Data
|
||||||
|
}
|
||||||
|
|
||||||
|
return variables, nil
|
||||||
|
}
|
||||||
|
|
|
@ -9,7 +9,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
actions_model "code.gitea.io/gitea/models/actions"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
actions_module "code.gitea.io/gitea/modules/actions"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
secret_module "code.gitea.io/gitea/modules/secret"
|
secret_module "code.gitea.io/gitea/modules/secret"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
|
@ -112,3 +115,39 @@ func UpdateSecret(ctx context.Context, secretID int64, data string) error {
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSecretsOfTask(ctx context.Context, task *actions_model.ActionTask) (map[string]string, error) {
|
||||||
|
secrets := map[string]string{}
|
||||||
|
|
||||||
|
secrets["GITHUB_TOKEN"] = task.Token
|
||||||
|
secrets["GITEA_TOKEN"] = task.Token
|
||||||
|
|
||||||
|
if task.Job.Run.IsForkPullRequest && task.Job.Run.TriggerEvent != actions_module.GithubEventPullRequestTarget {
|
||||||
|
// ignore secrets for fork pull request, except GITHUB_TOKEN and GITEA_TOKEN which are automatically generated.
|
||||||
|
// for the tasks triggered by pull_request_target event, they could access the secrets because they will run in the context of the base branch
|
||||||
|
// see the documentation: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target
|
||||||
|
return secrets, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
ownerSecrets, err := db.Find[Secret](ctx, FindSecretsOptions{OwnerID: 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})
|
||||||
|
if err != nil {
|
||||||
|
log.Error("find secrets of repo %v: %v", task.Job.Run.RepoID, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, secret := range append(ownerSecrets, repoSecrets...) {
|
||||||
|
v, err := secret_module.DecryptSecret(setting.SecretKey, secret.Data)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("decrypt secret %v %q: %v", secret.ID, secret.Name, err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
secrets[secret.Name] = v
|
||||||
|
}
|
||||||
|
|
||||||
|
return secrets, nil
|
||||||
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@ import (
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/json"
|
"code.gitea.io/gitea/modules/json"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
secret_module "code.gitea.io/gitea/modules/secret"
|
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/services/actions"
|
"code.gitea.io/gitea/services/actions"
|
||||||
|
|
||||||
|
@ -32,14 +31,24 @@ func pickTask(ctx context.Context, runner *actions_model.ActionRunner) (*runnerv
|
||||||
return nil, false, nil
|
return nil, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
secrets, err := secret_model.GetSecretsOfTask(ctx, t)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, fmt.Errorf("GetSecretsOfTask: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
vars, err := actions_model.GetVariablesOfRun(ctx, t.Job.Run)
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, fmt.Errorf("GetVariablesOfRun: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
actions.CreateCommitStatus(ctx, t.Job)
|
actions.CreateCommitStatus(ctx, t.Job)
|
||||||
|
|
||||||
task := &runnerv1.Task{
|
task := &runnerv1.Task{
|
||||||
Id: t.ID,
|
Id: t.ID,
|
||||||
WorkflowPayload: t.Job.WorkflowPayload,
|
WorkflowPayload: t.Job.WorkflowPayload,
|
||||||
Context: generateTaskContext(t),
|
Context: generateTaskContext(t),
|
||||||
Secrets: getSecretsOfTask(ctx, t),
|
Secrets: secrets,
|
||||||
Vars: getVariablesOfTask(ctx, t),
|
Vars: vars,
|
||||||
}
|
}
|
||||||
|
|
||||||
if needs, err := findTaskNeeds(ctx, t); err != nil {
|
if needs, err := findTaskNeeds(ctx, t); err != nil {
|
||||||
|
@ -55,71 +64,6 @@ func pickTask(ctx context.Context, runner *actions_model.ActionRunner) (*runnerv
|
||||||
return task, true, nil
|
return task, true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSecretsOfTask(ctx context.Context, task *actions_model.ActionTask) map[string]string {
|
|
||||||
secrets := map[string]string{}
|
|
||||||
|
|
||||||
secrets["GITHUB_TOKEN"] = task.Token
|
|
||||||
secrets["GITEA_TOKEN"] = task.Token
|
|
||||||
|
|
||||||
if task.Job.Run.IsForkPullRequest && task.Job.Run.TriggerEvent != actions_module.GithubEventPullRequestTarget {
|
|
||||||
// ignore secrets for fork pull request, except GITHUB_TOKEN and GITEA_TOKEN which are automatically generated.
|
|
||||||
// for the tasks triggered by pull_request_target event, they could access the secrets because they will run in the context of the base branch
|
|
||||||
// see the documentation: https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target
|
|
||||||
return secrets
|
|
||||||
}
|
|
||||||
|
|
||||||
ownerSecrets, err := db.Find[secret_model.Secret](ctx, secret_model.FindSecretsOptions{OwnerID: task.Job.Run.Repo.OwnerID})
|
|
||||||
if err != nil {
|
|
||||||
log.Error("find secrets of owner %v: %v", task.Job.Run.Repo.OwnerID, err)
|
|
||||||
// go on
|
|
||||||
}
|
|
||||||
repoSecrets, err := db.Find[secret_model.Secret](ctx, secret_model.FindSecretsOptions{RepoID: task.Job.Run.RepoID})
|
|
||||||
if err != nil {
|
|
||||||
log.Error("find secrets of repo %v: %v", task.Job.Run.RepoID, err)
|
|
||||||
// go on
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, secret := range append(ownerSecrets, repoSecrets...) {
|
|
||||||
if v, err := secret_module.DecryptSecret(setting.SecretKey, secret.Data); err != nil {
|
|
||||||
log.Error("decrypt secret %v %q: %v", secret.ID, secret.Name, err)
|
|
||||||
// go on
|
|
||||||
} else {
|
|
||||||
secrets[secret.Name] = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return secrets
|
|
||||||
}
|
|
||||||
|
|
||||||
func getVariablesOfTask(ctx context.Context, task *actions_model.ActionTask) map[string]string {
|
|
||||||
variables := map[string]string{}
|
|
||||||
|
|
||||||
// Global
|
|
||||||
globalVariables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{})
|
|
||||||
if err != nil {
|
|
||||||
log.Error("find global variables: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Org / User level
|
|
||||||
ownerVariables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{OwnerID: task.Job.Run.Repo.OwnerID})
|
|
||||||
if err != nil {
|
|
||||||
log.Error("find variables of org: %d, error: %v", task.Job.Run.Repo.OwnerID, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Repo level
|
|
||||||
repoVariables, err := db.Find[actions_model.ActionVariable](ctx, actions_model.FindVariablesOpts{RepoID: task.Job.Run.RepoID})
|
|
||||||
if err != nil {
|
|
||||||
log.Error("find variables of repo: %d, error: %v", task.Job.Run.RepoID, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Level precedence: Repo > Org / User > Global
|
|
||||||
for _, v := range append(globalVariables, append(ownerVariables, repoVariables...)...) {
|
|
||||||
variables[v.Name] = v.Data
|
|
||||||
}
|
|
||||||
|
|
||||||
return variables
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateTaskContext(t *actions_model.ActionTask) *structpb.Struct {
|
func generateTaskContext(t *actions_model.ActionTask) *structpb.Struct {
|
||||||
event := map[string]any{}
|
event := map[string]any{}
|
||||||
_ = json.Unmarshal([]byte(t.Job.Run.EventPayload), &event)
|
_ = json.Unmarshal([]byte(t.Job.Run.EventPayload), &event)
|
||||||
|
|
|
@ -305,7 +305,18 @@ func handleWorkflows(
|
||||||
run.NeedApproval = need
|
run.NeedApproval = need
|
||||||
}
|
}
|
||||||
|
|
||||||
jobs, err := jobparser.Parse(dwf.Content)
|
if err := run.LoadAttributes(ctx); err != nil {
|
||||||
|
log.Error("LoadAttributes: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
vars, err := actions_model.GetVariablesOfRun(ctx, run)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("GetVariablesOfRun: %v", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
jobs, err := jobparser.Parse(dwf.Content, jobparser.WithVars(vars))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("jobparser.Parse: %v", err)
|
log.Error("jobparser.Parse: %v", err)
|
||||||
continue
|
continue
|
||||||
|
|
Loading…
Reference in a new issue