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>
This commit is contained in:
Aaron Holmes 2022-12-19 00:37:53 -08:00 committed by GitHub
parent 0c8c082ac0
commit bef9b5c3c7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 34 additions and 9 deletions

View file

@ -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

View file

@ -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{}{

View file

@ -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,
}
}

View file

@ -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},

View file

@ -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