goyek
Create build pipelines in Go
Table of Contents:
Description
goyek is used to create build pipelines in Go. As opposed to many other tools, it is just a Go library.
Here are some good parts:
- No binary installation is needed. Simply add it to
go.mod
like any other Go module.- You can be sure that everyone uses the same version of goyek.
- It has low learning curve, thanks to the minimal API surface, documentation, and examples.
- One can reuse code like in any Go application. It may be helpful to use packages like:
- It is easy to debug, like a regular Go application.
- The API is based on testing. The task's command look like a unit test. It is even possible to use testify for asserting.
- Tasks and helpers can be easily tested. See exec_test.go.
goyek API is mainly inspired by the http, testing, and flag packages.
Please Star
this repository if you find it valuable and worth maintaining.
Quick start
Copy and paste the following code into build/build.go
:
package main
import "github.com/goyek/goyek"
func main() {
flow := &goyek.Taskflow{}
hello := flow.Register(taskHello())
fmt := flow.Register(taskFmt())
flow.Register(goyek.Task{
Name: "all",
Usage: "build pipeline",
Deps: goyek.Deps{
hello,
fmt,
},
})
flow.Main()
}
func taskHello() goyek.Task {
return goyek.Task{
Name: "hello",
Usage: "demonstration",
Command: func(tf *goyek.TF) {
tf.Log("Hello world!")
},
}
}
func taskFmt() goyek.Task {
return goyek.Task{
Name: "fmt",
Usage: "go fmt",
Command: goyek.Exec("go", "fmt", "./..."),
}
}
Run:
go mod tidy
Sample usage:
$ go run ./build -h
Usage: [flag(s) | task(s)]...
Flags:
-v Default: false Verbose output: log all tasks as they are run. Also print all text from Log and Logf calls even if the task succeeds.
Tasks:
all build pipeline
fmt go fmt
hello demonstration
$ go run ./build all
ok 0.167s
$ go run ./build all -v
===== TASK hello
Hello world!
----- PASS: hello (0.00s)
===== TASK fmt
Cmd: go fmt ./...
----- PASS: fmt (0.18s)
ok 0.183s
Tired of writing go run ./build
each time? Just add an alias to your shell. For example, add the line below to ~/.bash_aliases
:
alias goyek='go run ./build'
Examples
- examples
- build/build.go - this repository's own build pipeline
Features
Task registration
The registered tasks are required to have a non-empty name, matching the regular expression ^[a-zA-Z0-9_][a-zA-Z0-9_-]*$
, available as TaskNamePattern
. This means the following are acceptable:
- letters (
a-z
andA-Z
) - digits (
0-9
) - underscore (
_
) - hyphens (
-
) - except at the beginning
A task with a given name can be only registered once.
A task without description is not listed in CLI usage.
Task command
Task command is a function which is executed when a task is executed. It is not required to to set a command. Not having a command is very handy when registering "pipelines".
Task dependencies
During task registration it is possible to add a dependency to an already registered task. When taskflow is processed, it makes sure that the dependency is executed before the current task is run. Take note that each task will be executed at most once.
Helpers for running programs
Use func Exec(name string, args ...string) func(*TF)
to create a task's command which only runs a single program.
Use func (tf *TF) Cmd(name string, args ...string) *exec.Cmd
if within a task's command function when you want to execute more programs or you need more granular control.
Verbose mode
Enable verbose output using the -v
CLI flag. It works similar to go test -v
. Verbose mode streams all logs to the output. If it is disabled, only logs from failed task are send to the output.
Use func (f *Taskflow) VerboseParam() BoolParam
if you need to check if verbose mode was set within a task's command.
Default task
Default task can be assigned via the Taskflow.DefaultTask
field.
When the default task is set, then it is run if no task is provided via CLI.
Parameters
The parameters can be set via CLI using the flag syntax.
On the CLI, flags can be set in the following ways:
-param simple
- for simple single-word values-param "value with blanks"
-param="value with blanks"
-param
- setting boolean parameters implicitly totrue
For example, go run ./build test -v -pkg ./...
would run the test
task with v
bool parameter (verbose mode) set to true
, and pkg
string parameter set to "./..."
.
Parameters must first be registered via func (f *Taskflow) RegisterValueParam(newValue func() ParamValue, info ParamInfo) ValueParam
, or one of the provided methods like RegisterStringParam
.
The registered parameters are required to have a non-empty name, matching the regular expression ^[a-zA-Z0-9][a-zA-Z0-9_-]*$
, available as ParamNamePattern
. This means the following are acceptable:
- letters (
a-z
andA-Z
) - digits (
0-9
) - underscore (
_
) - except at the beginning - hyphens (
-
) - except at the beginning
After registration, tasks need to specify which parameters they will read. Do this by assigning the RegisteredParam
instance from the registration result to the Task.Params
field. If a task tries to retrieve the value from an unregistered parameter, the task will fail.
When registration is done, the task's command can retrieve the parameter value using the Get(*TF)
method from the registration result instance during the task's Command
execution.
See examples/parameters/main.go for a detailed example.
Taskflow
will fail execution if there are unused parameters.
Supported Go versions
Minimal supported Go version is 1.11.
Alternatives
Make
While Make is currently the de facto standard, it has some pitfalls:
- Requires to learn Make, which is not so easy.
- It is hard to develop a Makefile which is truly cross-platform.
- Debugging and testing Make targets is not fun.
However, if you know Make and are happy with it, do not change it. Make is very powerful and a lot of stuff can be made faster, if you know how to use it.
goyek is intended to be simpler and easier to learn, while still being able to handle most use cases.
Mage
Mage is a framework/tool which magically discovers the targets from magefiles, which results in some drawbacks:
- Requires using build tags.
- Reusing tasks is hacky.
- Requires installation or using zero install option which is slow.
- Debugging would be extermly complex.
- Magical by design (of course one may like it).
goyek is intended to be a non-magical alternative for Mage. Write regular Go code. No build tags, special names for functions, tricky imports.
Task
While Task is simpler and easier to use than Make it still has similar problems:
- Requires to learn Task's YAML structure and the minimalistic, cross-platform interpreter which it uses.
- Debugging and testing tasks is not fun.
- Hard to make reusable tasks.
- Requires to "install" the tool.
Bazel
Bazel is a very sophisticated tool which is created to efficiently handle complex and long-running build pipelines. It requires the build target inputs and outputs to be fully specified.
goyek is just a simple library that is mainly supposed to create a build pipeline consisting of commands like go vet
, go test
, go build
. However, take notice that goyek is a library. Nothing prevents you from, for example, using Mage's target package to make your build pipeline more efficient.
Presentations
Date | Presentation | Description |
---|---|---|
2021-05-05 | goyek - Create build pipelines in Go | goyek v0.3.0 demo |
2021-03-10 | taskflow - Create build pipelines in Go | taskflow v0.1.1 demo |
2020-12-14 | Build pipeline for a Go project | build pipeline using Make, Mage, and taskflow v0.1.0 |
Note: goyek was named taskflow before v0.3.0.
Contributing
We are open to any feedback and contribution.
You can find us on Gophers Slack in #goyek
channel.
Feel free to create an issue, or a pull request.
You may use Gitpod to experiment with the codebase.