package task
import "github.com/amonks/run/task"
Example (BringYourOwnTasks)
In this example, we generate our own Task and run it.
package main import ( "context" "fmt" "io" "log" "strings" "time" "github.com/amonks/run/task" ) func main() { tasks := task.NewLibrary( task.FuncTask(func(ctx context.Context, onReady chan<- struct{}, w io.Writer) error { w.Write([]byte("sleep")) time.Sleep(1 * time.Second) w.Write([]byte("done")) close(onReady) return nil }, task.TaskMetadata{ID: "custom", Type: "short"}), ) ids := tasks.IDs() if len(ids) != 1 { log.Fatal("expected 1 task") } fmt.Println(strings.Join(ids, ", ")) }
Output:
custom
Index
-
type Library
- func NewLibrary(tasks ...Task) Library
- func (lib Library) Get(id string) Task
- func (lib Library) Has(id string) bool
- func (lib Library) HasWatch(path string) bool
- func (lib Library) IDs() []string
- func (lib Library) LongestID() int
- func (lib Library) Size() int
- func (lib Library) Subtree(ids ...string) Library
- func (lib Library) Validate() error
- func (lib Library) ValidateWithCWD(cwd string) error
- func (lib Library) Watches() []string
- func (lib Library) WithDependency(dep string) []string
- func (lib Library) WithTrigger(trigger string) []string
- func (lib Library) WithWatch(path string) []string
- type Task
- type TaskMetadata
Examples
Types
type Library
type Library struct { // contains filtered or unexported fields }
Library is an opaque data structure representing an immutable, ordered collection of [Task]s. You can create a [runner.Run] by passing a Library into [runner.New].
func NewLibrary
func NewLibrary(tasks ...Task) Library
NewLibrary creates a Library from the given tasks.
func (Library) Get
func (lib Library) Get(id string) Task
Get looks up a specific task by its ID. If no task bearing that ID is present, the task will be nil.
func (Library) Has
func (lib Library) Has(id string) bool
Has returns true if the given ID is present among the Library.
func (Library) HasWatch
func (lib Library) HasWatch(path string) bool
HasWatch returns true if any task in the Library watches the given path.
func (Library) IDs
func (lib Library) IDs() []string
IDs returns the task IDs in their canonical order.
func (Library) LongestID
func (lib Library) LongestID() int
LongestID returns the length of the longest task ID.
func (Library) Size
func (lib Library) Size() int
Size returns the number of tasks in the Library.
func (Library) Subtree
func (lib Library) Subtree(ids ...string) Library
Subtree returns a new Library containing only the given task IDs and their transitive dependencies and triggers, preserving the canonical order from the original Library.
func (Library) Validate
func (lib Library) Validate() error
Validate inspects a Library and returns an error if it is invalid. If the error is not nil, its [error.Error] will return a formatted multiline string describing the problems with the task set.
func (Library) ValidateWithCWD
func (lib Library) ValidateWithCWD(cwd string) error
ValidateWithCWD inspects a Library and returns an error if it is invalid, using the given working directory for path validation.
func (Library) Watches
func (lib Library) Watches() []string
Watches returns a sorted slice of unique watched paths across all tasks.
func (Library) WithDependency
func (lib Library) WithDependency(dep string) []string
WithDependency returns the IDs of tasks that list dep as a dependency.
func (Library) WithTrigger
func (lib Library) WithTrigger(trigger string) []string
WithTrigger returns the IDs of tasks that list trigger as a trigger.
func (Library) WithWatch
func (lib Library) WithWatch(path string) []string
WithWatch returns the IDs of tasks that watch the given path.
type Task
type Task interface { // Start runs the task. It should write output to stdout and close // onReady when the task is ready (i.e., has produced whatever output // dependents need). For short tasks, close onReady on successful // completion. For long tasks, close onReady as soon as the task is // serving / ready. Start(ctx context.Context, onReady chan<- struct{}, stdout io.Writer) error Metadata() TaskMetadata }
Anything implementing Task can be run by bundling it into a Library and then passing it into [runner.New].
ScriptTask and FuncTask can be used to create Tasks.
A Task must be safe to access concurrently from multiple goroutines.
func FuncTask
func FuncTask(fn func(ctx context.Context, onReady chan<- struct{}, w io.Writer) error, metadata TaskMetadata) Task
FuncTask produces a runnable Task from a go function. The function receives an onReady channel that it should close when it is ready (i.e., has produced whatever output dependents need). metadata.Dir is ignored.
func ScriptTask
func ScriptTask(scriptText string, dir string, env []string, metadata TaskMetadata) Task
ScriptTask produces a runnable Task from a bash script and working directory. The script will execute in metadata.Dir. The script's Stdout and Stderr will be provided by the Run, and will be forwarded to the UI. The script will not get a Stdin.
Script runs in a new bash process, and can have multiple lines. It is run basically like this:
$ cd $DIR $ bash -c "$CMD" 2&>1 /some/ui
type TaskMetadata
type TaskMetadata struct { // ID identifies a task, for example, // - for command line invocation, as in `$ run <id>` // - in the TUI's task list. ID string // Description optionally provides additional information about a task, // which can be displayed, for example, by running `run -list`. It can // be one line or many lines. Description string // Type specifies how we manage a task. // // If the Type is "long", // - We will keep the task alive by restarting it if it exits. // - If the long task A is a dependency of task B, we will begin B as // soon as A starts. // - It is invalid to use a long task as a trigger, since long tasks // aren't expected to end. // // If the Type is "short", // - If the Start returns nil, we will consider it done. // - If the Start returns an error, we will wait 1 second and rerun it. // - If the short task A is a dependency or trigger of task B, we will // wait for A to complete before starting B. // // Any Type besides "long" or "short" is invalid. There is no default // type: every task must specify its type. Type string // Dependencies are other tasks IDs which should always run alongside // this task. If a task A lists B as a dependency, running A will first // run B. // // Dependencies do not set up an invalidation relationship: if long // task A lists short task B as a dependency, and B reruns because a // watched file is changed, we will not restart A, assuming that A has // its own mechanism for detecting file changes. If A does not have // such a mechanism, use a trigger rather than a dependency. // // Dependencies can be task IDs from child directories. For example, // the dependency "css/build" specifies the task with ID "build" in the // tasks file "./css/tasks.toml". // // If a task depends on a "long" task, the dependent is started once // the long task signals readiness by closing its onReady channel. Dependencies []string // Triggers are other task IDs which should always be run alongside // this task, and whose success should cause this task to re-execute. // If a task A lists B as a dependency, and both A and B are running, // successful execution of B will always trigger an execution of A. // // Triggers can be task IDs from child directories. For example, the // trigger "css/build" specifies the task with ID "build" in the tasks // file "./css/tasks.toml". // // It is invalid to use a "long" task as a trigger. Triggers []string // Watch specifies file paths where, if a change to // the file path is detected, we should restart the // task. Watch supports globs, and does **not** // support the "./..." style used typical of Go // command line tools. // // For example, // - `"."` watches for changes to the working // directory only, but not changes within // subdirectories. // - `"**" watches for changes at any level within // the working directory. // - `"./some/path/file.txt"` watches for changes // to the file, which must already exist. // - `"./src/website/**/*.js"` watches for changes // to javascript files within src/website. Watch []string }
TaskMetadata contains the data which, regardless of the type of Task, a [runner.Run] uses for task execution.