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