Documentation ¶
Overview ¶
Package goyek helps implementing task automation.
Example ¶
// Define a task printing a message. hi := goyek.Define(goyek.Task{ Name: "hi", Usage: "Greetings", Action: func(a *goyek.A) { a.Log("Hello world!") }, }) // Define a task running a command. goVer := goyek.Define(goyek.Task{ Name: "go-ver", Usage: `Run "go version"`, Action: func(a *goyek.A) { cmd := exec.CommandContext(a.Context(), "go", "version") cmd.Stdout = a.Output() cmd.Stderr = a.Output() if err := cmd.Run(); err != nil { a.Error(err) } }, }) // Define a pipeline and set it as the default task. all := goyek.Define(goyek.Task{ Name: "all", Deps: goyek.Deps{hi, goVer}, }) goyek.SetDefault(all) // Configure middlewares. goyek.UseExecutor(middleware.ReportFlow) goyek.Use(middleware.ReportStatus) goyek.Use(middleware.BufferParallel) // Run the tasks. tasks := os.Args[1:] goyek.Main(tasks) /* $ go run . ===== TASK hi main.go:15: Hello world! ----- PASS: hi (0.00s) ===== TASK go-ver go version go1.19.2 windows/amd64 ----- PASS: go-ver (0.04s) ===== TASK all ----- NOOP: all (0.00s) ok 0.039s */
Output:
Example (Flag) ¶
// Use the same output for flow and flag. flag.CommandLine.SetOutput(goyek.Output()) // Define a flag to configure flow output verbosity. verbose := flag.Bool("v", true, "print all tasks as they are run") // Define a flag used by a task. msg := flag.String("msg", "hello world", `message to display by "hi" task`) // Define a task printing the message (configurable via flag). goyek.Define(goyek.Task{ Name: "hi", Usage: "Greetings", Action: func(a *goyek.A) { a.Log(*msg) }, }) // Set the help message. usage := func() { fmt.Println("Usage of build: [flags] [--] [tasks]") goyek.Print() fmt.Println("Flags:") flag.PrintDefaults() } // Parse the args. flag.Usage = usage flag.Parse() // Configure middlewares. goyek.UseExecutor(middleware.ReportFlow) goyek.Use(middleware.ReportStatus) if *verbose { goyek.Use(middleware.BufferParallel) } else { goyek.Use(middleware.SilentNonFailed) } // Run the tasks. goyek.SetUsage(usage) goyek.Main(flag.Args()) /* $ go run . no task provided Usage of build: [flags] [--] [tasks] Tasks: hi Greetings Flags: -msg string message to display by "hi" task (default "hello world") -v print all tasks as they are run (default true) exit status 2 */
Output:
Index ¶
- Variables
- func Execute(ctx context.Context, tasks []string, opts ...Option) error
- func Main(args []string, opts ...Option)
- func Output() io.Writer
- func Print()
- func SetDefault(task *DefinedTask)
- func SetLogger(logger Logger)
- func SetOutput(out io.Writer)
- func SetUsage(fn func())
- func Undefine(task *DefinedTask)
- func Usage() func()
- func Use(middlewares ...Middleware)
- func UseExecutor(middlewares ...ExecutorMiddleware)
- type A
- func (a *A) Cleanup(fn func())
- func (a *A) Context() context.Context
- func (a *A) Error(args ...interface{})
- func (a *A) Errorf(format string, args ...interface{})
- func (a *A) Fail()
- func (a *A) FailNow()
- func (a *A) Failed() bool
- func (a *A) Fatal(args ...interface{})
- func (a *A) Fatalf(format string, args ...interface{})
- func (a *A) Helper()
- func (a *A) Log(args ...interface{})
- func (a *A) Logf(format string, args ...interface{})
- func (a *A) Name() string
- func (a *A) Output() io.Writer
- func (a *A) Setenv(key, value string)
- func (a *A) Skip(args ...interface{})
- func (a *A) SkipNow()
- func (a *A) Skipf(format string, args ...interface{})
- func (a *A) Skipped() bool
- func (a *A) TempDir() string
- type CodeLineLogger
- type DefinedTask
- func (r *DefinedTask) Action() func(a *A)
- func (r *DefinedTask) Deps() Deps
- func (r *DefinedTask) Name() string
- func (r *DefinedTask) SetAction(fn func(a *A))
- func (r *DefinedTask) SetDeps(deps Deps)
- func (r *DefinedTask) SetName(s string)
- func (r *DefinedTask) SetUsage(s string)
- func (r *DefinedTask) Usage() string
- type Deps
- type ExecuteInput
- type Executor
- type ExecutorMiddleware
- type FailError
- type Flow
- func (f *Flow) Default() *DefinedTask
- func (f *Flow) Define(task Task) *DefinedTask
- func (f *Flow) Execute(ctx context.Context, tasks []string, opts ...Option) error
- func (f *Flow) Logger() Logger
- func (f *Flow) Main(args []string, opts ...Option)
- func (f *Flow) Output() io.Writer
- func (f *Flow) Print()
- func (f *Flow) SetDefault(task *DefinedTask)
- func (f *Flow) SetLogger(logger Logger)
- func (f *Flow) SetOutput(out io.Writer)
- func (f *Flow) SetUsage(fn func())
- func (f *Flow) Tasks() []*DefinedTask
- func (f *Flow) Undefine(task *DefinedTask)
- func (f *Flow) Usage() func()
- func (f *Flow) Use(middlewares ...Middleware)
- func (f *Flow) UseExecutor(middlewares ...ExecutorMiddleware)
- type FmtLogger
- type Input
- type Logger
- type Middleware
- type Option
- type Result
- type Runner
- type Status
- type Task
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var DefaultFlow = &Flow{}
DefaultFlow is the default flow. The top-level functions such as Define, Main, and so on are wrappers for the methods of Flow.
Functions ¶
func Execute ¶
Execute runs provided tasks and all their dependencies. Each task is executed at most once. Returns nil if no task has failed, *FailError if a task failed, other errors in case of invalid input or context error.
func Main ¶
Main runs provided tasks and all their dependencies. Each task is executed at most once. It exits the current program when after the run is finished or SIGINT interrupted the execution.
- 0 exit code means that non of the tasks failed.
- 1 exit code means that a task has failed or the execution was interrupted.
- 2 exit code means that the input was invalid.
Calls Usage when invalid args are provided.
func Output ¶
Output returns the destination used for printing messages. os.Stdout is returned if output was not set or was set to nil.
func Print ¶
func Print()
Print prints the information about the registered tasks. Tasks with empty [Task.Usage] are not printed.
func SetDefault ¶
func SetDefault(task *DefinedTask)
SetDefault sets a task to run when none is explicitly provided. It panics in case of any error.
func SetLogger ¶
func SetLogger(logger Logger)
SetLogger sets the logger used by A's logging functions.
A uses following methods if implemented:
Error(w io.Writer, args ...interface{}) Errorf(w io.Writer, format string, args ...interface{}) Fatal(w io.Writer, args ...interface{}) Fatalf(w io.Writer, format string, args ...interface{}) Skip(w io.Writer, args ...interface{}) Skipf(w io.Writer, format string, args ...interface{}) Helper()
func SetUsage ¶
func SetUsage(fn func())
SetUsage sets the function called when an error occurs while parsing tasks.
func Undefine ¶
func Undefine(task *DefinedTask)
Undefine unregisters the task. It panics in case of any error.
func Usage ¶
func Usage() func()
Usage returns a function that prints a usage message documenting the flow. It is called when an error occurs while parsing the flow. Print is returned if a function was not set or was set to nil.
func UseExecutor ¶ added in v2.2.0
func UseExecutor(middlewares ...ExecutorMiddleware)
UseExecutor adds flow executor middlewares (interceptors).
Types ¶
type A ¶
type A struct {
// contains filtered or unexported fields
}
A is a type passed to [Task.Action] functions to manage task state and support formatted task logs.
A task ends when its action function returns or calls any of the methods FailNow, Fatal, Fatalf, SkipNow, Skip, or Skipf. Those methods must be called only from the goroutine running the action function.
The other reporting methods, such as the variations of Log and Error, may be called simultaneously from multiple goroutines.
func (*A) Cleanup ¶
func (a *A) Cleanup(fn func())
Cleanup registers a function to be called when [Task.Action] function completes. Cleanup functions will be called in the last-added first-called order.
func (*A) Fail ¶
func (a *A) Fail()
Fail marks the function as having failed but continues execution.
func (*A) FailNow ¶
func (a *A) FailNow()
FailNow marks the function as having failed and stops its execution by calling runtime.Goexit (which then runs all deferred calls in the current goroutine). It finishes the whole flow execution. FailNow must be called from the goroutine running the [Task.Action] function, not from other goroutines created during its execution. Calling FailNow does not stop those other goroutines.
func (*A) Helper ¶
func (a *A) Helper()
Helper marks the calling function as a helper function. It calls logger's Helper method if implemented. By default, when printing file and line information, that function will be skipped.
func (*A) Log ¶
func (a *A) Log(args ...interface{})
Log formats its arguments using default formatting, analogous to Println, and writes the text to A.Output. A final newline is added.
func (*A) Logf ¶
Logf formats its arguments according to the format, analogous to Printf, and writes the text to A.Output. A final newline is added.
func (*A) Setenv ¶
Setenv calls os.Setenv(key, value) and uses Cleanup to restore the environment variable to its original value after the action.
func (*A) SkipNow ¶
func (a *A) SkipNow()
SkipNow marks the task as having been skipped and stops its execution by calling runtime.Goexit (which then runs all deferred calls in the current goroutine). If a test fails (see Error, Errorf, Fail) and is then skipped, it is still considered to have failed. The flow execution will continue at the next task. See also A.FailNow. SkipNow must be called from the goroutine running the [Task.Action] function, not from other goroutines created during its execution. Calling SkipNow does not stop those other goroutines.
type CodeLineLogger ¶
type CodeLineLogger struct {
// contains filtered or unexported fields
}
CodeLineLogger decorates the log with code line information and indentation.
func (*CodeLineLogger) Helper ¶
func (l *CodeLineLogger) Helper()
Helper marks the calling function as a helper function. When printing file and line information, that function will be skipped. Helper may be called simultaneously from multiple goroutines.
type DefinedTask ¶
type DefinedTask struct {
// contains filtered or unexported fields
}
DefinedTask represents a task that has been defined. It can be used as a dependency for another task.
func Default ¶
func Default() *DefinedTask
Default returns the default task. nil is returned if default was not set.
func Define ¶
func Define(task Task) *DefinedTask
Define registers the task. It panics in case of any error.
func (*DefinedTask) Action ¶
func (r *DefinedTask) Action() func(a *A)
Action returns the action of the task.
func (*DefinedTask) SetAction ¶
func (r *DefinedTask) SetAction(fn func(a *A))
SetAction changes the action of the task.
func (*DefinedTask) SetDeps ¶
func (r *DefinedTask) SetDeps(deps Deps)
SetDeps sets all task's dependencies.
func (*DefinedTask) SetName ¶
func (r *DefinedTask) SetName(s string)
SetName changes the name of the task.
func (*DefinedTask) SetUsage ¶
func (r *DefinedTask) SetUsage(s string)
SetUsage sets the description of the task.
func (*DefinedTask) Usage ¶
func (r *DefinedTask) Usage() string
Usage returns the description of the task.
type ExecuteInput ¶ added in v2.2.0
type ExecuteInput struct { Context context.Context Tasks []string SkipTasks []string NoDeps bool Output io.Writer Logger Logger }
ExecuteInput received by the flow executor.
type Executor ¶ added in v2.2.0
type Executor func(ExecuteInput) error
Executor represents a flow execution function.
type ExecutorMiddleware ¶ added in v2.2.0
ExecutorMiddleware represents a flow execution interceptor.
type FailError ¶
type FailError struct {
Task string
}
FailError pointer is returned by Flow.Execute when a task failed.
type Flow ¶
type Flow struct {
// contains filtered or unexported fields
}
Flow is the root type of the package. Use Register methods to register all tasks and Run or Main method to execute provided tasks.
func (*Flow) Default ¶
func (f *Flow) Default() *DefinedTask
Default returns the default task. nil is returned if default was not set.
func (*Flow) Define ¶
func (f *Flow) Define(task Task) *DefinedTask
Define registers the task. It panics in case of any error.
func (*Flow) Execute ¶
Execute runs provided tasks and all their dependencies. Each task is executed at most once. Returns nil if no task has failed, *FailError if a task failed, other errors in case of invalid input or context error.
func (*Flow) Logger ¶
Logger returns the logger used by A's logging functions CodeLineLogger is returned if logger was not set or was set to nil.
func (*Flow) Main ¶
Main runs provided tasks and all their dependencies. Each task is executed at most once. It exits the current program when after the run is finished or SIGINT interrupted the execution.
- 0 exit code means that non of the tasks failed.
- 1 exit code means that a task has failed or the execution was interrupted.
- 2 exit code means that the input was invalid.
Calls Usage when invalid args are provided.
func (*Flow) Output ¶
Output returns the destination used for printing messages. os.Stdout is returned if output was not set or was set to nil.
func (*Flow) Print ¶
func (f *Flow) Print()
Print prints the information about the registered tasks. Tasks with empty [Task.Usage] are not printed.
func (*Flow) SetDefault ¶
func (f *Flow) SetDefault(task *DefinedTask)
SetDefault sets a task to run when none is explicitly provided. Passing nil clears the default task. It panics in case of any error.
func (*Flow) SetLogger ¶
SetLogger sets the logger used by A's logging functions.
A uses following methods if implemented:
Error(w io.Writer, args ...interface{}) Errorf(w io.Writer, format string, args ...interface{}) Fatal(w io.Writer, args ...interface{}) Fatalf(w io.Writer, format string, args ...interface{}) Skip(w io.Writer, args ...interface{}) Skipf(w io.Writer, format string, args ...interface{}) Helper()
func (*Flow) SetUsage ¶
func (f *Flow) SetUsage(fn func())
SetUsage sets the function called when an error occurs while parsing tasks.
func (*Flow) Tasks ¶
func (f *Flow) Tasks() []*DefinedTask
Tasks returns all tasks sorted in lexicographical order.
func (*Flow) Undefine ¶
func (f *Flow) Undefine(task *DefinedTask)
Undefine unregisters the task. It panics in case of any error.
func (*Flow) Usage ¶
func (f *Flow) Usage() func()
Usage returns a function that prints a usage message documenting the flow. It is called when an error occurs while parsing the flow. Flow.Print is returned if a function was not set or was set to nil.
func (*Flow) Use ¶
func (f *Flow) Use(middlewares ...Middleware)
Use adds task runner middlewares (interceptors).
func (*Flow) UseExecutor ¶ added in v2.2.0
func (f *Flow) UseExecutor(middlewares ...ExecutorMiddleware)
Use adds flow executor middlewares (interceptors).
type FmtLogger ¶
type FmtLogger struct{}
FmtLogger uses fmt when logging. It only appends a new line at the end.
type Input ¶
type Input struct { Context context.Context TaskName string Parallel bool Output io.Writer Logger Logger }
Input received by the task runner.
type Logger ¶
type Logger interface { Log(w io.Writer, args ...interface{}) Logf(w io.Writer, format string, args ...interface{}) }
Logger is used by A's logging functions.
func GetLogger ¶
func GetLogger() Logger
GetLogger returns the logger used by A's logging functions CodeLineLogger is returned if logger was not set or was set to nil.
type Middleware ¶
Middleware represents a task runner interceptor.
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option configures the flow execution.
type Runner ¶
Runner represents a task runner function.
func NewRunner ¶
NewRunner returns a task runner used by Flow.
It can be useful for testing and debugging a task action or middleware.
The following defaults are set for Input (take notice that they are different than Flow defaults):
Context = context.Background() Output = ioutil.Discard Logger = FmtLogger{}
It can be also used as a building block for a custom workflow runner if you are missing any functionalities provided by Flow (like concurrent dependencies execution).
type Task ¶
type Task struct { // Name uniquely identifies the task. // It cannot be empty and should be easily representable on the CLI. Name string // Usage provides information what the task does. Usage string // Action is function that is called when the task is run. // A task can have only dependencies and no action to act as a pipeline. Action func(a *A) // Deps is a collection of defined tasks // that need to be run before this task is executed. Deps Deps // Parallel marks that this task can be run in parallel // with (and only with) other parallel tasks. Parallel bool }
Task represents a named task that can have action and dependencies.
Source Files ¶
Directories ¶
Path | Synopsis |
---|---|
Package middleware provides reusable task runner interceptors such as ReportStatus.
|
Package middleware provides reusable task runner interceptors such as ReportStatus. |