Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 68 additions & 68 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,83 +7,83 @@ rake, gulp.

To install

go get -u gopkg.in/godo.v1/cmd/godo
go get -u gopkg.in/godo.v1/cmd/godo

## Godofile

**godo** runs either `Gododir/Godofile.go` or `tasks/Godofile.go`.
godo requires that the go tool and compiler installed and assumes that a valid `GOPATH` is set.

As an example, create a file **Gododir/Godofile.go** with this content
## Godofile

package main
**godo** runs tasks defined in `Gododir`. The `Gododir` can contain multiple `.go` files which should form a valid go package.

import (
. "gopkg.in/godo.v1"
)
_The legacy `tasks/Godofile.go` is still supported, but not recommended._

func Tasks(p *Project) {
Env = "GOPATH=.vendor::$GOPATH PG_PASSWORD=dev"
As an example, create a file **Gododir/myTasks.go** with this content
```go
package tasks

p.Task("default", D{"hello", "build"})
import (
. "gopkg.in/godo.v1"
)

p.Task("hello", func() {
Bash("echo Hello $USER!")
})
func Tasks(p *Project) {
Env = "GOPATH=.vendor::$GOPATH PG_PASSWORD=dev"

p.Task("build", W{"**/*.go"}, func() {
Run("GOOS=linux GOARCH=amd64 go build", In{"cmd/server"})
})
p.Task("default", D{"hello", "build"})

p.Task("views", W{"templates/**/*.go.html"}, func() {
Run("razor templates")
})
p.Task("hello", func() {
Bash("echo Hello $USER!")
})

p.Task("server", D{"views"}, W{"**/*.go"}, Debounce(3000), func() {
// Start recompiles and restarts on changes when watching
Start("main.go", In{"cmd/server"})
})
}
p.Task("build", W{"**/*.go"}, func() {
Run("GOOS=linux GOARCH=amd64 go build", In{"cmd/server"})
})

func main() {
Godo(Tasks)
}
p.Task("views", W{"templates/**/*.go.html"}, func() {
Run("razor templates")
})

p.Task("server", D{"views"}, W{"**/*.go"}, Debounce(3000), func() {
// Start recompiles and restarts on changes when watching
Start("main.go", In{"cmd/server"})
})
}
```

To run "server" task from parent dir of `tasks/`
To run "server" task from parent dir of `Gododir`

godo server
godo server

To rerun "server" and its dependencies whenever any `*.go.html` or `*.go` file changes

godo server --watch
godo server --watch

To run the "default" task which runs "hello" and "views"

godo
godo

Task names may add a "?" suffix to execute only once even when watching

// build once regardless of number of dependents
p.Task("build?", func() {})
// build once regardless of number of dependents
p.Task("build?", func() {})

Task options

D{} or Dependencies{} - dependent tasks which run before task
Debounce - minimum milliseconds before task can run again
W{} or Watches{} - array of glob file patterns to watch
D{} or Dependencies{} - dependent tasks which run before task
Debounce - minimum milliseconds before task can run again
W{} or Watches{} - array of glob file patterns to watch

/**/ - match zero or more directories
{a,b} - match a or b, no spaces
* - match any non-separator char
? - match a single non-separator char
**/ - match any directory, start of pattern only
/** - match any in this directory, end of pattern only
! - removes files from resultset, start of pattern only
/**/ - match zero or more directories
{a,b} - match a or b, no spaces
* - match any non-separator char
? - match a single non-separator char
**/ - match any directory, start of pattern only
/** - match any in this directory, end of pattern only
! - removes files from resultset, start of pattern only

Task handlers

func() {} - Simple function handler
func(c *Context) {} - Handler which accepts the current context
func() {} - Simple function handler
func(c *Context) {} - Handler which accepts the current context

## Exec functions

Expand All @@ -93,32 +93,32 @@ Bash functions uses the bash executable and may not run on all OS.

Run a bash script string. The script can be multine line with continutation.

Bash(`
echo -n $USER
echo some really long \
command
`)
Bash(`
echo -n $USER
echo some really long \
command
`)

Run a bash script and capture STDOUT and STDERR.

output, err := BashOutput(`echo -n $USER`)
output, err := BashOutput(`echo -n $USER`)

### Run

Run `go build` inside of cmd/app and set environment variables.

Run(`GOOS=linux GOARCH=amd64 go build`, In{"cmd/app"})
Run(`GOOS=linux GOARCH=amd64 go build`, In{"cmd/app"})

Run and capture STDOUT and STDERR

output, err := RunOutput("whoami")
output, err := RunOutput("whoami")

### Start

Start an async command. If the executable has suffix ".go" then it will be "go install"ed then executed.
Use this for watching a server task.

Start("main.go", In{"cmd/app"})
Start("main.go", In{"cmd/app"})

Godo tracks the pid of the `Start` async function to restart an application gracefully.

Expand All @@ -127,33 +127,33 @@ Godo tracks the pid of the `Start` async function to restart an application grac
To run many commands inside a directory, use `Inside` instead of the `In` option.
`Inside` changes the working directory.

Inside("somedir", func() {
Run("...")
Bash("...")
})
Inside("somedir", func() {
Run("...")
Bash("...")
})

## Godofile Run-Time Environment

To specify whether to inherit from parent's process environment,
set `InheritParentEnv`. This setting defaults to true

InheritParentEnv = false
InheritParentEnv = false

To specify the base environment for your tasks, set `Env`.
Separate with whitespace or newlines.

Env = `
GOPATH=.vendor::$GOPATH
PG_USER="developer"
`
Env = `
GOPATH=.vendor::$GOPATH
PG_USER="developer"
`

Functions can add or override environment variables as part of the command string.
Note that environment variables are set before the executable similar to a shell;
however, the `Run` and `Start` functions do not use a shell.

p.Task("build", func() {
Run("GOOS=linux GOARCH=amd64 go build" )
})
p.Task("build", func() {
Run("GOOS=linux GOARCH=amd64 go build" )
})

The effective environment for exec functions is: `parent (if inherited) <- Env <- func parsed env`

Expand Down
108 changes: 108 additions & 0 deletions cmd/godo/legacy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package main

import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"regexp"
"strings"

"github.com/mgutz/str"
"gopkg.in/godo.v1"
"gopkg.in/godo.v1/util"
)

// This file contains support for the legacy `tasks/Godofile.go` tasks definitions file.
// I (GeertJohan) propose to drop legacy support in godo.v2

func hasMain(data []byte) bool {
hasMainRe := regexp.MustCompile(`\nfunc main\(`)
matches := hasMainRe.Find(data)
return len(matches) > 0
}

func isPackageMain(data []byte) bool {
isMainRe := regexp.MustCompile(`(\n|^)?package main\b`)
matches := isMainRe.Find(data)
return len(matches) > 0
}

func runLegacy() (bool, error) {
rel := "tasks/Godofile.go"
filename, err := filepath.Abs(rel)
if err != nil {
panic("Could not get absolute path " + filename)
}
if !util.FileExists(filename) {
return false, nil
}

mainFile := legacyBuildMain(rel)
if mainFile != "" {
filename = mainFile
defer os.RemoveAll(filepath.Dir(mainFile))
}
cmd := "go run " + filename + " " + strings.Join(os.Args[1:], " ")
// errors are displayed by tasks
godo.Run(cmd)

return true, nil
}

func legacyBuildMain(src string) string {
tempFile := ""
data, err := ioutil.ReadFile(src)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}

if !hasMain(data) {
if isPackageMain(data) {
msg := `%s is not runnable. Rename package OR make it runnable by adding

func main() {
godo.Godo(Tasks)
}
`
fmt.Printf(msg, src)
os.Exit(1)
}

template := `package main

import (
"gopkg.in/godo.v1"
tasks "{{package}}"
)

func main() {
godo.Godo(tasks.Tasks)
}
`
packageName, err := util.PackageName(src)
if err != nil {
panic(err)
}
code := str.Template(template, map[string]interface{}{
"package": filepath.ToSlash(packageName),
})
//log.Println("DBG template", code)
tempDir, err := ioutil.TempDir("", "godo")
if err != nil {
panic("Could not create temp directory")
}
//log.Printf("code\n %s\n", code)
tempFile = filepath.Join(tempDir, "Godofile_main.go")
err = ioutil.WriteFile(tempFile, []byte(code), 0644)
if err != nil {
log.Panicf("Could not write temp file %s\n", tempFile)
}

src = tempFile
return src
}
return ""
}
Loading