Add more steps context support (#887)
* feat: add more steps context support - Add step outcome - Remove step success in favour of conclusion * feat: add conclusion and outcome steps context tests Add corresponding tests and extend pkg/runner/expression.go vmSteps() to handle steps context conclusion and outcome iota as strings. Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
parent
6517d04b9a
commit
e793d03f4b
|
@ -466,9 +466,19 @@ func (rc *RunContext) vmJob() func(*otto.Otto) {
|
|||
}
|
||||
|
||||
func (rc *RunContext) vmSteps() func(*otto.Otto) {
|
||||
steps := rc.getStepsContext()
|
||||
ctxSteps := rc.getStepsContext()
|
||||
|
||||
steps := make(map[string]interface{})
|
||||
for id, ctxStep := range ctxSteps {
|
||||
steps[id] = map[string]interface{}{
|
||||
"conclusion": ctxStep.Conclusion.String(),
|
||||
"outcome": ctxStep.Outcome.String(),
|
||||
"outputs": ctxStep.Outputs,
|
||||
}
|
||||
}
|
||||
|
||||
return func(vm *otto.Otto) {
|
||||
log.Debugf("context steps => %v", steps)
|
||||
_ = vm.Set("steps", steps)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,22 +49,25 @@ func TestEvaluate(t *testing.T) {
|
|||
},
|
||||
StepResults: map[string]*stepResult{
|
||||
"idwithnothing": {
|
||||
Conclusion: stepStatusSuccess,
|
||||
Outcome: stepStatusFailure,
|
||||
Outputs: map[string]string{
|
||||
"foowithnothing": "barwithnothing",
|
||||
},
|
||||
Success: true,
|
||||
},
|
||||
"id-with-hyphens": {
|
||||
Conclusion: stepStatusSuccess,
|
||||
Outcome: stepStatusFailure,
|
||||
Outputs: map[string]string{
|
||||
"foo-with-hyphens": "bar-with-hyphens",
|
||||
},
|
||||
Success: true,
|
||||
},
|
||||
"id_with_underscores": {
|
||||
Conclusion: stepStatusSuccess,
|
||||
Outcome: stepStatusFailure,
|
||||
Outputs: map[string]string{
|
||||
"foo_with_underscores": "bar_with_underscores",
|
||||
},
|
||||
Success: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -107,8 +110,14 @@ func TestEvaluate(t *testing.T) {
|
|||
{"github.run_id", "1", ""},
|
||||
{"github.run_number", "1", ""},
|
||||
{"job.status", "success", ""},
|
||||
{"steps.idwithnothing.conclusion", "success", ""},
|
||||
{"steps.idwithnothing.outcome", "failure", ""},
|
||||
{"steps.idwithnothing.outputs.foowithnothing", "barwithnothing", ""},
|
||||
{"steps.id-with-hyphens.conclusion", "success", ""},
|
||||
{"steps.id-with-hyphens.outcome", "failure", ""},
|
||||
{"steps.id-with-hyphens.outputs.foo-with-hyphens", "bar-with-hyphens", ""},
|
||||
{"steps.id_with_underscores.conclusion", "success", ""},
|
||||
{"steps.id_with_underscores.outcome", "failure", ""},
|
||||
{"steps.id_with_underscores.outputs.foo_with_underscores", "bar_with_underscores", ""},
|
||||
{"runner.os", "Linux", ""},
|
||||
{"matrix.os", "Linux", ""},
|
||||
|
|
|
@ -52,9 +52,44 @@ func (rc *RunContext) String() string {
|
|||
return fmt.Sprintf("%s/%s", rc.Run.Workflow.Name, rc.Name)
|
||||
}
|
||||
|
||||
type stepStatus int
|
||||
|
||||
const (
|
||||
stepStatusSuccess stepStatus = iota
|
||||
stepStatusFailure
|
||||
)
|
||||
|
||||
var stepStatusStrings = [...]string{
|
||||
"success",
|
||||
"failure",
|
||||
}
|
||||
|
||||
func (s stepStatus) MarshalText() ([]byte, error) {
|
||||
return []byte(s.String()), nil
|
||||
}
|
||||
|
||||
func (s *stepStatus) UnmarshalText(b []byte) error {
|
||||
str := string(b)
|
||||
for i, name := range stepStatusStrings {
|
||||
if name == str {
|
||||
*s = stepStatus(i)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("invalid step status %q", str)
|
||||
}
|
||||
|
||||
func (s stepStatus) String() string {
|
||||
if int(s) >= len(stepStatusStrings) {
|
||||
return ""
|
||||
}
|
||||
return stepStatusStrings[s]
|
||||
}
|
||||
|
||||
type stepResult struct {
|
||||
Success bool `json:"success"`
|
||||
Outputs map[string]string `json:"outputs"`
|
||||
Conclusion stepStatus `json:"conclusion"`
|
||||
Outcome stepStatus `json:"outcome"`
|
||||
}
|
||||
|
||||
// GetEnv returns the env for the context
|
||||
|
@ -266,7 +301,8 @@ func (rc *RunContext) newStepExecutor(step *model.Step) common.Executor {
|
|||
return func(ctx context.Context) error {
|
||||
rc.CurrentStep = sc.Step.ID
|
||||
rc.StepResults[rc.CurrentStep] = &stepResult{
|
||||
Success: true,
|
||||
Outcome: stepStatusSuccess,
|
||||
Conclusion: stepStatusSuccess,
|
||||
Outputs: make(map[string]string),
|
||||
}
|
||||
runStep, err := rc.EvalBool(sc.Step.If.Value)
|
||||
|
@ -278,7 +314,8 @@ func (rc *RunContext) newStepExecutor(step *model.Step) common.Executor {
|
|||
return err
|
||||
}
|
||||
rc.ExprEval = exprEval
|
||||
rc.StepResults[rc.CurrentStep].Success = false
|
||||
rc.StepResults[rc.CurrentStep].Conclusion = stepStatusFailure
|
||||
rc.StepResults[rc.CurrentStep].Outcome = stepStatusFailure
|
||||
return err
|
||||
}
|
||||
|
||||
|
@ -300,12 +337,13 @@ func (rc *RunContext) newStepExecutor(step *model.Step) common.Executor {
|
|||
} else {
|
||||
common.Logger(ctx).Errorf(" \u274C Failure - %s", sc.Step)
|
||||
|
||||
rc.StepResults[rc.CurrentStep].Outcome = stepStatusFailure
|
||||
if sc.Step.ContinueOnError {
|
||||
common.Logger(ctx).Infof("Failed but continue next step")
|
||||
err = nil
|
||||
rc.StepResults[rc.CurrentStep].Success = true
|
||||
rc.StepResults[rc.CurrentStep].Conclusion = stepStatusSuccess
|
||||
} else {
|
||||
rc.StepResults[rc.CurrentStep].Success = false
|
||||
rc.StepResults[rc.CurrentStep].Conclusion = stepStatusFailure
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
@ -500,7 +538,7 @@ type jobContext struct {
|
|||
func (rc *RunContext) getJobContext() *jobContext {
|
||||
jobStatus := "success"
|
||||
for _, stepStatus := range rc.StepResults {
|
||||
if !stepStatus.Success {
|
||||
if stepStatus.Conclusion == stepStatusFailure {
|
||||
jobStatus = "failure"
|
||||
break
|
||||
}
|
||||
|
|
|
@ -54,10 +54,11 @@ func TestRunContext_EvalBool(t *testing.T) {
|
|||
},
|
||||
StepResults: map[string]*stepResult{
|
||||
"id1": {
|
||||
Conclusion: stepStatusSuccess,
|
||||
Outcome: stepStatusFailure,
|
||||
Outputs: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
Success: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
@ -73,6 +74,10 @@ func TestRunContext_EvalBool(t *testing.T) {
|
|||
{in: "success()", out: true},
|
||||
{in: "cancelled()", out: false},
|
||||
{in: "always()", out: true},
|
||||
{in: "steps.id1.conclusion == 'success'", out: true},
|
||||
{in: "steps.id1.conclusion != 'success'", out: false},
|
||||
{in: "steps.id1.outcome == 'failure'", out: true},
|
||||
{in: "steps.id1.outcome != 'failure'", out: false},
|
||||
{in: "true", out: true},
|
||||
{in: "false", out: false},
|
||||
{in: "!true", wantErr: true},
|
||||
|
|
|
@ -121,6 +121,8 @@ func TestRunEvent(t *testing.T) {
|
|||
{"testdata", "issue-598", "push", "", platforms, ""},
|
||||
{"testdata", "env-and-path", "push", "", platforms, ""},
|
||||
{"testdata", "outputs", "push", "", platforms, ""},
|
||||
{"testdata", "steps-context/conclusion", "push", "", platforms, ""},
|
||||
{"testdata", "steps-context/outcome", "push", "", 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
|
||||
|
||||
|
|
|
@ -640,7 +640,7 @@ func (sc *StepContext) execAsComposite(ctx context.Context, step *model.Step, _
|
|||
// Setup the outputs for the composite steps
|
||||
if _, ok := rcClone.StepResults[stepClone.ID]; !ok {
|
||||
rcClone.StepResults[stepClone.ID] = &stepResult{
|
||||
Success: true,
|
||||
Conclusion: stepStatusSuccess,
|
||||
Outputs: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
name: conclusion
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- id: first
|
||||
run: exit 0
|
||||
- id: second
|
||||
continue-on-error: true
|
||||
run: exit 1
|
||||
- run: echo '${{ steps.first.conclusion }}' | grep 'success'
|
||||
- run: echo '${{ steps.second.conclusion }}' | grep 'success'
|
|
@ -0,0 +1,14 @@
|
|||
name: outcome
|
||||
on: push
|
||||
|
||||
jobs:
|
||||
check:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- id: first
|
||||
run: exit 0
|
||||
- id: second
|
||||
continue-on-error: true
|
||||
run: exit 1
|
||||
- run: echo '${{ steps.first.outcome }}' | grep 'success'
|
||||
- run: echo '${{ steps.second.outcome }}' | grep 'failure'
|
Loading…
Reference in New Issue