package runner
import "github.com/amonks/run/runner"
Package runner executes a collection of tasks with dependency management, file watching, and process lifecycle control.
Conceptual Overview
1. You call [taskfile.Load] to parse task files and get a task.Library.
- You can also generate your own task set, or append your own tasks onto it.
- Tasks just implement an interface.
2. You combine a task library with an ID to get a Run using New. 3. You pass a UI into a Run and Start it.
- You can also make your own UI.
- You can also use a Run UI with any other collection of processes that expect io.Writers.
Example
In this example, we use components from Run to build our own version of the run CLI tool. See the root package for the source of the -real- run CLI, which isn't too much more complex.
package main import ( "context" "os" "github.com/amonks/run/runner" "github.com/amonks/run/taskfile" "github.com/amonks/run/tui" ) func main() { tasks, _ := taskfile.Load(".") r, _ := runner.New(".", tasks, "dev") ui := tui.New(r) ctx := context.Background() uiReady := make(chan struct{}) go ui.Start(ctx, uiReady, os.Stdin, os.Stdout) <-uiReady r.Start(ctx, ui) // blocks until done }
Example (BringYourOwnUI)
In this example, we build a version of the run CLI tool that uses a UI we provide ourselves.
package main import ( "context" "io" "log" "os" "github.com/amonks/run/runner" "github.com/amonks/run/taskfile" ) // ui implements MultiWriter var _ runner.MultiWriter = ui{} type ui struct{} func (w ui) Writer(string) io.Writer { return os.Stdout } // In this example, we build a version of the run CLI tool that uses a UI we // provide ourselves. func main() { tasks, err := taskfile.Load(".") if err != nil { log.Fatal(err) } run, err := runner.New(".", tasks, "dev") if err != nil { log.Fatal(err) } ui := ui{} if err := run.Start(context.Background(), ui); err != nil { log.Fatal(err) } }
Index
- Constants
- Variables
- func StripANSIEscapeCodes(s string) string
- type MultiWriter
-
type Run
- func New(dir string, allTasks task.Library, taskID string) (*Run, error)
- func (r *Run) Add(ids ...string)
- func (r *Run) IDs() []string
- func (r *Run) Invalidate(id string)
- func (r *Run) Remove(id string)
- func (r *Run) Start(ctx context.Context, out MultiWriter) error
- func (r *Run) TaskStatus(id string) TaskStatus
- func (r *Run) Tasks() task.Library
- func (r *Run) Type() RunType
- type RunType
- type TaskStatus
- type UI
Examples
Constants
const InternalTaskInterleaved = "@interleaved"
InternalTaskInterleaved is the ID used for the interleaved output stream.
const InternalTaskWatch = "@watch"
InternalTaskWatch is the ID used for file-watcher messaging.
Variables
var LogStyle = lipgloss.NewStyle(). Foreground(color.XXXLight). Italic(true)
LogStyle is the style used for run system messages (starting, exit, etc.).
Functions
func StripANSIEscapeCodes
func StripANSIEscapeCodes(s string) string
StripANSIEscapeCodes removes ANSI escape codes from a string.
Types
type MultiWriter
type MultiWriter interface { Writer(id string) io.Writer }
MultiWriter is the interface Runs use to display UI. To start a Run, you must pass a MultiWriter into Run.Start.
MultiWriter is a subset of UI, so the UIs produced by [tui.New] and [printer.New] implement MultiWriter.
type Run
type Run struct { // contains filtered or unexported fields }
A Run represents an execution of a task, including,
- execution of other tasks that it depends on
- configuration of file-watches for retriggering tasks.
A Run is safe to access concurrently from multiple goroutines.
func New
func New(dir string, allTasks task.Library, taskID string) (*Run, error)
New creates an executable Run from a taskList and a taskID.
The run will handle task dependencies, watches, and triggers as documented in the README.
func (*Run) Add
func (r *Run) Add(ids ...string)
Add dynamically adds tasks (by ID) to the active run. The task IDs must exist in the allTasks collection passed to New. Their transitive dependencies, triggers, and watches are also activated.
func (*Run) IDs
func (r *Run) IDs() []string
IDs returns the list of output stream names that a Run would write to. This includes the IDs of each Task that will be used in the run, plus (if applicable) the id "@watch", which the Run uses for messaging about file watchers.
func (*Run) Invalidate
func (r *Run) Invalidate(id string)
Invalidate asks a task to rerun.
func (*Run) Remove
func (r *Run) Remove(id string)
Remove dynamically removes a task (by ID) from the active run. Tasks exclusively owned by the removed task are also cleaned up.
func (*Run) Start
func (r *Run) Start(ctx context.Context, out MultiWriter) error
Start starts the Run, waits for it to complete, and returns an error. Remember that "long" runs will never complete until canceled.
func (*Run) TaskStatus
func (r *Run) TaskStatus(id string) TaskStatus
TaskStatus, given a task ID, returns that task's TaskStatus.
func (*Run) Tasks
func (r *Run) Tasks() task.Library
Tasks returns the Library that a Run would execute.
func (*Run) Type
func (r *Run) Type() RunType
Type returns the RunType of a run. It is RunTypeLong if any task is "long", otherwise it is RunTypeShort.
If a run is RunTypeShort, it will exit once all of its tasks have succeeded. If a run is RunTypeLong, it will continue running until it is interrupted. File watches are only used if a run is RunTypeLong.
type RunType
type RunType int
A Run's RunType is RunTypeLong if any task is "long", otherwise it is RunTypeShort.
If a run is RunTypeShort, it will exit once all of its tasks have succeeded. If a run is RunTypeLong, it will continue running until it is interrupted. File watches are only used if a run is RunTypeLong.
const ( RunTypeShort RunType RunTypeLong )
func (RunType) String
func (i RunType) String() string
type TaskStatus
type TaskStatus int
const ( TaskStatusNotStarted TaskStatus TaskStatusRunning TaskStatusRestarting TaskStatusFailed TaskStatusDone )
func (TaskStatus) String
func (i TaskStatus) String() string
type UI
type UI interface { Start(ctx context.Context, ready chan<- struct{}, stdin io.Reader, stdout io.Writer) error Writer(id string) io.Writer }
A UI is essentially a multiplexed io.Writer that can be started and stopped. Since UIs implement MultiWriter, they can be passed into Run.Start to display run execution.
The packages [tui] and [printer] produce implementors of UI.