diff --git a/pkg/model/workflow.go b/pkg/model/workflow.go index 86ec67f..af71231 100644 --- a/pkg/model/workflow.go +++ b/pkg/model/workflow.go @@ -215,7 +215,8 @@ func (j *Job) Matrix() map[string][]interface{} { // GetMatrixes returns the matrix cross product // It skips includes and hard fails excludes for non-existing keys -// nolint:gocyclo +// +//nolint:gocyclo func (j *Job) GetMatrixes() []map[string]interface{} { matrixes := make([]map[string]interface{}, 0) if j.Strategy != nil { @@ -376,8 +377,16 @@ func (s *Step) String() string { } // Environments returns string-based key=value map for a step +// Note: all keys are uppercase func (s *Step) Environment() map[string]string { - return environment(s.Env) + env := environment(s.Env) + + for k, v := range env { + delete(env, k) + env[strings.ToUpper(k)] = v + } + + return env } // GetEnv gets the env for a step @@ -436,6 +445,22 @@ const ( StepTypeInvalid ) +func (s StepType) String() string { + switch s { + case StepTypeInvalid: + return "invalid" + case StepTypeRun: + return "run" + case StepTypeUsesActionLocal: + return "local-action" + case StepTypeUsesActionRemote: + return "remote-action" + case StepTypeUsesDockerURL: + return "docker" + } + return "unknown" +} + // Type returns the type of the step func (s *Step) Type() StepType { if s.Run == "" && s.Uses == "" { diff --git a/pkg/runner/action.go b/pkg/runner/action.go index 97674c8..2dee988 100644 --- a/pkg/runner/action.go +++ b/pkg/runner/action.go @@ -136,26 +136,10 @@ func runActionImpl(step actionStep, actionDir string, remoteAction *remoteAction action := step.getActionModel() logger.Debugf("About to run action %v", action) - if remoteAction != nil { - rc.ActionRepository = fmt.Sprintf("%s/%s", remoteAction.Org, remoteAction.Repo) - rc.ActionRef = remoteAction.Ref - } else { - rc.ActionRepository = "" - rc.ActionRef = "" + err := setupActionEnv(ctx, step, remoteAction) + if err != nil { + return err } - defer (func() { - // cleanup after the action is done, to avoid side-effects in - // the next step/action - rc.ActionRepository = "" - rc.ActionRef = "" - })() - - // we need to merge with github-env again, since at the step setup - // time, we don't have all environment prepared - mergeIntoMap(step.getEnv(), rc.withGithubEnv(ctx, map[string]string{})) - - populateEnvsFromSavedState(step.getEnv(), step, rc) - populateEnvsFromInput(ctx, step.getEnv(), action, rc) actionLocation := path.Join(actionDir, actionPath) actionName, containerActionDir := getContainerActionPaths(stepModel, actionLocation, rc) @@ -169,6 +153,7 @@ func runActionImpl(step actionStep, actionDir string, remoteAction *remoteAction } containerArgs := []string{"node", path.Join(containerActionDir, action.Runs.Main)} logger.Debugf("executing remote job container: %s", containerArgs) + return rc.execJobContainer(containerArgs, *step.getEnv(), "", "")(ctx) case model.ActionRunsUsingDocker: location := actionLocation @@ -193,6 +178,20 @@ func runActionImpl(step actionStep, actionDir string, remoteAction *remoteAction } } +func setupActionEnv(ctx context.Context, step actionStep, remoteAction *remoteAction) error { + rc := step.getRunContext() + + // A few fields in the environment (e.g. GITHUB_ACTION_REPOSITORY) + // are dependent on the action. That means we can complete the + // setup only after resolving the whole action model and cloning + // the action + rc.withGithubEnv(ctx, step.getGithubContext(ctx), *step.getEnv()) + populateEnvsFromSavedState(step.getEnv(), step, rc) + populateEnvsFromInput(ctx, step.getEnv(), step.getActionModel(), rc) + + return nil +} + // https://github.com/nektos/act/issues/228#issuecomment-629709055 // files in .gitignore are not copied in a Docker container // this causes issues with actions that ignore other important resources @@ -211,7 +210,8 @@ func removeGitIgnore(ctx context.Context, directory string) error { } // TODO: break out parts of function to reduce complexicity -// nolint:gocyclo +// +//nolint:gocyclo func execAsDocker(ctx context.Context, step actionStep, actionName string, basedir string, localAction bool) error { logger := common.Logger(ctx) rc := step.getRunContext() @@ -299,11 +299,8 @@ func execAsDocker(ctx context.Context, step actionStep, actionName string, based func evalDockerArgs(ctx context.Context, step step, action *model.Action, cmd *[]string) { rc := step.getRunContext() stepModel := step.getStepModel() - oldInputs := rc.Inputs - defer func() { - rc.Inputs = oldInputs - }() - inputs := make(map[string]interface{}) + + inputs := make(map[string]string) eval := rc.NewExpressionEvaluator(ctx) // Set Defaults for k, input := range action.Inputs { @@ -314,7 +311,8 @@ func evalDockerArgs(ctx context.Context, step step, action *model.Action, cmd *[ inputs[k] = eval.Interpolate(ctx, v) } } - rc.Inputs = inputs + mergeIntoMap(step.getEnv(), inputs) + stepEE := rc.NewStepExpressionEvaluator(ctx, step) for i, v := range *cmd { (*cmd)[i] = stepEE.Interpolate(ctx, v) @@ -372,29 +370,6 @@ func newStepContainer(ctx context.Context, step step, image string, cmd []string return stepContainer } -func (rc *RunContext) setupActionInputs(ctx context.Context, step actionStep) { - if step.getActionModel() == nil { - // e.g. local checkout skip has no action model - return - } - - stepModel := step.getStepModel() - action := step.getActionModel() - - eval := rc.NewExpressionEvaluator(ctx) - inputs := make(map[string]interface{}) - for k, input := range action.Inputs { - inputs[k] = eval.Interpolate(ctx, input.Default) - } - if stepModel.With != nil { - for k, v := range stepModel.With { - inputs[k] = eval.Interpolate(ctx, v) - } - } - - rc.Inputs = inputs -} - func populateEnvsFromSavedState(env *map[string]string, step actionStep, rc *RunContext) { stepResult := rc.StepResults[step.getStepModel().ID] if stepResult != nil { @@ -513,7 +488,10 @@ func runPreStep(step actionStep) common.Executor { return rc.execJobContainer(containerArgs, *step.getEnv(), "", "")(ctx) case model.ActionRunsUsingComposite: - step.getCompositeRunContext(ctx).updateCompositeRunContext(ctx, step.getRunContext(), step) + if step.getCompositeSteps() == nil { + step.getCompositeRunContext(ctx) + } + return step.getCompositeSteps().pre(ctx) default: @@ -601,7 +579,6 @@ func runPostStep(step actionStep) common.Executor { return err } - step.getCompositeRunContext(ctx).updateCompositeRunContext(ctx, step.getRunContext(), step) return step.getCompositeSteps().post(ctx) default: diff --git a/pkg/runner/action_composite.go b/pkg/runner/action_composite.go index 5dbfde6..256d36e 100644 --- a/pkg/runner/action_composite.go +++ b/pkg/runner/action_composite.go @@ -3,37 +3,43 @@ package runner import ( "context" "fmt" + "regexp" + "strings" "github.com/nektos/act/pkg/common" "github.com/nektos/act/pkg/model" ) -func evaluteCompositeInputAndEnv(ctx context.Context, parent *RunContext, step actionStep) (inputs map[string]interface{}, env map[string]string) { - eval := parent.NewExpressionEvaluator(ctx) - - inputs = make(map[string]interface{}) - for k, input := range step.getActionModel().Inputs { - inputs[k] = eval.Interpolate(ctx, input.Default) - } - if step.getStepModel().With != nil { - for k, v := range step.getStepModel().With { - inputs[k] = eval.Interpolate(ctx, v) +func evaluateCompositeInputAndEnv(ctx context.Context, parent *RunContext, step actionStep) map[string]string { + env := make(map[string]string) + stepEnv := *step.getEnv() + for k, v := range stepEnv { + // do not set current inputs into composite action + // the required inputs are added in the second loop + if !strings.HasPrefix(k, "INPUT_") { + env[k] = v } } - env = make(map[string]string) - for k, v := range parent.Env { - env[k] = eval.Interpolate(ctx, v) - } - for k, v := range step.getStepModel().Environment() { - env[k] = eval.Interpolate(ctx, v) + for inputID, input := range step.getActionModel().Inputs { + envKey := regexp.MustCompile("[^A-Z0-9-]").ReplaceAllString(strings.ToUpper(inputID), "_") + envKey = fmt.Sprintf("INPUT_%s", strings.ToUpper(envKey)) + + // lookup if key is defined in the step but the the already + // evaluated value from the environment + _, defined := step.getStepModel().With[inputID] + if value, ok := stepEnv[envKey]; defined && ok { + env[envKey] = value + } else { + env[envKey] = input.Default + } } - return inputs, env + return env } func newCompositeRunContext(ctx context.Context, parent *RunContext, step actionStep, actionPath string) *RunContext { - inputs, env := evaluteCompositeInputAndEnv(ctx, parent, step) + env := evaluateCompositeInputAndEnv(ctx, parent, step) // run with the global config but without secrets configCopy := *(parent.Config) @@ -52,57 +58,42 @@ func newCompositeRunContext(ctx context.Context, parent *RunContext, step action }, }, }, - Config: &configCopy, - StepResults: map[string]*model.StepResult{}, - JobContainer: parent.JobContainer, - Inputs: inputs, - ActionPath: actionPath, - ActionRepository: parent.ActionRepository, - ActionRef: parent.ActionRef, - Env: env, - Masks: parent.Masks, - ExtraPath: parent.ExtraPath, - Parent: parent, + Config: &configCopy, + StepResults: map[string]*model.StepResult{}, + JobContainer: parent.JobContainer, + ActionPath: actionPath, + Env: env, + Masks: parent.Masks, + ExtraPath: parent.ExtraPath, + Parent: parent, } return compositerc } -// This updates a composite context inputs, env and masks. -// This is needed to re-evalute/update that context between pre/main/post steps. -// Some of the inputs/env may requires the results of in-between steps. -func (rc *RunContext) updateCompositeRunContext(ctx context.Context, parent *RunContext, step actionStep) { - inputs, env := evaluteCompositeInputAndEnv(ctx, parent, step) - - rc.Inputs = inputs - rc.Env = env - rc.Masks = append(rc.Masks, parent.Masks...) -} - func execAsComposite(step actionStep) common.Executor { rc := step.getRunContext() action := step.getActionModel() return func(ctx context.Context) error { - compositerc := step.getCompositeRunContext(ctx) + compositeRC := step.getCompositeRunContext(ctx) steps := step.getCompositeSteps() - ctx = WithCompositeLogger(ctx, &compositerc.Masks) + ctx = WithCompositeLogger(ctx, &compositeRC.Masks) - compositerc.updateCompositeRunContext(ctx, rc, step) err := steps.main(ctx) // Map outputs from composite RunContext to job RunContext - eval := compositerc.NewExpressionEvaluator(ctx) + eval := compositeRC.NewExpressionEvaluator(ctx) for outputName, output := range action.Outputs { rc.setOutput(ctx, map[string]string{ "name": outputName, }, eval.Interpolate(ctx, output.Value)) } - rc.Masks = append(rc.Masks, compositerc.Masks...) - rc.ExtraPath = compositerc.ExtraPath + rc.Masks = append(rc.Masks, compositeRC.Masks...) + rc.ExtraPath = compositeRC.ExtraPath return err } diff --git a/pkg/runner/action_test.go b/pkg/runner/action_test.go index 733daa9..0b23085 100644 --- a/pkg/runner/action_test.go +++ b/pkg/runner/action_test.go @@ -187,10 +187,8 @@ func TestActionRunner(t *testing.T) { Uses: "org/repo/path@ref", }, RunContext: &RunContext{ - ActionRepository: "org/repo", - ActionPath: "path", - ActionRef: "ref", - Config: &Config{}, + ActionPath: "path", + Config: &Config{}, Run: &model.Run{ JobID: "job", Workflow: &model.Workflow{ diff --git a/pkg/runner/expression.go b/pkg/runner/expression.go index d803446..a0f0c9b 100644 --- a/pkg/runner/expression.go +++ b/pkg/runner/expression.go @@ -39,6 +39,13 @@ func (rc *RunContext) NewExpressionEvaluator(ctx context.Context) ExpressionEval } } + inputs := make(map[string]interface{}) + for k, v := range rc.GetEnv() { + if strings.HasPrefix(k, "INPUT_") { + inputs[strings.ToLower(strings.TrimPrefix(k, "INPUT_"))] = v + } + } + ee := &exprparser.EvaluationEnvironment{ Github: rc.getGithubContext(ctx), Env: rc.GetEnv(), @@ -56,7 +63,7 @@ func (rc *RunContext) NewExpressionEvaluator(ctx context.Context) ExpressionEval Strategy: strategy, Matrix: rc.Matrix, Needs: using, - Inputs: rc.Inputs, + Inputs: inputs, } return expressionEvaluator{ interpreter: exprparser.NewInterpeter(ee, exprparser.Config{ @@ -87,8 +94,15 @@ func (rc *RunContext) NewStepExpressionEvaluator(ctx context.Context, step step) } } + inputs := make(map[string]interface{}) + for k, v := range *step.getEnv() { + if strings.HasPrefix(k, "INPUT_") { + inputs[strings.ToLower(strings.TrimPrefix(k, "INPUT_"))] = v + } + } + ee := &exprparser.EvaluationEnvironment{ - Github: rc.getGithubContext(ctx), + Github: step.getGithubContext(ctx), Env: *step.getEnv(), Job: rc.getJobContext(), Steps: rc.getStepsContext(), @@ -104,7 +118,7 @@ func (rc *RunContext) NewStepExpressionEvaluator(ctx context.Context, step step) Needs: using, // todo: should be unavailable // but required to interpolate/evaluate the inputs in actions/composite - Inputs: rc.Inputs, + Inputs: inputs, } return expressionEvaluator{ interpreter: exprparser.NewInterpeter(ee, exprparser.Config{ diff --git a/pkg/runner/run_context.go b/pkg/runner/run_context.go index 8c2de75..facdef0 100644 --- a/pkg/runner/run_context.go +++ b/pkg/runner/run_context.go @@ -27,25 +27,22 @@ const ActPath string = "/var/run/act" // RunContext contains info about current job type RunContext struct { - Name string - Config *Config - Matrix map[string]interface{} - Run *model.Run - EventJSON string - Env map[string]string - ExtraPath []string - CurrentStep string - StepResults map[string]*model.StepResult - ExprEval ExpressionEvaluator - JobContainer container.Container - OutputMappings map[MappableOutput]MappableOutput - JobName string - ActionPath string - ActionRef string - ActionRepository string - Inputs map[string]interface{} - Parent *RunContext - Masks []string + Name string + Config *Config + Matrix map[string]interface{} + Run *model.Run + EventJSON string + Env map[string]string + ExtraPath []string + CurrentStep string + StepResults map[string]*model.StepResult + ExprEval ExpressionEvaluator + JobContainer container.Container + OutputMappings map[MappableOutput]MappableOutput + JobName string + ActionPath string + Parent *RunContext + Masks []string } func (rc *RunContext) AddMask(mask string) { @@ -438,8 +435,6 @@ func (rc *RunContext) getGithubContext(ctx context.Context) *model.GithubContext Action: rc.CurrentStep, Token: rc.Config.Token, ActionPath: rc.ActionPath, - ActionRef: rc.ActionRef, - ActionRepository: rc.ActionRepository, RepositoryOwner: rc.Config.Env["GITHUB_REPOSITORY_OWNER"], RetentionDays: rc.Config.Env["GITHUB_RETENTION_DAYS"], RunnerPerflog: rc.Config.Env["RUNNER_PERFLOG"], @@ -557,8 +552,7 @@ func nestedMapLookup(m map[string]interface{}, ks ...string) (rval interface{}) } } -func (rc *RunContext) withGithubEnv(ctx context.Context, env map[string]string) map[string]string { - github := rc.getGithubContext(ctx) +func (rc *RunContext) withGithubEnv(ctx context.Context, github *model.GithubContext, env map[string]string) map[string]string { env["CI"] = "true" env["GITHUB_ENV"] = ActPath + "/workflow/envs.txt" env["GITHUB_PATH"] = ActPath + "/workflow/paths.txt" diff --git a/pkg/runner/step.go b/pkg/runner/step.go index 5b37ce3..8682d58 100644 --- a/pkg/runner/step.go +++ b/pkg/runner/step.go @@ -16,6 +16,7 @@ type step interface { post() common.Executor getRunContext() *RunContext + getGithubContext(ctx context.Context) *model.GithubContext getStepModel() *model.Step getEnv() *map[string]string getIfExpression(context context.Context, stage stepStage) string @@ -136,9 +137,10 @@ func setupEnv(ctx context.Context, step step) error { if err != nil { return err } - mergeIntoMap(step.getEnv(), step.getStepModel().GetEnv()) // step env should not be overwritten + // merge step env last, since it should not be overwritten + mergeIntoMap(step.getEnv(), step.getStepModel().GetEnv()) - exprEval := rc.NewStepExpressionEvaluator(ctx, step) + exprEval := rc.NewExpressionEvaluator(ctx) for k, v := range *step.getEnv() { (*step.getEnv())[k] = exprEval.Interpolate(ctx, v) } @@ -169,7 +171,7 @@ func mergeEnv(ctx context.Context, step step) { (*env)["PATH"] += `:` + p } - mergeIntoMap(env, rc.withGithubEnv(ctx, *env)) + rc.withGithubEnv(ctx, step.getGithubContext(ctx), *env) } func isStepEnabled(ctx context.Context, expr string, step step, stage stepStage) (bool, error) { diff --git a/pkg/runner/step_action_local.go b/pkg/runner/step_action_local.go index df73979..6b4fc06 100644 --- a/pkg/runner/step_action_local.go +++ b/pkg/runner/step_action_local.go @@ -4,7 +4,6 @@ import ( "archive/tar" "context" "io" - "io/ioutil" "os" "path" "path/filepath" @@ -55,7 +54,7 @@ func (sal *stepActionLocal) main() common.Executor { } } - actionModel, err := sal.readAction(ctx, sal.Step, actionDir, "", localReader(ctx), ioutil.WriteFile) + actionModel, err := sal.readAction(ctx, sal.Step, actionDir, "", localReader(ctx), os.WriteFile) if err != nil { return err } @@ -74,6 +73,10 @@ func (sal *stepActionLocal) getRunContext() *RunContext { return sal.RunContext } +func (sal *stepActionLocal) getGithubContext(ctx context.Context) *model.GithubContext { + return sal.getRunContext().getGithubContext(ctx) +} + func (sal *stepActionLocal) getStepModel() *model.Step { return sal.Step } diff --git a/pkg/runner/step_action_remote.go b/pkg/runner/step_action_remote.go index b0f23c1..6616335 100644 --- a/pkg/runner/step_action_remote.go +++ b/pkg/runner/step_action_remote.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "io" - "io/ioutil" "os" "path" "path/filepath" @@ -49,7 +48,7 @@ func (sar *stepActionRemote) prepareActionExecutor() common.Executor { sar.remoteAction.URL = sar.RunContext.Config.GitHubInstance - github := sar.RunContext.getGithubContext(ctx) + github := sar.getGithubContext(ctx) if sar.remoteAction.IsCheckout() && isLocalCheckout(github, sar.Step) && !sar.RunContext.Config.NoSkipCheckout { common.Logger(ctx).Debugf("Skipping local actions/checkout because workdir was already copied") return nil @@ -92,14 +91,10 @@ func (sar *stepActionRemote) prepareActionExecutor() common.Executor { return common.NewPipelineExecutor( ntErr, func(ctx context.Context) error { - actionModel, err := sar.readAction(ctx, sar.Step, actionDir, sar.remoteAction.Path, remoteReader(ctx), ioutil.WriteFile) + actionModel, err := sar.readAction(ctx, sar.Step, actionDir, sar.remoteAction.Path, remoteReader(ctx), os.WriteFile) sar.action = actionModel return err }, - func(ctx context.Context) error { - sar.RunContext.setupActionInputs(ctx, sar) - return nil - }, )(ctx) } } @@ -116,7 +111,7 @@ func (sar *stepActionRemote) main() common.Executor { return common.NewPipelineExecutor( sar.prepareActionExecutor(), runStepExecutor(sar, stepStageMain, func(ctx context.Context) error { - github := sar.RunContext.getGithubContext(ctx) + github := sar.getGithubContext(ctx) if sar.remoteAction.IsCheckout() && isLocalCheckout(github, sar.Step) && !sar.RunContext.Config.NoSkipCheckout { if sar.RunContext.Config.BindWorkdir { common.Logger(ctx).Debugf("Skipping local actions/checkout because you bound your workspace") @@ -129,9 +124,7 @@ func (sar *stepActionRemote) main() common.Executor { actionDir := fmt.Sprintf("%s/%s", sar.RunContext.ActionCacheDir(), strings.ReplaceAll(sar.Step.Uses, "/", "-")) - return common.NewPipelineExecutor( - sar.runAction(sar, actionDir, sar.remoteAction), - )(ctx) + return sar.runAction(sar, actionDir, sar.remoteAction)(ctx) }), ) } @@ -144,6 +137,19 @@ func (sar *stepActionRemote) getRunContext() *RunContext { return sar.RunContext } +func (sar *stepActionRemote) getGithubContext(ctx context.Context) *model.GithubContext { + ghc := sar.getRunContext().getGithubContext(ctx) + + // extend github context if we already have an initialized remoteAction + remoteAction := sar.remoteAction + if remoteAction != nil { + ghc.ActionRepository = fmt.Sprintf("%s/%s", remoteAction.Org, remoteAction.Repo) + ghc.ActionRef = remoteAction.Ref + } + + return ghc +} + func (sar *stepActionRemote) getStepModel() *model.Step { return sar.Step } @@ -155,7 +161,7 @@ func (sar *stepActionRemote) getEnv() *map[string]string { func (sar *stepActionRemote) getIfExpression(ctx context.Context, stage stepStage) string { switch stage { case stepStagePre: - github := sar.RunContext.getGithubContext(ctx) + github := sar.getGithubContext(ctx) if sar.remoteAction.IsCheckout() && isLocalCheckout(github, sar.Step) && !sar.RunContext.Config.NoSkipCheckout { // skip local checkout pre step return "false" diff --git a/pkg/runner/step_docker.go b/pkg/runner/step_docker.go index 6d625ee..4ac3b27 100644 --- a/pkg/runner/step_docker.go +++ b/pkg/runner/step_docker.go @@ -39,6 +39,10 @@ func (sd *stepDocker) getRunContext() *RunContext { return sd.RunContext } +func (sd *stepDocker) getGithubContext(ctx context.Context) *model.GithubContext { + return sd.getRunContext().getGithubContext(ctx) +} + func (sd *stepDocker) getStepModel() *model.Step { return sd.Step } diff --git a/pkg/runner/step_run.go b/pkg/runner/step_run.go index 87c9516..85dfed6 100644 --- a/pkg/runner/step_run.go +++ b/pkg/runner/step_run.go @@ -45,6 +45,10 @@ func (sr *stepRun) getRunContext() *RunContext { return sr.RunContext } +func (sr *stepRun) getGithubContext(ctx context.Context) *model.GithubContext { + return sr.getRunContext().getGithubContext(ctx) +} + func (sr *stepRun) getStepModel() *model.Step { return sr.Step } diff --git a/pkg/runner/step_test.go b/pkg/runner/step_test.go index 621f873..b72f997 100644 --- a/pkg/runner/step_test.go +++ b/pkg/runner/step_test.go @@ -94,6 +94,11 @@ func (sm *stepMock) getRunContext() *RunContext { return args.Get(0).(*RunContext) } +func (sm *stepMock) getGithubContext(ctx context.Context) *model.GithubContext { + args := sm.Called() + return args.Get(0).(*RunContext).getGithubContext(ctx) +} + func (sm *stepMock) getStepModel() *model.Step { args := sm.Called() return args.Get(0).(*model.Step) @@ -142,6 +147,7 @@ func TestSetupEnv(t *testing.T) { } sm.On("getRunContext").Return(rc) + sm.On("getGithubContext").Return(rc) sm.On("getStepModel").Return(step) sm.On("getEnv").Return(&env) diff --git a/pkg/runner/testdata/uses-composite-with-inputs/action/action.yml b/pkg/runner/testdata/uses-composite-with-inputs/action/action.yml new file mode 100644 index 0000000..0e35475 --- /dev/null +++ b/pkg/runner/testdata/uses-composite-with-inputs/action/action.yml @@ -0,0 +1,19 @@ +name: "action" +description: "action" + +inputs: + some: + description: "some input" + required: true +outputs: + out: + description: "some output" + value: "output value" + +runs: + using: "composite" + steps: + - run: | + echo "action input=${{ inputs.some }}" + [[ "${{ inputs.some == 'value' }}" = "true" ]] || exit 1 + shell: bash diff --git a/pkg/runner/testdata/uses-composite-with-inputs/composite/action.yml b/pkg/runner/testdata/uses-composite-with-inputs/composite/action.yml new file mode 100644 index 0000000..4ca6f6d --- /dev/null +++ b/pkg/runner/testdata/uses-composite-with-inputs/composite/action.yml @@ -0,0 +1,22 @@ +name: "composite" +description: "composite" + +inputs: + composite-input: + description: "value" + required: true + +runs: + using: "composite" + steps: + - name: test input value + run: | + echo "input value 1=${{ inputs.composite-input }}" + [[ "${{ inputs.composite-input == 'value' }}" = "true" ]] || exit 1 + shell: bash + - uses: nektos/act-test-actions/js@main + - name: test input value again + run: | + echo "input value 2=${{ inputs.composite-input }}" + [[ "${{ inputs.composite-input == 'value' }}" = "true" ]] || exit 1 + shell: bash diff --git a/pkg/runner/testdata/uses-composite-with-inputs/push.yml b/pkg/runner/testdata/uses-composite-with-inputs/push.yml new file mode 100644 index 0000000..229969b --- /dev/null +++ b/pkg/runner/testdata/uses-composite-with-inputs/push.yml @@ -0,0 +1,30 @@ +name: push +on: push +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: use simple composite action + uses: ./uses-composite-with-inputs/action + with: + some: value + - name: use nested composite action + uses: ./uses-composite-with-inputs/composite + with: + composite-input: value + ### + # + # Remote composite test + # + - name: use remote composite action + id: remote-composite + uses: nektos/act-test-actions/composite@main + with: + input: value + - name: test remote composite output + run: | + echo "steps.remote-composite.outputs.output=${{ steps.remote-composite.outputs.output }}" + [[ "${{ steps.remote-composite.outputs.output == 'value' }}" = "true" ]] || exit 1 + # + ### diff --git a/pkg/runner/testdata/uses-composite/composite_action/action.yml b/pkg/runner/testdata/uses-composite/composite_action/action.yml index e7b878f..e79736c 100644 --- a/pkg/runner/testdata/uses-composite/composite_action/action.yml +++ b/pkg/runner/testdata/uses-composite/composite_action/action.yml @@ -35,7 +35,8 @@ outputs: runs: using: "composite" steps: - - run: | + - name: echo inputs + run: | echo "#####################################" echo "Inputs:" echo "---" diff --git a/pkg/runner/testdata/uses-nested-composite/composite_action2/action.yml b/pkg/runner/testdata/uses-nested-composite/composite_action2/action.yml index 1062ebd..2fae40c 100644 --- a/pkg/runner/testdata/uses-nested-composite/composite_action2/action.yml +++ b/pkg/runner/testdata/uses-nested-composite/composite_action2/action.yml @@ -46,7 +46,8 @@ runs: [[ "${{steps.composite.outputs.secret_output == format('{0}/{0}', inputs.test_input_optional)}}" = "true" ]] || exit 1 shell: bash # Now test again with default values - - uses: ./uses-composite/composite_action + - name: ./uses-composite/composite_action with defaults + uses: ./uses-composite/composite_action id: composite2 with: test_input_required: 'test_input_required_value' @@ -60,4 +61,4 @@ runs: - run: | echo "steps.composite.outputs.secret_output=$COMPOSITE_ACTION_ENV_OUTPUT" [[ "${{env.COMPOSITE_ACTION_ENV_OUTPUT == 'my test value' }}" = "true" ]] || exit 1 - shell: bash \ No newline at end of file + shell: bash