Skip to content

Commit

Permalink
expressions working
Browse files Browse the repository at this point in the history
  • Loading branch information
Unit Test committed Feb 13, 2020
1 parent 25fd377 commit d0eaa07
Show file tree
Hide file tree
Showing 114 changed files with 32,361 additions and 0 deletions.
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ module github.com/nektos/act

require (
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
github.com/MichaelTJones/walk v0.0.0-20161122175330-4748e29d5718 // indirect
github.com/Microsoft/go-winio v0.4.11 // indirect
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 // indirect
github.com/andreaskoch/go-fswatch v1.0.0
Expand All @@ -17,11 +18,13 @@ require (
github.com/gorilla/mux v1.7.0 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jtolds/gls v4.2.1+incompatible // indirect
github.com/mgutz/str v1.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/opencontainers/go-digest v1.0.0-rc1 // indirect
github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/opencontainers/runc v0.1.1 // indirect
github.com/pkg/errors v0.8.1
github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff
github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94
github.com/sirupsen/logrus v1.3.0
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 // indirect
Expand All @@ -38,7 +41,9 @@ require (
google.golang.org/genproto v0.0.0-20190128161407-8ac453e89fca // indirect
google.golang.org/grpc v1.18.0 // indirect
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
gopkg.in/godo.v2 v2.0.9
gopkg.in/ini.v1 v1.41.0 // indirect
gopkg.in/sourcemap.v1 v1.0.5 // indirect
gopkg.in/src-d/go-billy.v4 v4.3.0 // indirect
gopkg.in/src-d/go-git-fixtures.v3 v3.3.0 // indirect
gopkg.in/src-d/go-git.v4 v4.9.1
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 h1:w+iIsaOQNcT7OZ575w+acHgRric5iCyQh+xv+KJ4HB8=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/MichaelTJones/walk v0.0.0-20161122175330-4748e29d5718 h1:FSsoaa1q4jAaeiAUxf9H0PgFP7eA/UL6c3PdJH+nMN4=
github.com/MichaelTJones/walk v0.0.0-20161122175330-4748e29d5718/go.mod h1:VVwKsx9Dc8rNG55BWqogoJzGubjKnRoXdUvpGbWqeCc=
github.com/Microsoft/go-winio v0.4.11 h1:zoIOcVf0xPN1tnMVbTtEdI+P8OofVk3NObnwOQ6nK2Q=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw=
Expand Down Expand Up @@ -67,6 +69,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mgutz/str v1.2.0 h1:4IzWSdIz9qPQWLfKZ0rJcV0jcUDpxvP4JVZ4GXQyvSw=
github.com/mgutz/str v1.2.0/go.mod h1:w1v0ofgLaJdoD0HpQ3fycxKD1WtxpjSo151pK/31q6w=
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
Expand All @@ -85,6 +89,8 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff h1:+6NUiITWwE5q1KO6SAfUX918c+Tab0+tGAM/mtdlUyA=
github.com/robertkrimen/otto v0.0.0-20191219234010-c382bd3c16ff/go.mod h1:xvqspoSXJTIpemEonrMDFq6XzwHYYgToXWj5eRX1OtY=
github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94 h1:G04eS0JkAIVZfaJLjla9dNxkJCPiKIGZlw9AfOhzOD0=
github.com/sabhiram/go-gitignore v0.0.0-20180611051255-d3107576ba94/go.mod h1:b18R55ulyQ/h3RaWyloPyER7fWQVZvimKKhnI5OfrJQ=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
Expand Down Expand Up @@ -159,8 +165,12 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/godo.v2 v2.0.9 h1:jnbznTzXVk0JDKOxN3/LJLDPYJzIl0734y+Z0cEJb4A=
gopkg.in/godo.v2 v2.0.9/go.mod h1:wgvPPKLsWN0hPIJ4JyxvFGGbIW3fJMSrXhdvSuZ1z/8=
gopkg.in/ini.v1 v1.41.0 h1:Ka3ViY6gNYSKiVy71zXBEqKplnV35ImDLVG+8uoIklE=
gopkg.in/ini.v1 v1.41.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/src-d/go-billy.v4 v4.2.1 h1:omN5CrMrMcQ+4I8bJ0wEhOBPanIRWzFC953IiXKdYzo=
gopkg.in/src-d/go-billy.v4 v4.2.1/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk=
gopkg.in/src-d/go-billy.v4 v4.3.0 h1:KtlZ4c1OWbIs4jCv5ZXrTqG8EQocr0g/d4DjNg70aek=
Expand Down
171 changes: 171 additions & 0 deletions pkg/runner/expression.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
package runner

import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"regexp"
"strings"

"github.com/robertkrimen/otto"
"github.com/sirupsen/logrus"
"gopkg.in/godo.v2/glob"
)

const prefix = "${{"
const suffix = "}}"

var pattern *regexp.Regexp

func init() {
pattern = regexp.MustCompile(fmt.Sprintf("\\%s.+?%s", prefix, suffix))
}

// NewExpressionEvaluator creates a new evaluator
func (rc *RunContext) NewExpressionEvaluator() ExpressionEvaluator {
vm := rc.newVM()
return &expressionEvaluator{
vm,
}
}

// ExpressionEvaluator is the interface for evaluating expressions
type ExpressionEvaluator interface {
Evaluate(string) (string, error)
Interpolate(string) (string, error)
}

type expressionEvaluator struct {
vm *otto.Otto
}

func (ee *expressionEvaluator) Evaluate(in string) (string, error) {
val, err := ee.vm.Run(in)
if err != nil {
return "", err
}
return val.ToString()
}

func (ee *expressionEvaluator) Interpolate(in string) (string, error) {
errList := make([]error, 0)
out := pattern.ReplaceAllStringFunc(in, func(match string) string {
expression := strings.TrimPrefix(strings.TrimSuffix(match, suffix), prefix)
evaluated, err := ee.Evaluate(expression)
if err != nil {
errList = append(errList, err)
}
return evaluated
})
if len(errList) > 0 {
return "", fmt.Errorf("Unable to interpolate string '%s' - %v", in, errList)
}
return out, nil
}

func (rc *RunContext) newVM() *otto.Otto {
configers := []func(*otto.Otto){
vmContains,
vmStartsWith,
vmEndsWith,
vmFormat,
vmJoin,
vmToJSON,
vmHashFiles(rc.Config.Workdir),
}
vm := otto.New()
for _, configer := range configers {
configer(vm)
}
return vm
}

func vmContains(vm *otto.Otto) {
vm.Set("contains", func(searchString interface{}, searchValue string) bool {
if searchStringString, ok := searchString.(string); ok {
return strings.Contains(strings.ToLower(searchStringString), strings.ToLower(searchValue))
} else if searchStringArray, ok := searchString.([]string); ok {
for _, s := range searchStringArray {
if strings.ToLower(s) == strings.ToLower(searchValue) {
return true
}
}
}
return false
})
}

func vmStartsWith(vm *otto.Otto) {
vm.Set("startsWith", func(searchString string, searchValue string) bool {
return strings.HasPrefix(strings.ToLower(searchString), strings.ToLower(searchValue))
})
}

func vmEndsWith(vm *otto.Otto) {
vm.Set("endsWith", func(searchString string, searchValue string) bool {
return strings.HasSuffix(strings.ToLower(searchString), strings.ToLower(searchValue))
})
}

func vmFormat(vm *otto.Otto) {
vm.Set("format", func(s string, vals ...string) string {
for i, v := range vals {
s = strings.ReplaceAll(s, fmt.Sprintf("{%d}", i), v)
}
return s
})
}

func vmJoin(vm *otto.Otto) {
vm.Set("join", func(element interface{}, optionalElem string) string {
slist := make([]string, 0)
if elementString, ok := element.(string); ok {
slist = append(slist, elementString)
} else if elementArray, ok := element.([]string); ok {
slist = append(slist, elementArray...)
}
if optionalElem != "" {
slist = append(slist, optionalElem)
}
return strings.Join(slist, " ")
})
}

func vmToJSON(vm *otto.Otto) {
vm.Set("toJSON", func(o interface{}) string {
rtn, err := json.MarshalIndent(o, "", " ")
if err != nil {
logrus.Errorf("Unable to marsal: %v", err)
return ""
}
return string(rtn)
})
}

func vmHashFiles(workdir string) func(*otto.Otto) {
return func(vm *otto.Otto) {
vm.Set("hashFiles", func(path string) string {
files, _, err := glob.Glob([]string{filepath.Join(workdir, path)})
if err != nil {
logrus.Error(err)
return ""
}
hasher := sha256.New()
for _, file := range files {
f, err := os.Open(file.Path)
if err != nil {
logrus.Error(err)
}
defer f.Close()
if _, err := io.Copy(hasher, f); err != nil {
logrus.Error(err)
}
}
return hex.EncodeToString(hasher.Sum(nil))
})
}
}
69 changes: 69 additions & 0 deletions pkg/runner/expression_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package runner

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestEvaluate(t *testing.T) {
assert := assert.New(t)
rc := &RunContext{
Config: &Config{
Workdir: ".",
},
}
ee := rc.NewExpressionEvaluator()

tables := []struct {
in string
out string
errMesg string
}{
{" 1 ", "1", ""},
{"1 + 3", "4", ""},
{"(1 + 3) * -2", "-8", ""},
{"'my text'", "my text", ""},
{"contains('my text', 'te')", "true", ""},
{"contains('my TEXT', 'te')", "true", ""},
{"contains(['my text'], 'te')", "false", ""},
{"contains(['foo','bar'], 'bar')", "true", ""},
{"startsWith('hello world', 'He')", "true", ""},
{"endsWith('hello world', 'ld')", "true", ""},
{"format('0:{0} 2:{2} 1:{1}', 'zero', 'one', 'two')", "0:zero 2:two 1:one", ""},
{"join(['hello'],'octocat')", "hello octocat", ""},
{"join(['hello','mona','the'],'octocat')", "hello mona the octocat", ""},
{"join('hello','mona')", "hello mona", ""},
{"toJSON({'foo':'bar'})", "{\n \"foo\": \"bar\"\n}", ""},
{"hashFiles('**/package-lock.json')", "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""},
}

for _, table := range tables {
table := table
t.Run(table.in, func(t *testing.T) {
out, err := ee.Evaluate(table.in)
if table.errMesg == "" {
assert.NoError(err, table.in)
assert.Equal(table.out, out)
} else {
assert.Error(err)
assert.Equal(table.errMesg, err.Error())
}
})
}
}

func TestInterpolate(t *testing.T) {
assert := assert.New(t)
rc := &RunContext{
Config: &Config{
Workdir: ".",
},
}
ee := rc.NewExpressionEvaluator()

out, err := ee.Interpolate(" ${{1}} to ${{2}} ")

assert.NoError(err)
assert.Equal(" 1 to 2 ", out)
}
25 changes: 25 additions & 0 deletions vendor/github.com/MichaelTJones/walk/README.md

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

30 changes: 30 additions & 0 deletions vendor/github.com/MichaelTJones/walk/path_plan9.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit d0eaa07

Please sign in to comment.