From bef9b5c3c77bcdbc6c15169c0d55f635e27350ae Mon Sep 17 00:00:00 2001 From: Aaron Holmes Date: Mon, 19 Dec 2022 00:37:53 -0800 Subject: [PATCH] feat: Support "result" on "needs" context. (#1497) * Support "result" on "needs" context. This change adds "result" to a job's "needs" context, as documented [here](https://docs.github.com/en/actions/learn-github-actions/contexts#needs-context). `act` currently tracks the success/failure/cancelled status of a job, but does not include this value the `needs` context. Fixes #1367 * Change `Needs` to use a new struct rather than the open type `interface{}`. Related #1497 Fixes #1367 * Add integration test to "needs" context change. Relates: #1497 * feat: allow to spawn and run a local reusable workflow (#1423) * feat: allow to spawn and run a local reusable workflow This change contains the ability to parse/plan/run a local reusable workflow. There are still numerous things missing: - inputs - secrets - outputs * feat: add workflow_call inputs * test: improve inputs test * feat: add input defaults * feat: allow expressions in inputs * feat: use context specific expression evaluator * refactor: prepare for better re-usability * feat: add secrets for reusable workflows * test: use secrets during test run * feat: handle reusable workflow outputs Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * refactor: fix savestate in pre steps (#1466) * refactor: fix savestate in pre steps * fix pre steps collision * fix tests * remove * enable tests * Update pkg/runner/action.go * Rename InterActionState to IntraActionState Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * fix: tail (not absolute) as entrypoint of job container (#1506) Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> * Fix conflict in merge. Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com> --- pkg/exprparser/interpreter.go | 7 ++++++- pkg/exprparser/interpreter_test.go | 6 ++++-- pkg/runner/expression.go | 14 ++++++++------ pkg/runner/runner_test.go | 1 + .../job-needs-context-contains-result/push.yml | 15 +++++++++++++++ 5 files changed, 34 insertions(+), 9 deletions(-) create mode 100644 pkg/runner/testdata/job-needs-context-contains-result/push.yml diff --git a/pkg/exprparser/interpreter.go b/pkg/exprparser/interpreter.go index 7b76f3b..6b276fd 100644 --- a/pkg/exprparser/interpreter.go +++ b/pkg/exprparser/interpreter.go @@ -20,10 +20,15 @@ type EvaluationEnvironment struct { Secrets map[string]string Strategy map[string]interface{} Matrix map[string]interface{} - Needs map[string]map[string]map[string]string + Needs map[string]Needs Inputs map[string]interface{} } +type Needs struct { + Outputs map[string]string `json:"outputs"` + Result string `json:"result"` +} + type Config struct { Run *model.Run WorkingDir string diff --git a/pkg/exprparser/interpreter_test.go b/pkg/exprparser/interpreter_test.go index 2547aae..d6f58a7 100644 --- a/pkg/exprparser/interpreter_test.go +++ b/pkg/exprparser/interpreter_test.go @@ -555,6 +555,7 @@ func TestContexts(t *testing.T) { {"strategy.fail-fast", true, "strategy-context"}, {"matrix.os", "Linux", "matrix-context"}, {"needs.job-id.outputs.output-name", "value", "needs-context"}, + {"needs.job-id.result", "success", "needs-context"}, {"inputs.name", "value", "inputs-context"}, } @@ -593,11 +594,12 @@ func TestContexts(t *testing.T) { Matrix: map[string]interface{}{ "os": "Linux", }, - Needs: map[string]map[string]map[string]string{ + Needs: map[string]Needs{ "job-id": { - "outputs": { + Outputs: map[string]string{ "output-name": "value", }, + Result: "success", }, }, Inputs: map[string]interface{}{ diff --git a/pkg/runner/expression.go b/pkg/runner/expression.go index dc6b0e5..a8d506e 100644 --- a/pkg/runner/expression.go +++ b/pkg/runner/expression.go @@ -26,7 +26,7 @@ func (rc *RunContext) NewExpressionEvaluator(ctx context.Context) ExpressionEval func (rc *RunContext) NewExpressionEvaluatorWithEnv(ctx context.Context, env map[string]string) ExpressionEvaluator { // todo: cleanup EvaluationEnvironment creation - using := make(map[string]map[string]map[string]string) + using := make(map[string]exprparser.Needs) strategy := make(map[string]interface{}) if rc.Run != nil { job := rc.Run.Job() @@ -39,8 +39,9 @@ func (rc *RunContext) NewExpressionEvaluatorWithEnv(ctx context.Context, env map jobNeeds := rc.Run.Job().Needs() for _, needs := range jobNeeds { - using[needs] = map[string]map[string]string{ - "outputs": jobs[needs].Outputs, + using[needs] = exprparser.Needs{ + Outputs: jobs[needs].Outputs, + Result: jobs[needs].Result, } } } @@ -86,10 +87,11 @@ func (rc *RunContext) NewStepExpressionEvaluator(ctx context.Context, step step) jobs := rc.Run.Workflow.Jobs jobNeeds := rc.Run.Job().Needs() - using := make(map[string]map[string]map[string]string) + using := make(map[string]exprparser.Needs) for _, needs := range jobNeeds { - using[needs] = map[string]map[string]string{ - "outputs": jobs[needs].Outputs, + using[needs] = exprparser.Needs{ + Outputs: jobs[needs].Outputs, + Result: jobs[needs].Result, } } diff --git a/pkg/runner/runner_test.go b/pkg/runner/runner_test.go index 1f61411..5cf4837 100644 --- a/pkg/runner/runner_test.go +++ b/pkg/runner/runner_test.go @@ -196,6 +196,7 @@ func TestRunEvent(t *testing.T) { {workdir, "workflow_dispatch_no_inputs_mapping", "workflow_dispatch", "", platforms, secrets}, {workdir, "workflow_dispatch-scalar", "workflow_dispatch", "", platforms, secrets}, {workdir, "workflow_dispatch-scalar-composite-action", "workflow_dispatch", "", platforms, secrets}, + {workdir, "job-needs-context-contains-result", "push", "", platforms, secrets}, {"../model/testdata", "strategy", "push", "", platforms, secrets}, // 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, secrets}, diff --git a/pkg/runner/testdata/job-needs-context-contains-result/push.yml b/pkg/runner/testdata/job-needs-context-contains-result/push.yml new file mode 100644 index 0000000..0ecbcea --- /dev/null +++ b/pkg/runner/testdata/job-needs-context-contains-result/push.yml @@ -0,0 +1,15 @@ +on: + push: +jobs: + test: + runs-on: ubuntu-latest + steps: + - run: exit 0 + assert: + needs: test + if: | + ( always() && !cancelled() ) && ( + ( needs.test.result != 'success' || !success() ) ) + runs-on: ubuntu-latest + steps: + - run: exit 1