diff --git a/pkg/model/planner.go b/pkg/model/planner.go index 828132e..3c2a660 100644 --- a/pkg/model/planner.go +++ b/pkg/model/planner.go @@ -50,6 +50,40 @@ func (r *Run) Job() *Job { return r.Workflow.GetJob(r.JobID) } +// Helper function for FixIfstatement +func FixIfStatement1(val string, lines [][][]byte, l int) (string, error) { + if val != "" { + line := lines[l-1][0] + outcome := regexp.MustCompile(`\s+if:\s+".*".*`).FindSubmatch(line) + if outcome != nil { + oldLines := regexp.MustCompile(`"(.*?)"`).FindAllSubmatch(line, 2) + val = "${{" + string(oldLines[0][1]) + "}}" + } + } + return val, nil +} + +// Fixes faulty if statements from decoder +func FixIfStatement(content []byte, wr *Workflow) error { + jobs := wr.Jobs + lines := regexp.MustCompile(".*\n|.+$").FindAllSubmatch(content, -1) + for j := range jobs { + val, err := FixIfStatement1(jobs[j].If.Value, lines, jobs[j].If.Line) + if err != nil { + return err + } + jobs[j].If.Value = val + for i := range jobs[j].Steps { + val, err = FixIfStatement1(jobs[j].Steps[i].If.Value, lines, jobs[j].Steps[i].If.Line) + if err != nil { + return err + } + jobs[j].Steps[i].If.Value = val + } + } + return nil +} + type WorkflowFiles struct { workflowFileInfo os.FileInfo dirPath string @@ -135,6 +169,21 @@ func NewWorkflowPlanner(path string, noWorkflowRecurse bool) (WorkflowPlanner, e } return nil, err } + _, err = f.Seek(0, 0) + if err != nil { + f.Close() + return nil, errors.WithMessagef(err, "error occurring when resetting io pointer, %s", wf.workflowFileInfo.Name()) + } + log.Debugf("Correcting if statements '%s'", f.Name()) + content, err := ioutil.ReadFile(filepath.Join(wf.dirPath, wf.workflowFileInfo.Name())) + if err != nil { + return nil, errors.WithMessagef(err, "error occurring when reading file, %s", wf.workflowFileInfo.Name()) + } + + err = FixIfStatement(content, workflow) + if err != nil { + return nil, err + } if workflow.Name == "" { workflow.Name = wf.workflowFileInfo.Name() diff --git a/pkg/model/workflow.go b/pkg/model/workflow.go index 25f419a..4510ffb 100644 --- a/pkg/model/workflow.go +++ b/pkg/model/workflow.go @@ -59,7 +59,7 @@ type Job struct { RawNeeds yaml.Node `yaml:"needs"` RawRunsOn yaml.Node `yaml:"runs-on"` Env map[string]string `yaml:"env"` - If string `yaml:"if"` + If yaml.Node `yaml:"if"` Steps []*Step `yaml:"steps"` TimeoutMinutes int64 `yaml:"timeout-minutes"` Services map[string]*ContainerSpec `yaml:"services"` @@ -211,7 +211,7 @@ type ContainerSpec struct { // Step is the structure of one step in a job type Step struct { ID string `yaml:"id"` - If string `yaml:"if"` + If yaml.Node `yaml:"if"` Name string `yaml:"name"` Uses string `yaml:"uses"` Run string `yaml:"run"` diff --git a/pkg/runner/run_context.go b/pkg/runner/run_context.go index 1c4bba1..d26a4cd 100755 --- a/pkg/runner/run_context.go +++ b/pkg/runner/run_context.go @@ -229,7 +229,7 @@ func (rc *RunContext) newStepExecutor(step *model.Step) common.Executor { Success: true, Outputs: make(map[string]string), } - runStep, err := rc.EvalBool(sc.Step.If) + runStep, err := rc.EvalBool(sc.Step.If.Value) if err != nil { common.Logger(ctx).Errorf(" \u274C Error in if: expression - %s", sc.Step) @@ -243,7 +243,7 @@ func (rc *RunContext) newStepExecutor(step *model.Step) common.Executor { } if !runStep { - log.Debugf("Skipping step '%s' due to '%s'", sc.Step.String(), sc.Step.If) + log.Debugf("Skipping step '%s' due to '%s'", sc.Step.String(), sc.Step.If.Value) return nil } @@ -298,13 +298,13 @@ func (rc *RunContext) platformImage() string { func (rc *RunContext) isEnabled(ctx context.Context) bool { job := rc.Run.Job() l := common.Logger(ctx) - runJob, err := rc.EvalBool(job.If) + runJob, err := rc.EvalBool(job.If.Value) if err != nil { common.Logger(ctx).Errorf(" \u274C Error in if: expression - %s", job.Name) return false } if !runJob { - l.Debugf("Skipping job '%s' due to '%s'", job.Name, job.If) + l.Debugf("Skipping job '%s' due to '%s'", job.Name, job.If.Value) return false } diff --git a/pkg/runner/runner_test.go b/pkg/runner/runner_test.go index ddf99b6..89e1061 100644 --- a/pkg/runner/runner_test.go +++ b/pkg/runner/runner_test.go @@ -106,6 +106,7 @@ func TestRunEvent(t *testing.T) { {"testdata", "defaults-run", "push", "", platforms, ""}, {"testdata", "uses-composite", "push", "", platforms, ""}, {"testdata", "issue-597", "push", "", platforms, ""}, + {"testdata", "issue-598", "push", "", platforms, ""}, // {"testdata", "issue-228", "push", "", platforms, ""}, // TODO [igni]: Remove this once everything passes // single test for different architecture: linux/arm64 diff --git a/pkg/runner/testdata/issue-598/spelling.yml b/pkg/runner/testdata/issue-598/spelling.yml new file mode 100644 index 0000000..65255f9 --- /dev/null +++ b/pkg/runner/testdata/issue-598/spelling.yml @@ -0,0 +1,31 @@ +name: issue-598 +on: push + + +jobs: + my_first_job: + + runs-on: ubuntu-latest + steps: + - name: My first false step + if: "endsWith('Hello world', 'o1')" + uses: actions/hello-world-javascript-action@main + with: + who-to-greet: 'Mona the Octocat' + - name: My first true step + if: "!endsWith('Hello world', 'od')" + uses: actions/hello-world-javascript-action@main + with: + who-to-greet: "Renst the Octocat" + - name: My second false step + if: "endsWith('Hello world', 'o2')" + uses: actions/hello-world-javascript-action@main + with: + who-to-greet: 'Act the Octocat' + - name: My third false step + if: "endsWith('Hello world', 'o2')" + uses: actions/hello-world-javascript-action@main + with: + who-to-greet: 'Git the Octocat' + + \ No newline at end of file