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.

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.

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

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,

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.