Skip to content

Commit

Permalink
Rewrite contexts before evaluating them
Browse files Browse the repository at this point in the history
  • Loading branch information
badouralix committed Jun 21, 2020
1 parent d4e41a9 commit 5a72c07
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 5 deletions.
33 changes: 31 additions & 2 deletions pkg/runner/expression.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,20 @@ func (sc *StepContext) NewExpressionEvaluator() ExpressionEvaluator {
type ExpressionEvaluator interface {
Evaluate(string) (string, error)
Interpolate(string) string
Rewrite(string) string
}

type expressionEvaluator struct {
vm *otto.Otto
}

func (ee *expressionEvaluator) Evaluate(in string) (string, error) {
val, err := ee.vm.Run(in)
re := ee.Rewrite(in)
if re != in {
logrus.Debugf("Evaluating '%s' instead of '%s'", re, in)
}

val, err := ee.vm.Run(re)
if err != nil {
return "", err
}
Expand All @@ -77,7 +83,7 @@ func (ee *expressionEvaluator) Interpolate(in string) string {
out := in
for {
out = pattern.ReplaceAllStringFunc(in, func(match string) string {
expression := strings.TrimPrefix(strings.TrimSuffix(match, suffix), prefix)
expression := strings.TrimSpace(strings.TrimPrefix(strings.TrimSuffix(match, suffix), prefix))
evaluated, err := ee.Evaluate(expression)
if err != nil {
errList = append(errList, err)
Expand All @@ -97,6 +103,29 @@ func (ee *expressionEvaluator) Interpolate(in string) string {
return out
}

// Rewrite tries to transform any javascript property accessor into its bracket notation.
// For instance, "object.property" would become "object['property']".
func (ee *expressionEvaluator) Rewrite(in string) string {
p := regexp.MustCompile(`^(\w+(?:\[.+\])*)(?:\.([\w-]+))?(.*)$`)

re := in
for {
matches := p.FindStringSubmatch(re)
if matches == nil {
// no global match, we're done!
break
}
if matches[2] == "" {
// no property match, we're done!
break
}

re = fmt.Sprintf("%s['%s']%s", matches[1], matches[2], matches[3])
}

return re
}

func (rc *RunContext) newVM() *otto.Otto {
configers := []func(*otto.Otto){
vmContains,
Expand Down
62 changes: 59 additions & 3 deletions pkg/runner/expression_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,21 @@ func TestEvaluate(t *testing.T) {
"foo": "bar",
},
StepResults: map[string]*stepResult{
"id1": {
"idwithnothing": {
Outputs: map[string]string{
"foo": "bar",
"foowithnothing": "barwithnothing",
},
Success: true,
},
"id-with-hyphens": {
Outputs: map[string]string{
"foo-with-hyphens": "bar-with-hyphens",
},
Success: true,
},
"id_with_underscores": {
Outputs: map[string]string{
"foo_with_underscores": "bar_with_underscores",
},
Success: true,
},
Expand Down Expand Up @@ -78,7 +90,9 @@ func TestEvaluate(t *testing.T) {
{"github.run_id", "1", ""},
{"github.run_number", "1", ""},
{"job.status", "success", ""},
{"steps.id1.outputs.foo", "bar", ""},
{"steps.idwithnothing.outputs.foowithnothing", "barwithnothing", ""},
{"steps.id-with-hyphens.outputs.foo-with-hyphens", "bar-with-hyphens", ""},
{"steps.id_with_underscores.outputs.foo_with_underscores", "bar_with_underscores", ""},
{"runner.os", "Linux", ""},
{"matrix.os", "Linux", ""},
{"matrix.foo", "bar", ""},
Expand Down Expand Up @@ -137,3 +151,45 @@ func TestInterpolate(t *testing.T) {
})
}
}

func TestRewrite(t *testing.T) {
assert := a.New(t)

rc := &RunContext{
Config: &Config{},
Run: &model.Run{
JobID: "job1",
Workflow: &model.Workflow{
Jobs: map[string]*model.Job{
"job1": {},
},
},
},
}
ee := rc.NewExpressionEvaluator()

tables := []struct {
in string
re string
}{
{"ecole", "ecole"},
{"ecole.centrale", "ecole['centrale']"},
{"ecole['centrale']", "ecole['centrale']"},
{"ecole.centrale.paris", "ecole['centrale']['paris']"},
{"ecole['centrale'].paris", "ecole['centrale']['paris']"},
{"ecole.centrale['paris']", "ecole['centrale']['paris']"},
{"ecole['centrale']['paris']", "ecole['centrale']['paris']"},
{"ecole.centrale-paris", "ecole['centrale-paris']"},
{"ecole['centrale-paris']", "ecole['centrale-paris']"},
{"ecole.centrale_paris", "ecole['centrale_paris']"},
{"ecole['centrale_paris']", "ecole['centrale_paris']"},
}

for _, table := range tables {
table := table
t.Run(table.in, func(t *testing.T) {
re := ee.Rewrite(table.in)
assert.Equal(table.re, re, table.in)
})
}
}

0 comments on commit 5a72c07

Please sign in to comment.