Skip to content

Commit

Permalink
Add text/template (#29)
Browse files Browse the repository at this point in the history
* Add text/template

* Simplify templating command

* Update command
  • Loading branch information
rdsubhas authored Dec 19, 2016
1 parent 0fa4e86 commit 55e76f2
Show file tree
Hide file tree
Showing 15 changed files with 110 additions and 68 deletions.
3 changes: 2 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ install:
- godep restore -v
- godep get -v github.com/onsi/ginkgo/ginkgo
script:
- bin/cross-compile.sh
- ginkgo -r -v --trace --keepGoing
- bin/cross-compile.sh "$TRAVIS_TAG-$TRAVIS_COMMIT"
deploy:
provider: releases
skip_cleanup: true
Expand Down
18 changes: 14 additions & 4 deletions Godeps/Godeps.json

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

6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ You can pass task parameters like:
* Environment variables can be defined in the yml or included from dotenv files, and can be overridden from the shell
* Runtime parameters like `myke ...task[key1=val1, key2=val2, ...]`
* One YML can mixin another YML, acquiring all tasks, env, env files, PATH defaults, etc, and can override all of them
* Built-in templating using [Pongo2](https://github.com/flosch/pongo2) for tasks as well as custom files, because templating is a basic necessity
* Built-in templating using golang text/template and 50+ functions provided by [sprig](https://github.com/Masterminds/sprig)
* Other commands can run other tasks in `before/after` hooks, and they are chained with mixins

## Installation
Expand All @@ -62,8 +62,8 @@ Explore the self documenting `examples` folder.
* So, if you mixin `<some-other-folder>/myke.yml`, then that yml's `cwd/bin` is also added to the PATH, that yml's env/env_files/env_files.local are also loaded, and so on
* shell exported environment variables take precedence
* additional variables: `MYKE_PROJECT`, `MYKE_TASK`, `MYKE_CWD` are set
* command is templated using [pongo2](https://github.com/flosch/pongo2)
* `env` and `args` are passed as variables
* command is templated using golang text/template and sprig
* environment and task arguments are passed in as variables
* command is run using `sh -exc`

## FAQs
Expand Down
12 changes: 8 additions & 4 deletions bin/cross-compile.sh
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
#!/usr/bin/env bash
#Usage: build.sh <version>
set -ex

# Run tests
ginkgo -r -v --trace --keepGoing
# Prepare tmp folder
rm -rf tmp
mkdir -p tmp

# Insert version
version=${1?"version is required"}
echo $version >> "tmp/version"

# Generate license notices
deps="github.com/goeuro/myke $(go list -f '{{ join .Deps "\n"}}' . | grep -v 'goeuro/myke')"
rm -rf tmp
mkdir -p tmp
out="tmp/LICENSES"
echo -e "OPEN SOURCE LICENSES\n" > $out

Expand Down
6 changes: 0 additions & 6 deletions cmd/license.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,6 @@ import (
"fmt"
)

var LicenseCmd = cli.Command{
Name: "license",
Usage: "prints licenses",
Action: License,
}

func License(c *cli.Context) error {
data, err := core.Asset("tmp/LICENSES")
if err != nil {
Expand Down
6 changes: 0 additions & 6 deletions cmd/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,6 @@ import (
"strings"
)

var ListCmd = cli.Command{
Name: "list",
Usage: "list available tasks",
Action: List,
}

func List(c *cli.Context) error {
w := loadWorkspace(c.String("file"))
table := tablewriter.NewWriter(os.Stdout)
Expand Down
14 changes: 12 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,27 @@ import (
"gopkg.in/urfave/cli.v1"
"github.com/goeuro/myke/core"
"path/filepath"
"strings"
"os"
)

func RunOrList(c *cli.Context) error {
if c.NArg() > 0 {
func Action(c *cli.Context) error {
if len(c.String("template")) > 0 {
return Template(c)
} else if c.Bool("license") {
return License(c)
} else if c.NArg() > 0 {
return Run(c)
} else {
return List(c)
}
}

func Version() string {
version, _ := core.Asset("tmp/version")
return strings.TrimSpace(string(version))
}

func loadWorkspace(path string) core.Workspace {
if !filepath.IsAbs(path) {
cwd, _ := os.Getwd()
Expand Down
6 changes: 0 additions & 6 deletions cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@ import (
"log"
)

var RunCmd = cli.Command{
Name: "run",
Usage: "query to execute of format tag1/tag2/project/task[arg1=val1,arg2=val2,...]",
Action: Run,
}

func Run(c *cli.Context) error {
qs := make([]string, len(c.Args()))
for i, v := range c.Args() {
Expand Down
8 changes: 1 addition & 7 deletions cmd/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,8 @@ import (
"io/ioutil"
)

var TemplateCmd = cli.Command{
Name: "template",
Usage: "render a template file with environment variables",
Action: Template,
}

func Template(c *cli.Context) error {
bytes, err := ioutil.ReadFile(c.Args().First())
bytes, err := ioutil.ReadFile(c.String("template"))
if err != nil {
log.Fatal(err)
}
Expand Down
25 changes: 24 additions & 1 deletion core/bindata.go

Large diffs are not rendered by default.

37 changes: 21 additions & 16 deletions core/template.go
Original file line number Diff line number Diff line change
@@ -1,32 +1,37 @@
package core

import (
"github.com/flosch/pongo2"
"strings"
"github.com/Masterminds/sprig"
"text/template"
"errors"
"bytes"
"fmt"
)

func RenderTemplate(tmpl string, env map[string]string, args map[string]string) (string, error) {
tpl, err := pongo2.FromString(tmpl)
if err != nil {
return "", err
w := new(bytes.Buffer)
params := union(env, args)
funcs := template.FuncMap{
"required": templateRequired,
}

out, err := tpl.Execute(pongo2.Context{"env":env, "args":args})
tpl, err := template.New("test").
Funcs(sprig.TxtFuncMap()).
Funcs(funcs).
Option("missingkey=zero").
Parse(tmpl)
if err != nil {
return "", err
} else {
return out, nil
}

err = tpl.Execute(w, params)
return w.String(), err
}

func filterRequired(in *pongo2.Value, param *pongo2.Value) (out *pongo2.Value, err *pongo2.Error) {
if len(strings.TrimSpace(in.String())) == 0 {
return in, &(pongo2.Error{Sender: "filter:required", ErrorMsg: "required parameter missing"})
func templateRequired(s string) (interface{}, error) {
if len(s) > 0 {
return s, nil
} else {
return in, nil
return s, errors.New(fmt.Sprintf("variable not provided to template"))
}
}

func init() {
pongo2.RegisterFilter("required", filterRequired)
}
11 changes: 11 additions & 0 deletions core/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ func mergeEnv(first map[string]string, next map[string]string) map[string]string
return first
}

func union(first map[string]string, next map[string]string) map[string]string {
res := make(map[string]string)
for k, v := range first {
res[k] = v
}
for k, v := range next {
res[k] = v
}
return res
}

func normalizeEnvPaths(cwd string, paths string) string {
newPaths := []string{}
for _, path := range strings.Split(strings.TrimSpace(paths), PathSep) {
Expand Down
4 changes: 2 additions & 2 deletions examples/template/myke.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ env:
PARAM2: value2
tasks:
args:
cmd: echo {{args.from|required}} {{args.to|default:"something_to"}}
cmd: echo {{.from|required}} {{.to|default "something_to"}}
desc: run as myke template/args[from=...,to=...]
file:
cmd: myke template template.tpl
cmd: myke --template template.tpl
desc: run as myke template/file
4 changes: 2 additions & 2 deletions examples/template/template.tpl
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
I am a template.
PARAM1={{env.PARAM1}}
PARAM2={{env.PARAM2}}
PARAM1={{.PARAM1}}
PARAM2={{.PARAM2}}
18 changes: 10 additions & 8 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,23 @@ import (
func main() {
app := cli.NewApp()
app.Name = "myke"
app.Version = "0.3.2"
app.Version = cmd.Version()
app.Usage = "make with yml"
app.Action = cmd.RunOrList
app.Action = cmd.Action
app.Flags = []cli.Flag {
cli.StringFlag{
Name: "f, file",
Value: "myke.yml",
Usage: "`yml-file` to load",
},
}
app.Commands = []cli.Command{
cmd.ListCmd,
cmd.RunCmd,
cmd.TemplateCmd,
cmd.LicenseCmd,
cli.StringFlag{
Name: "template",
Usage: "render template `tpl-file` (will not run any command)",
},
cli.BoolFlag{
Name: "license",
Usage: "show license",
},
}
if err := app.Run(os.Args); err != nil {
log.Fatal(err)
Expand Down

0 comments on commit 55e76f2

Please sign in to comment.