From 16ca81c679ea33c25442a489c303e83ff083bab0 Mon Sep 17 00:00:00 2001 From: Robert Kaussow Date: Sat, 18 Sep 2021 17:14:54 +0200 Subject: [PATCH] refactor: replace unsupported raymond package with handlebars/v3 (#2) The raymond package appears to be abandoned. This changes to a supported fork (handlebars/v3) that has Go module support, and has some maintenance done. Additionally, updates to latest sprig package, and changes the logic used to skip/avoid adding sprig helpers to handlebars when the func has an unsupported return type. Co-authored-by: Kenneth Shaw --- go.mod | 10 ++++- go.sum | 56 +++++++++++++++-------- template/helpers.go | 97 +++++++++++++--------------------------- template/helpers_test.go | 4 -- template/template.go | 7 +-- 5 files changed, 80 insertions(+), 94 deletions(-) diff --git a/go.mod b/go.mod index f860481..e470749 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,12 @@ module github.com/drone/drone-template-lib go 1.13 require ( - github.com/Masterminds/sprig/v3 v3.1.0 - github.com/aymerick/raymond v2.0.2+incompatible + github.com/Masterminds/sprig/v3 v3.2.2 + github.com/flowchartsman/handlebars/v3 v3.0.1 + github.com/google/uuid v1.3.0 // indirect + github.com/huandu/xstrings v1.3.2 // indirect + github.com/imdario/mergo v0.3.12 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect + github.com/spf13/cast v1.4.1 // indirect + golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect ) diff --git a/go.sum b/go.sum index 322002e..a0fe3e7 100644 --- a/go.sum +++ b/go.sum @@ -1,37 +1,57 @@ -github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RPBiVg= -github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver/v3 v3.1.0 h1:Y2lUDsFKVRSYGojLJ1yLxSXdMmMYTYls0rCvoqmMUQk= -github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= -github.com/Masterminds/sprig/v3 v3.1.0 h1:j7GpgZ7PdFqNsmncycTHsLmVPf5/3wJtlgW9TNDYD9Y= -github.com/Masterminds/sprig/v3 v3.1.0/go.mod h1:ONGMf7UfYGAbMXCZmQLy8x3lCDIPrEZE/rU8pmrbihA= -github.com/aymerick/raymond v1.1.0 h1:phuNN2s67eI/HtO8CrvqFcdR2JP+BtkGJZ9n692Hr2Y= -github.com/aymerick/raymond v2.0.2+incompatible h1:VEp3GpgdAnv9B2GFyTvqgcKvY+mfKMjPOA3SbKLtnU0= -github.com/aymerick/raymond v2.0.2+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= +github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/flowchartsman/handlebars/v3 v3.0.1 h1:16YAX2vJ2X2wgliz4QoUNyOJDLmnZ7Uldg/5w49/z3A= +github.com/flowchartsman/handlebars/v3 v3.0.1/go.mod h1:HGaRKxnZS8F2cteR3rusKeY+lI9fbnqwwesT+A3a18I= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= -github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= +github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw= +github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= +github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= -github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +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/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= +github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20200414173820-0848c9571904 h1:bXoxMPcSLOq08zI3/c5dEBT6lE4eh+jOh886GHrn6V8= golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/template/helpers.go b/template/helpers.go index b4f931b..534c7d0 100644 --- a/template/helpers.go +++ b/template/helpers.go @@ -18,6 +18,7 @@ import ( "fmt" "math" "net/url" + "reflect" "regexp" "strings" "time" @@ -25,11 +26,11 @@ import ( "unicode/utf8" "github.com/Masterminds/sprig/v3" - "github.com/aymerick/raymond" + "github.com/flowchartsman/handlebars/v3" ) -var ( - funcs = map[string]interface{}{ +func init() { + funcs := map[string]interface{}{ "duration": toDuration, "datetime": toDatetime, "success": isSuccess, @@ -42,18 +43,13 @@ var ( "lowercase": strings.ToLower, "regexReplace": regexReplace, } -) - -func init() { - for name, function := range sprig.GenericFuncMap() { - if invalidHelper(name) { + for name, f := range sprig.GenericFuncMap() { + if _, ok := funcs[name]; ok || !validHelper(f) { continue } - - funcs[name] = function + funcs[name] = f } - - raymond.RegisterHelpers(funcs) + handlebars.RegisterHelpers(funcs) } func toDuration(started, finished int64) string { @@ -66,7 +62,6 @@ func toDatetime(timestamp int64, layout, zone string) string { } loc, err := time.LoadLocation(zone) - if err != nil { return time.Unix(timestamp, 0).Local().Format(layout) } @@ -74,7 +69,7 @@ func toDatetime(timestamp int64, layout, zone string) string { return time.Unix(timestamp, 0).In(loc).Format(layout) } -func isSuccess(conditional bool, options *raymond.Options) string { +func isSuccess(conditional bool, options *handlebars.Options) string { if !conditional { return options.Inverse() } @@ -87,7 +82,7 @@ func isSuccess(conditional bool, options *raymond.Options) string { } } -func isFailure(conditional bool, options *raymond.Options) string { +func isFailure(conditional bool, options *handlebars.Options) string { if !conditional { return options.Inverse() } @@ -115,7 +110,7 @@ func truncate(s string, len int) string { return string(runes[:len]) } -func urlencode(options *raymond.Options) string { +func urlencode(options *handlebars.Options) string { return url.QueryEscape(options.Fn()) } @@ -138,56 +133,28 @@ func regexReplace(pattern string, input string, replacement string) string { return re.ReplaceAllString(input, replacement) } -func invalidHelper(name string) bool { - invalids := []string{ - "buildCustomCert", - "decryptAES", - "derivePassword", - "encryptAES", - "fail", - "genCA", - "genPrivateKey", - "genSelfSignedCert", - "genSignedCert", - "hello", - "mustAppend", - "mustCompact", - "mustDateModify", - "mustDeepCopy", - "mustFirst", - "mustHas", - "mustInitial", - "mustLast", - "mustMerge", - "mustMergeOverwrite", - "mustPrepend", - "mustPush", - "mustRegexFind", - "mustRegexFindAll", - "mustRegexMatch", - "mustRegexReplaceAll", - "mustRegexReplaceAllLiteral", - "mustRegexSplit", - "mustRest", - "mustReverse", - "mustSlice", - "mustToDate", - "mustToJson", - "mustToPrettyJson", - "mustToRawJson", - "mustUniq", - "mustWithout", - "must_date_modify", - "semver", - "semverCompare", - "trimall", +func validHelper(f interface{}) bool { + typ := reflect.TypeOf(f) + if typ.NumOut() != 1 { + return false } - - for _, invalid := range invalids { - if name == invalid { - return true - } + v := reflect.Zero(typ.Out(0)) + switch v.Interface().(type) { + case + bool, + float64, + []int, + int, + int64, + [][]interface{}, + []interface{}, + interface{}, + map[string]interface{}, + map[string]string, + []string, + string, + time.Time: + return true } - return false } diff --git a/template/helpers_test.go b/template/helpers_test.go index b93339d..51a21fb 100644 --- a/template/helpers_test.go +++ b/template/helpers_test.go @@ -69,10 +69,6 @@ func TestNegativeTruncate(t *testing.T) { } } -func TestSince(t *testing.T) { - t.Skip() -} - func TestUppercaseFirst(t *testing.T) { vals := map[string]string{ "hello": "Hello", diff --git a/template/template.go b/template/template.go index f6bf093..a9068ab 100644 --- a/template/template.go +++ b/template/template.go @@ -21,7 +21,7 @@ import ( "net/url" "strings" - "github.com/aymerick/raymond" + "github.com/flowchartsman/handlebars/v3" ) // Render parses and executes a template, returning the results in string @@ -35,7 +35,6 @@ func Render(template string, payload interface{}) (s string, err error) { switch u.Scheme { case "http", "https": res, err := http.Get(template) - if err != nil { return s, fmt.Errorf("failed to fetch: %w", err) } @@ -43,7 +42,6 @@ func Render(template string, payload interface{}) (s string, err error) { defer res.Body.Close() out, err := ioutil.ReadAll(res.Body) - if err != nil { return s, fmt.Errorf("failed to read: %w", err) } @@ -51,7 +49,6 @@ func Render(template string, payload interface{}) (s string, err error) { template = string(out) case "file": out, err := ioutil.ReadFile(u.Path) - if err != nil { return s, fmt.Errorf("failed to read: %w", err) } @@ -60,7 +57,7 @@ func Render(template string, payload interface{}) (s string, err error) { } } - return raymond.Render(template, payload) + return handlebars.Render(template, payload) } // RenderTrim parses and executes a template, returning the results in string