diff options
author | Markus Wolf <KnisterPeter@users.noreply.github.com> | 2022-10-17 18:25:26 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-17 18:25:26 +0200 |
commit | 1e0ef8ce693c31f1ff0b8e0f81f9bc56373ba3d3 (patch) | |
tree | f23f5d3c38be717f22bb5c6c0367e4ea09ec917f | |
parent | fix: ci is failing since 2022-10-17 (#1397) (diff) | |
download | forgejo-act-1e0ef8ce693c31f1ff0b8e0f81f9bc56373ba3d3.tar.xz forgejo-act-1e0ef8ce693c31f1ff0b8e0f81f9bc56373ba3d3.zip |
Mapping `workflow_dispatch` inputs into the Expression `inputs` context (#1363)
* test: check workflow_dispatch inputs
This implements a test to check for `workflow_dispatch` inputs.
This will be a prerequisite for implementing the inputs.
* feat: map workflow_dispatch input to expression evaluator
This changes adds the workflow_dispatch event inputs
to the `inputs` context and maintaining the boolean type
* fix: coerce boolean input types
* fix: use step env if available, rc env otherwise
-rw-r--r-- | pkg/model/workflow.go | 45 | ||||
-rw-r--r-- | pkg/runner/expression.go | 53 | ||||
-rw-r--r-- | pkg/runner/runner_test.go | 10 | ||||
-rw-r--r-- | pkg/runner/testdata/workflow_dispatch/event.json | 6 | ||||
-rw-r--r-- | pkg/runner/testdata/workflow_dispatch/workflow_dispatch.yml | 36 |
5 files changed, 136 insertions, 14 deletions
diff --git a/pkg/model/workflow.go b/pkg/model/workflow.go index af71231..214927e 100644 --- a/pkg/model/workflow.go +++ b/pkg/model/workflow.go @@ -55,6 +55,51 @@ func (w *Workflow) On() []string { return nil } +func (w *Workflow) OnEvent(event string) interface{} { + if w.RawOn.Kind == yaml.MappingNode { + var val map[string]interface{} + err := w.RawOn.Decode(&val) + if err != nil { + log.Fatal(err) + } + return val[event] + } + return nil +} + +type WorkflowDispatchInput struct { + Description string `yaml:"description"` + Required bool `yaml:"required"` + Default string `yaml:"default"` + Type string `yaml:"type"` + Options []string `yaml:"options"` +} + +type WorkflowDispatch struct { + Inputs map[string]WorkflowDispatchInput `yaml:"inputs"` +} + +func (w *Workflow) WorkflowDispatchConfig() *WorkflowDispatch { + if w.RawOn.Kind != yaml.MappingNode { + return nil + } + + var val map[string]yaml.Node + err := w.RawOn.Decode(&val) + if err != nil { + log.Fatal(err) + } + + var config WorkflowDispatch + node := val["workflow_dispatch"] + err = node.Decode(&config) + if err != nil { + log.Fatal(err) + } + + return &config +} + // Job is the structure of one job in a workflow type Job struct { Name string `yaml:"name"` diff --git a/pkg/runner/expression.go b/pkg/runner/expression.go index a0f0c9b..adba569 100644 --- a/pkg/runner/expression.go +++ b/pkg/runner/expression.go @@ -9,6 +9,7 @@ import ( "github.com/nektos/act/pkg/common" "github.com/nektos/act/pkg/container" "github.com/nektos/act/pkg/exprparser" + "github.com/nektos/act/pkg/model" "gopkg.in/yaml.v3" ) @@ -39,15 +40,11 @@ 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 - } - } + ghc := rc.getGithubContext(ctx) + inputs := getEvaluatorInputs(ctx, rc, nil, ghc) ee := &exprparser.EvaluationEnvironment{ - Github: rc.getGithubContext(ctx), + Github: ghc, Env: rc.GetEnv(), Job: rc.getJobContext(), // todo: should be unavailable @@ -94,12 +91,8 @@ 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 - } - } + ghc := rc.getGithubContext(ctx) + inputs := getEvaluatorInputs(ctx, rc, step, ghc) ee := &exprparser.EvaluationEnvironment{ Github: step.getGithubContext(ctx), @@ -319,3 +312,37 @@ func rewriteSubExpression(ctx context.Context, in string, forceFormat bool) (str } return out, nil } + +func getEvaluatorInputs(ctx context.Context, rc *RunContext, step step, ghc *model.GithubContext) map[string]interface{} { + inputs := map[string]interface{}{} + + var env map[string]string + if step != nil { + env = *step.getEnv() + } else { + env = rc.GetEnv() + } + + for k, v := range env { + if strings.HasPrefix(k, "INPUT_") { + inputs[strings.ToLower(strings.TrimPrefix(k, "INPUT_"))] = v + } + } + + if ghc.EventName == "workflow_dispatch" { + config := rc.Run.Workflow.WorkflowDispatchConfig() + for k, v := range config.Inputs { + value := nestedMapLookup(ghc.Event, "inputs", k) + if value == nil { + value = v.Default + } + if v.Type == "boolean" { + inputs[k] = value == "true" + } else { + inputs[k] = value + } + } + } + + return inputs +} diff --git a/pkg/runner/runner_test.go b/pkg/runner/runner_test.go index f2610a1..dbf8a00 100644 --- a/pkg/runner/runner_test.go +++ b/pkg/runner/runner_test.go @@ -182,6 +182,7 @@ func TestRunEvent(t *testing.T) { {workdir, "uses-action-with-pre-and-post-step", "push", "", platforms}, {workdir, "evalenv", "push", "", platforms}, {workdir, "ensure-post-steps", "push", "Job 'second-post-step-should-fail' failed", platforms}, + {workdir, "workflow_dispatch", "workflow_dispatch", "", platforms}, {"../model/testdata", "strategy", "push", "", platforms}, // TODO: move all testdata into pkg so we can validate it with planner and runner // {"testdata", "issue-228", "push", "", platforms, }, // TODO [igni]: Remove this once everything passes {"../model/testdata", "container-volumes", "push", "", platforms}, @@ -189,7 +190,14 @@ func TestRunEvent(t *testing.T) { for _, table := range tables { t.Run(table.workflowPath, func(t *testing.T) { - table.runTest(ctx, t, &Config{}) + config := &Config{} + + eventFile := filepath.Join(workdir, table.workflowPath, "event.json") + if _, err := os.Stat(eventFile); err == nil { + config.EventPath = eventFile + } + + table.runTest(ctx, t, config) }) } } diff --git a/pkg/runner/testdata/workflow_dispatch/event.json b/pkg/runner/testdata/workflow_dispatch/event.json new file mode 100644 index 0000000..d3ecab1 --- /dev/null +++ b/pkg/runner/testdata/workflow_dispatch/event.json @@ -0,0 +1,6 @@ +{ + "inputs": { + "required": "required input", + "boolean": "true" + } +} diff --git a/pkg/runner/testdata/workflow_dispatch/workflow_dispatch.yml b/pkg/runner/testdata/workflow_dispatch/workflow_dispatch.yml new file mode 100644 index 0000000..db12548 --- /dev/null +++ b/pkg/runner/testdata/workflow_dispatch/workflow_dispatch.yml @@ -0,0 +1,36 @@ +name: workflow_dispatch + +on: + workflow_dispatch: + inputs: + required: + description: a required input + required: true + with_default: + description: an input with default + required: false + default: default + boolean: + description: an input of type boolean + required: false + type: boolean + +jobs: + test: + runs-on: ubuntu-latest + steps: + - name: test required input + run: | + echo input.required=${{ inputs.required }} + [[ "${{ inputs.required }}" = "required input" ]] || exit 1 + - name: test input with default + run: | + echo input.with_default=${{ inputs.with_default }} + [[ "${{ inputs.with_default }}" = "default" ]] || exit 1 + - id: boolean-test + name: run on boolean input + if: ${{ inputs.boolean == true }} + run: echo "::set-output name=value::executed" + - name: has boolean test? + run: | + [[ "${{ steps.boolean-test.outputs.value }}" = "executed" ]] || exit 1 |