Categorygithub.com/go-godo/godo
modulepackage
2.0.9+incompatible
Repository: https://github.com/go-godo/godo.git
Documentation: pkg.go.dev

# README

Documentation is WIP

godo

godoc

godo is a task runner and file watcher for golang in the spirit of rake, gulp.

To install

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

Godofile

Godo runs Gododir/main.go.

As an example, create a file Gododir/main.go with this content

package main

import (
    "fmt"
    do "gopkg.in/godo.v2"
)

func tasks(p *do.Project) {
    do.Env = `GOPATH=.vendor::$GOPATH`

    p.Task("default", do.S{"hello", "build"}, nil)

    p.Task("hello", nil, func(c *do.Context) {
        name := c.Args.AsString("name", "n")
        if name == "" {
            c.Bash("echo Hello $USER!")
        } else {
            fmt.Println("Hello", name)
        }
    })

    p.Task("assets?", nil,  func(c *do.Context) {
        // The "?" tells Godo to run this task ONLY ONCE regardless of
        // how many tasks depend on it. In this case watchify watches
        // on its own.
	    c.Run("watchify public/js/index.js d -o dist/js/app.bundle.js")
    }).Src("public/**/*.{css,js,html}")

    p.Task("build", do.S{"views", "assets"}, func(c *do.Context) {
        c.Run("GOOS=linux GOARCH=amd64 go build", do.M{"$in": "cmd/server"})
    }).Src("**/*.go")

    p.Task("server", do.S{"views", "assets"}, func(c *do.Context) {
        // rebuilds and restarts when a watched file changes
        c.Start("main.go", do.M{"$in": "cmd/server"})
    }).Src("server/**/*.go", "cmd/server/*.{go,json}").
       Debounce(3000)

    p.Task("views", nil, func(c *do.Context) {
        c.Run("razor templates")
    }).Src("templates/**/*.go.html")
}

func main() {
    do.Godo(tasks)
}

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

godo server

To rerun "server" and its dependencies whenever any of their watched files change

godo server --watch

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

godo

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

// build once regardless of number of dependents
p.Task("assets?", nil, func(*do.Context) { })

Task dependencies

do.S{} or do.Series{} - dependent tasks to run in series
do.P{} or do.Parallel{} - dependent tasks to run in parallel

For example, do.S{"clean", do.P{"stylesheets", "templates"}, "build"}

Task Option Funcs

  • Task#Src() - specify watch paths or the src files for Task#Dest()

    Glob patterns
    
        /**/   - 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 result set, start of pattern only
    
  • Task#Dest(globs ...string) - If globs in Src are newer than Dest, then the task is run

  • Task#Desc(description string) - Set task's description in usage.

  • Task#Debounce(duration time.Duration) - Disallow a task from running until duration has elapsed.

  • Task#Deps(names ...interface{}) - Can be S, Series, P, Parallel, string

Task CLI Arguments

Task CLI arguments follow POSIX style flag convention (unlike go's built-in flag package). Any command line arguments succeeding -- are passed to each task. Note, arguments before -- are reserved for godo.

As an example,

p.Task("hello", nil, func(c *do.Context) {
    // "(none)" is the default value
    msg := c.Args.MayString("(none)", "message", "msg", "m")
    var name string
    if len(c.Args.NonFlags()) == 1 {
        name = c.Args.NonFlags()[0]
    }
    fmt.Println(msg, name)
})

running

# prints "(none)"
godo hello

# prints "Hello dude" using POSIX style flags
godo hello -- dude --message Hello
godo hello -- dude --msg Hello
godo hello -- -m Hello dude

Args functions are categorized as

  • Must* - Argument must be set by user or panic.

c.Args.MustInt("number", "n")


*  `May*` - If argument is not set, default to first value.

    ```go
// defaults to 100
c.Args.MayInt(100, "number", "n")
  • As* - If argument is not set, default to zero value.

// defaults to 0 c.Args.AsInt("number", "n")



## Modularity and Namespaces

A project may include other tasks functions with `Project#Use`. `Use` requires a namespace to
prevent task name conflicts with existing tasks.

```go
func buildTasks(p *do.Project) {
    p.Task("default", S{"clean"}, nil)

    p.Task("clean", nil, func(*do.Context) {
        fmt.Println("build clean")
    })
}

func tasks(p *do.Project) {
    p.Use("build", buildTasks)

    p.Task("clean", nil, func(*do.Context) {
        fmt.Println("root clean")
    })

    p.Task("build", do.S{"build:default"}, func(*do.Context) {
        fmt.Println("root clean")
    })
}

Running godo build:. or godo build results in output of build clean. Note that it uses the clean task in its namespace not the clean in the parent project.

The special name build:. is alias for build:default.

Task dependencies that start with "/" are relative to the parent project and may be called referenced from sub projects.

godobin

godo compiles Godofile.go to godobin-VERSION (godobin-VERSION.exe on Windows) whenever Godofile.go changes. The binary file is built into the same directory as Godofile.go and should be ignored by adding the path godobin* to .gitignore.

Exec functions

All of these functions accept a map[string]interface{} or M for options. Option keys that start with "$" are reserved for godo. Other fields can be used as context for template.

Bash

Bash functions uses the bash executable and may not run on all OS.

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

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

Bash can use Go templates

c.Bash(`echo -n {{.name}}`, do.M{"name": "mario", "$in": "cmd/bar"})

Run a bash script and capture STDOUT and STDERR.

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

Run

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

c.Run(`GOOS=linux GOARCH=amd64 go build`, do.M{"$in": "cmd/app"})

Run can use Go templates

c.Run(`echo -n {{.name}}`, do.M{"name": "mario", "$in": "cmd/app"})

Run and capture STDOUT and STDERR

output, err := c.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.

c.Start("main.go", do.M{"$in": "cmd/app"})

Godo tracks the process ID of started processes to restart the app gracefully.

Inside

To run many commands inside a directory, use Inside instead of the $in option. Inside changes the working directory.

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

User Input

To get plain string

user := do.Prompt("user: ")

To get password

password := do.PromptPassword("password: ")

Godofile Run-Time Environment

From command-line

Environment variables may be set via key-value pairs as arguments to godo. This feature was added to facilitate users on Windows.

godo NAME=mario GOPATH=./vendor hello

From source code

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

do.InheritParentEnv = false

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

do.Env = `
    GOPATH=.vendor::$GOPATH
    PG_USER=mario
`

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", nil, func(c *do.Context) {
    c.Run("GOOS=linux GOARCH=amd64 go build" )
})

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

Paths should use :: as a cross-platform path list separator. On Windows :: is replaced with ;. On Mac and linux :: is replaced with :.

From godoenv file

For special circumstances where the GOPATH needs to be set before building the Gododir, use Gododir/godoenv file.

TIP: Create Gododir/godoenv when using a dependency manager like godep that necessitates changing $GOPATH

# Gododir/godoenv
GOPATH=$PWD/cmd/app/Godeps/_workspace::$GOPATH

# Packages

No description provided by the author
No description provided by the author
No description provided by the author
Package util contains general purpose utility and logging functions.
Package watcher implements filesystem notification,.

# Functions

Bash executes a bash script (string).
BashOutput executes a bash script and returns the output.
EffectiveEnv is the effective environment for an exec function.
Getenv environment variable from a string array.
GetWatchDelay gets the watch delay.
Godo runs a project of tasks.
GoThrottle starts to run the given list of fns concurrently, at most n fns at a time.
Halt is a soft panic and stops a task.
Inside temporarily changes the working directory and restores it when lambda finishes.
NewProject creates am empty project ready for tasks.
NewTask creates a new Task.
ParseStringEnv parse the package Env string and converts it into an environment slice.
Prompt prompts user for input with default value.
PromptPassword prompts user for password input.
Run runs a command.
RunOutput runs a command and returns output.
SetEnviron sets the environment for child processes.
SetWatchDelay sets the time duration between watches.
Start starts an async command.
Usage prints a usage screen with task descriptions.

# Constants

CaptureBoth captures STDOUT and STDERR.
CaptureStderr is a bitmask to capture STDERR.
CaptureStdout is a bitmask to capture STDOUT.

# Variables

DebounceMs is the default time (1500 ms) to debounce task events in watch mode.
Env is the default environment to use for all commands.
InheritParentEnv whether to inherit parent's environment.
PathListSeparator is a cross-platform path list separator.
Processes are the processes spawned by Start().
Version is the current version.

# Structs

Context is the data passed to a task.
Message are sent on the Events channel.
Project is a container for tasks.
A Task is an operation performed on a user's project directory.
WaitGroupN is a custom wait group that tracks the number added so it can be stopped.

# Interfaces

Dependency marks an interface as a dependency.
Handler is the interface which all task handlers eventually implement.

# Type aliases

HandlerFunc is a Handler adapter.
M is generic string to interface alias.
P is alias for Parallel.
Parallel runs tasks in parallel.
S is alias for Series.
Series are dependent tasks which must run in series.