Follow upstream support for variables
(#66)
Because the upstream [PR](https://github.com/nektos/act/pull/1833) already supports variables, so this PR revert #43 (commitde529139af
), and cherry-pick commit [6ce45e3
](6ce45e3f24
). Co-authored-by: Kuan Yong <wong0514@gmail.com> Reviewed-on: https://gitea.com/gitea/act/pulls/66 Reviewed-by: Jason Song <i@wolfogre.com> Co-authored-by: sillyguodong <gedong_1994@163.com> Co-committed-by: sillyguodong <gedong_1994@163.com>
This commit is contained in:
parent
6ce5c93cc8
commit
fe76a035ad
9 changed files with 38 additions and 15 deletions
|
@ -16,6 +16,7 @@ type Input struct {
|
||||||
reuseContainers bool
|
reuseContainers bool
|
||||||
bindWorkdir bool
|
bindWorkdir bool
|
||||||
secrets []string
|
secrets []string
|
||||||
|
vars []string
|
||||||
envs []string
|
envs []string
|
||||||
inputs []string
|
inputs []string
|
||||||
platforms []string
|
platforms []string
|
||||||
|
@ -26,6 +27,7 @@ type Input struct {
|
||||||
envfile string
|
envfile string
|
||||||
inputfile string
|
inputfile string
|
||||||
secretfile string
|
secretfile string
|
||||||
|
varfile string
|
||||||
insecureSecrets bool
|
insecureSecrets bool
|
||||||
defaultBranch string
|
defaultBranch string
|
||||||
privileged bool
|
privileged bool
|
||||||
|
@ -78,6 +80,10 @@ func (i *Input) Secretfile() string {
|
||||||
return i.resolve(i.secretfile)
|
return i.resolve(i.secretfile)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *Input) Varfile() string {
|
||||||
|
return i.resolve(i.varfile)
|
||||||
|
}
|
||||||
|
|
||||||
// Workdir returns path to workdir
|
// Workdir returns path to workdir
|
||||||
func (i *Input) Workdir() string {
|
func (i *Input) Workdir() string {
|
||||||
return i.resolve(".")
|
return i.resolve(".")
|
||||||
|
|
|
@ -49,6 +49,7 @@ func Execute(ctx context.Context, version string) {
|
||||||
|
|
||||||
rootCmd.Flags().StringVar(&input.remoteName, "remote-name", "origin", "git remote name that will be used to retrieve url of git repo")
|
rootCmd.Flags().StringVar(&input.remoteName, "remote-name", "origin", "git remote name that will be used to retrieve url of git repo")
|
||||||
rootCmd.Flags().StringArrayVarP(&input.secrets, "secret", "s", []string{}, "secret to make available to actions with optional value (e.g. -s mysecret=foo or -s mysecret)")
|
rootCmd.Flags().StringArrayVarP(&input.secrets, "secret", "s", []string{}, "secret to make available to actions with optional value (e.g. -s mysecret=foo or -s mysecret)")
|
||||||
|
rootCmd.Flags().StringArrayVar(&input.vars, "var", []string{}, "variable to make available to actions with optional value (e.g. --var myvar=foo or --var myvar)")
|
||||||
rootCmd.Flags().StringArrayVarP(&input.envs, "env", "", []string{}, "env to make available to actions with optional value (e.g. --env myenv=foo or --env myenv)")
|
rootCmd.Flags().StringArrayVarP(&input.envs, "env", "", []string{}, "env to make available to actions with optional value (e.g. --env myenv=foo or --env myenv)")
|
||||||
rootCmd.Flags().StringArrayVarP(&input.inputs, "input", "", []string{}, "action input to make available to actions (e.g. --input myinput=foo)")
|
rootCmd.Flags().StringArrayVarP(&input.inputs, "input", "", []string{}, "action input to make available to actions (e.g. --input myinput=foo)")
|
||||||
rootCmd.Flags().StringArrayVarP(&input.platforms, "platform", "P", []string{}, "custom image to use per platform (e.g. -P ubuntu-18.04=nektos/act-environments-ubuntu:18.04)")
|
rootCmd.Flags().StringArrayVarP(&input.platforms, "platform", "P", []string{}, "custom image to use per platform (e.g. -P ubuntu-18.04=nektos/act-environments-ubuntu:18.04)")
|
||||||
|
@ -77,6 +78,7 @@ func Execute(ctx context.Context, version string) {
|
||||||
rootCmd.PersistentFlags().BoolVarP(&input.noOutput, "quiet", "q", false, "disable logging of output from steps")
|
rootCmd.PersistentFlags().BoolVarP(&input.noOutput, "quiet", "q", false, "disable logging of output from steps")
|
||||||
rootCmd.PersistentFlags().BoolVarP(&input.dryrun, "dryrun", "n", false, "dryrun mode")
|
rootCmd.PersistentFlags().BoolVarP(&input.dryrun, "dryrun", "n", false, "dryrun mode")
|
||||||
rootCmd.PersistentFlags().StringVarP(&input.secretfile, "secret-file", "", ".secrets", "file with list of secrets to read from (e.g. --secret-file .secrets)")
|
rootCmd.PersistentFlags().StringVarP(&input.secretfile, "secret-file", "", ".secrets", "file with list of secrets to read from (e.g. --secret-file .secrets)")
|
||||||
|
rootCmd.PersistentFlags().StringVarP(&input.varfile, "var-file", "", ".vars", "file with list of vars to read from (e.g. --var-file .vars)")
|
||||||
rootCmd.PersistentFlags().BoolVarP(&input.insecureSecrets, "insecure-secrets", "", false, "NOT RECOMMENDED! Doesn't hide secrets while printing logs.")
|
rootCmd.PersistentFlags().BoolVarP(&input.insecureSecrets, "insecure-secrets", "", false, "NOT RECOMMENDED! Doesn't hide secrets while printing logs.")
|
||||||
rootCmd.PersistentFlags().StringVarP(&input.envfile, "env-file", "", ".env", "environment file to read and use as env in the containers")
|
rootCmd.PersistentFlags().StringVarP(&input.envfile, "env-file", "", ".env", "environment file to read and use as env in the containers")
|
||||||
rootCmd.PersistentFlags().StringVarP(&input.inputfile, "input-file", "", ".input", "input file to read and use as action input")
|
rootCmd.PersistentFlags().StringVarP(&input.inputfile, "input-file", "", ".input", "input file to read and use as action input")
|
||||||
|
@ -418,6 +420,10 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
|
||||||
secrets := newSecrets(input.secrets)
|
secrets := newSecrets(input.secrets)
|
||||||
_ = readEnvs(input.Secretfile(), secrets)
|
_ = readEnvs(input.Secretfile(), secrets)
|
||||||
|
|
||||||
|
log.Debugf("Loading vars from %s", input.Varfile())
|
||||||
|
vars := newSecrets(input.vars)
|
||||||
|
_ = readEnvs(input.Varfile(), vars)
|
||||||
|
|
||||||
matrixes := parseMatrix(input.matrix)
|
matrixes := parseMatrix(input.matrix)
|
||||||
log.Debugf("Evaluated matrix inclusions: %v", matrixes)
|
log.Debugf("Evaluated matrix inclusions: %v", matrixes)
|
||||||
|
|
||||||
|
@ -579,6 +585,7 @@ func newRunCommand(ctx context.Context, input *Input) func(*cobra.Command, []str
|
||||||
JSONLogger: input.jsonLogger,
|
JSONLogger: input.jsonLogger,
|
||||||
Env: envs,
|
Env: envs,
|
||||||
Secrets: secrets,
|
Secrets: secrets,
|
||||||
|
Vars: vars,
|
||||||
Inputs: inputs,
|
Inputs: inputs,
|
||||||
Token: secrets["GITHUB_TOKEN"],
|
Token: secrets["GITHUB_TOKEN"],
|
||||||
InsecureSecrets: input.insecureSecrets,
|
InsecureSecrets: input.insecureSecrets,
|
||||||
|
|
|
@ -19,12 +19,11 @@ type EvaluationEnvironment struct {
|
||||||
Steps map[string]*model.StepResult
|
Steps map[string]*model.StepResult
|
||||||
Runner map[string]interface{}
|
Runner map[string]interface{}
|
||||||
Secrets map[string]string
|
Secrets map[string]string
|
||||||
|
Vars map[string]string
|
||||||
Strategy map[string]interface{}
|
Strategy map[string]interface{}
|
||||||
Matrix map[string]interface{}
|
Matrix map[string]interface{}
|
||||||
Needs map[string]Needs
|
Needs map[string]Needs
|
||||||
Inputs map[string]interface{}
|
Inputs map[string]interface{}
|
||||||
|
|
||||||
Vars map[string]string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Needs struct {
|
type Needs struct {
|
||||||
|
@ -150,6 +149,7 @@ func (impl *interperterImpl) evaluateNode(exprNode actionlint.ExprNode) (interfa
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// nolint:gocyclo
|
||||||
func (impl *interperterImpl) evaluateVariable(variableNode *actionlint.VariableNode) (interface{}, error) {
|
func (impl *interperterImpl) evaluateVariable(variableNode *actionlint.VariableNode) (interface{}, error) {
|
||||||
switch strings.ToLower(variableNode.Name) {
|
switch strings.ToLower(variableNode.Name) {
|
||||||
case "github":
|
case "github":
|
||||||
|
@ -171,6 +171,8 @@ func (impl *interperterImpl) evaluateVariable(variableNode *actionlint.VariableN
|
||||||
return impl.env.Runner, nil
|
return impl.env.Runner, nil
|
||||||
case "secrets":
|
case "secrets":
|
||||||
return impl.env.Secrets, nil
|
return impl.env.Secrets, nil
|
||||||
|
case "vars":
|
||||||
|
return impl.env.Vars, nil
|
||||||
case "strategy":
|
case "strategy":
|
||||||
return impl.env.Strategy, nil
|
return impl.env.Strategy, nil
|
||||||
case "matrix":
|
case "matrix":
|
||||||
|
@ -183,8 +185,6 @@ func (impl *interperterImpl) evaluateVariable(variableNode *actionlint.VariableN
|
||||||
return math.Inf(1), nil
|
return math.Inf(1), nil
|
||||||
case "nan":
|
case "nan":
|
||||||
return math.NaN(), nil
|
return math.NaN(), nil
|
||||||
case "vars":
|
|
||||||
return impl.env.Vars, nil
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unavailable context: %s", variableNode.Name)
|
return nil, fmt.Errorf("Unavailable context: %s", variableNode.Name)
|
||||||
}
|
}
|
||||||
|
|
|
@ -557,6 +557,7 @@ func TestContexts(t *testing.T) {
|
||||||
// {"contains(steps.*.outputs.name, 'value')", true, "steps-context-array-outputs"},
|
// {"contains(steps.*.outputs.name, 'value')", true, "steps-context-array-outputs"},
|
||||||
{"runner.os", "Linux", "runner-context"},
|
{"runner.os", "Linux", "runner-context"},
|
||||||
{"secrets.name", "value", "secrets-context"},
|
{"secrets.name", "value", "secrets-context"},
|
||||||
|
{"vars.name", "value", "vars-context"},
|
||||||
{"strategy.fail-fast", true, "strategy-context"},
|
{"strategy.fail-fast", true, "strategy-context"},
|
||||||
{"matrix.os", "Linux", "matrix-context"},
|
{"matrix.os", "Linux", "matrix-context"},
|
||||||
{"needs.job-id.outputs.output-name", "value", "needs-context"},
|
{"needs.job-id.outputs.output-name", "value", "needs-context"},
|
||||||
|
@ -593,6 +594,9 @@ func TestContexts(t *testing.T) {
|
||||||
Secrets: map[string]string{
|
Secrets: map[string]string{
|
||||||
"name": "value",
|
"name": "value",
|
||||||
},
|
},
|
||||||
|
Vars: map[string]string{
|
||||||
|
"name": "value",
|
||||||
|
},
|
||||||
Strategy: map[string]interface{}{
|
Strategy: map[string]interface{}{
|
||||||
"fail-fast": true,
|
"fail-fast": true,
|
||||||
},
|
},
|
||||||
|
|
|
@ -62,8 +62,6 @@ func NewInterpeter(
|
||||||
Matrix: matrix,
|
Matrix: matrix,
|
||||||
Needs: using,
|
Needs: using,
|
||||||
Inputs: nil, // not supported yet
|
Inputs: nil, // not supported yet
|
||||||
|
|
||||||
Vars: nil,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config := exprparser.Config{
|
config := exprparser.Config{
|
||||||
|
|
|
@ -77,12 +77,11 @@ func (rc *RunContext) NewExpressionEvaluatorWithEnv(ctx context.Context, env map
|
||||||
// but required to interpolate/evaluate the step outputs on the job
|
// but required to interpolate/evaluate the step outputs on the job
|
||||||
Steps: rc.getStepsContext(),
|
Steps: rc.getStepsContext(),
|
||||||
Secrets: getWorkflowSecrets(ctx, rc),
|
Secrets: getWorkflowSecrets(ctx, rc),
|
||||||
|
Vars: getWorkflowVars(ctx, rc),
|
||||||
Strategy: strategy,
|
Strategy: strategy,
|
||||||
Matrix: rc.Matrix,
|
Matrix: rc.Matrix,
|
||||||
Needs: using,
|
Needs: using,
|
||||||
Inputs: inputs,
|
Inputs: inputs,
|
||||||
|
|
||||||
Vars: rc.getVarsContext(),
|
|
||||||
}
|
}
|
||||||
if rc.JobContainer != nil {
|
if rc.JobContainer != nil {
|
||||||
ee.Runner = rc.JobContainer.GetRunnerContext(ctx)
|
ee.Runner = rc.JobContainer.GetRunnerContext(ctx)
|
||||||
|
@ -126,14 +125,13 @@ func (rc *RunContext) NewStepExpressionEvaluator(ctx context.Context, step step)
|
||||||
Job: rc.getJobContext(),
|
Job: rc.getJobContext(),
|
||||||
Steps: rc.getStepsContext(),
|
Steps: rc.getStepsContext(),
|
||||||
Secrets: getWorkflowSecrets(ctx, rc),
|
Secrets: getWorkflowSecrets(ctx, rc),
|
||||||
|
Vars: getWorkflowVars(ctx, rc),
|
||||||
Strategy: strategy,
|
Strategy: strategy,
|
||||||
Matrix: rc.Matrix,
|
Matrix: rc.Matrix,
|
||||||
Needs: using,
|
Needs: using,
|
||||||
// todo: should be unavailable
|
// todo: should be unavailable
|
||||||
// but required to interpolate/evaluate the inputs in actions/composite
|
// but required to interpolate/evaluate the inputs in actions/composite
|
||||||
Inputs: inputs,
|
Inputs: inputs,
|
||||||
|
|
||||||
Vars: rc.getVarsContext(),
|
|
||||||
}
|
}
|
||||||
if rc.JobContainer != nil {
|
if rc.JobContainer != nil {
|
||||||
ee.Runner = rc.JobContainer.GetRunnerContext(ctx)
|
ee.Runner = rc.JobContainer.GetRunnerContext(ctx)
|
||||||
|
@ -426,3 +424,7 @@ func getWorkflowSecrets(ctx context.Context, rc *RunContext) map[string]string {
|
||||||
|
|
||||||
return rc.Config.Secrets
|
return rc.Config.Secrets
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getWorkflowVars(ctx context.Context, rc *RunContext) map[string]string {
|
||||||
|
return rc.Config.Vars
|
||||||
|
}
|
||||||
|
|
|
@ -28,6 +28,9 @@ func createRunContext(t *testing.T) *RunContext {
|
||||||
Secrets: map[string]string{
|
Secrets: map[string]string{
|
||||||
"CASE_INSENSITIVE_SECRET": "value",
|
"CASE_INSENSITIVE_SECRET": "value",
|
||||||
},
|
},
|
||||||
|
Vars: map[string]string{
|
||||||
|
"CASE_INSENSITIVE_VAR": "value",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Env: map[string]string{
|
Env: map[string]string{
|
||||||
"key": "value",
|
"key": "value",
|
||||||
|
@ -122,6 +125,8 @@ func TestEvaluateRunContext(t *testing.T) {
|
||||||
{"env.key", "value", ""},
|
{"env.key", "value", ""},
|
||||||
{"secrets.CASE_INSENSITIVE_SECRET", "value", ""},
|
{"secrets.CASE_INSENSITIVE_SECRET", "value", ""},
|
||||||
{"secrets.case_insensitive_secret", "value", ""},
|
{"secrets.case_insensitive_secret", "value", ""},
|
||||||
|
{"vars.CASE_INSENSITIVE_VAR", "value", ""},
|
||||||
|
{"vars.case_insensitive_var", "value", ""},
|
||||||
{"format('{{0}}', 'test')", "{0}", ""},
|
{"format('{{0}}', 'test')", "{0}", ""},
|
||||||
{"format('{{{0}}}', 'test')", "{test}", ""},
|
{"format('{{{0}}}', 'test')", "{test}", ""},
|
||||||
{"format('}}')", "}", ""},
|
{"format('}}')", "}", ""},
|
||||||
|
@ -195,6 +200,9 @@ func TestInterpolate(t *testing.T) {
|
||||||
Secrets: map[string]string{
|
Secrets: map[string]string{
|
||||||
"CASE_INSENSITIVE_SECRET": "value",
|
"CASE_INSENSITIVE_SECRET": "value",
|
||||||
},
|
},
|
||||||
|
Vars: map[string]string{
|
||||||
|
"CASE_INSENSITIVE_VAR": "value",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Env: map[string]string{
|
Env: map[string]string{
|
||||||
"KEYWITHNOTHING": "valuewithnothing",
|
"KEYWITHNOTHING": "valuewithnothing",
|
||||||
|
@ -229,6 +237,8 @@ func TestInterpolate(t *testing.T) {
|
||||||
{" ${{ env.KEY_WITH_UNDERSCORES }} ", " value_with_underscores "},
|
{" ${{ env.KEY_WITH_UNDERSCORES }} ", " value_with_underscores "},
|
||||||
{"${{ secrets.CASE_INSENSITIVE_SECRET }}", "value"},
|
{"${{ secrets.CASE_INSENSITIVE_SECRET }}", "value"},
|
||||||
{"${{ secrets.case_insensitive_secret }}", "value"},
|
{"${{ secrets.case_insensitive_secret }}", "value"},
|
||||||
|
{"${{ vars.CASE_INSENSITIVE_VAR }}", "value"},
|
||||||
|
{"${{ vars.case_insensitive_var }}", "value"},
|
||||||
{"${{ env.UNKNOWN }}", ""},
|
{"${{ env.UNKNOWN }}", ""},
|
||||||
{"${{ env.SOMETHING_TRUE }}", "true"},
|
{"${{ env.SOMETHING_TRUE }}", "true"},
|
||||||
{"${{ env.SOMETHING_FALSE }}", "false"},
|
{"${{ env.SOMETHING_FALSE }}", "false"},
|
||||||
|
|
|
@ -739,10 +739,6 @@ func (rc *RunContext) getStepsContext() map[string]*model.StepResult {
|
||||||
return rc.StepResults
|
return rc.StepResults
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rc *RunContext) getVarsContext() map[string]string {
|
|
||||||
return rc.Config.Vars
|
|
||||||
}
|
|
||||||
|
|
||||||
func (rc *RunContext) getGithubContext(ctx context.Context) *model.GithubContext {
|
func (rc *RunContext) getGithubContext(ctx context.Context) *model.GithubContext {
|
||||||
logger := common.Logger(ctx)
|
logger := common.Logger(ctx)
|
||||||
ghc := &model.GithubContext{
|
ghc := &model.GithubContext{
|
||||||
|
|
|
@ -36,6 +36,7 @@ type Config struct {
|
||||||
Env map[string]string // env for containers
|
Env map[string]string // env for containers
|
||||||
Inputs map[string]string // manually passed action inputs
|
Inputs map[string]string // manually passed action inputs
|
||||||
Secrets map[string]string // list of secrets
|
Secrets map[string]string // list of secrets
|
||||||
|
Vars map[string]string // list of vars
|
||||||
Token string // GitHub token
|
Token string // GitHub token
|
||||||
InsecureSecrets bool // switch hiding output when printing to terminal
|
InsecureSecrets bool // switch hiding output when printing to terminal
|
||||||
Platforms map[string]string // list of platforms
|
Platforms map[string]string // list of platforms
|
||||||
|
@ -67,7 +68,6 @@ type Config struct {
|
||||||
DefaultActionsURLs []string // urls from gitea's `DEFAULT_ACTIONS_URL` config
|
DefaultActionsURLs []string // urls from gitea's `DEFAULT_ACTIONS_URL` config
|
||||||
PlatformPicker func(labels []string) string // platform picker, it will take precedence over Platforms if isn't nil
|
PlatformPicker func(labels []string) string // platform picker, it will take precedence over Platforms if isn't nil
|
||||||
JobLoggerLevel *log.Level // the level of job logger
|
JobLoggerLevel *log.Level // the level of job logger
|
||||||
Vars map[string]string // the list of variables set at the repository, environment, or organization levels.
|
|
||||||
ValidVolumes []string // only volumes (and bind mounts) in this slice can be mounted on the job container or service containers
|
ValidVolumes []string // only volumes (and bind mounts) in this slice can be mounted on the job container or service containers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue