gorun

package module
v0.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 4, 2026 License: MIT Imports: 36 Imported by: 0

README

Gorun

Go Reference XERJ Corpus Hub contributor

Run plain shell commands on a pile of servers, in parallel, and watch it happen.

One Go binary, one TOML file and SSH. Nothing to install on the servers.

gorun provisioning ten servers in parallel

[!WARNING] Use at your own risk. gorun runs commands on your servers, often as root. It comes with no warranty of any kind (see the MIT license). Read your Gorunfiles and try them on non-production servers first.

What it does

You write tasks as shell commands in a Gorunfile, and say which servers run which tasks:

[tasks.update]
cmd = "apt-get update && apt-get upgrade -y"
sudo = true

[servers]
tasks = ["update"]

[servers.hosts.web-1]
hostname = "web-1.example.com"
    [servers.hosts.web-1.ssh]
    username = "ubuntu"

Then gorun Gorunfile lets you pick the servers, runs the tasks on all of them at once, and shows each server's progress live.

  • Plain commands. A task is a shell command or script. When something breaks, you can copy the command and run it by hand.
  • Parallel. Every server runs at the same time. A failure stops that server, not the others.
  • Nothing runs by accident. You pick servers and tasks in a picker first, and every task has a timeout.
  • Grows with you. Dependencies, bundles, server groups, tags, templates with per-task variables, file copies, retries and secrets from your environment, when you need them.
  • Remembers. Every run is saved, with its commands and output, to look back on later.
  • Exports. Dump every task as a standalone, runnable shell file with --dump-tasks, to audit or run by hand.
  • Task browser. The picker’s Tasks tab previews each task’s description, details, command, execution settings, env vars, and vars beside the dependency tree, with collapsible sections and direct editing of file-backed commands.
  • History. Past runs are saved with commands and output; expanded servers list tasks slowest first. When to use something else: gorun runs commands; it doesn't enforce state. It has no modules, facts, drift detection, dry runs, dynamic inventories or secrets vault. For that, use Ansible, Salt, Puppet or Nix.

Install

curl -fsSL https://raw.githubusercontent.com/jenmud/gorun/master/scripts/install.sh | sh

Or download a binary from the releases, or build it yourself with go build -o gorun ./cmd.

Two builds: instrumented (default) and standard

The install script installs the instrumented build, which adds OpenTelemetry support. It does nothing until you set an OTEL_* endpoint. For the standard build without it:

curl -fsSL https://raw.githubusercontent.com/jenmud/gorun/master/scripts/install.sh | INSTALL_VARIANTS=1 sh

Prebuilt binaries are for Linux x86-64; elsewhere the script builds from source.

Quick start

gorun -dump > Gorunfile      # write a starting Gorunfile; it runs as-is on this machine
gorun Gorunfile              # pick what to run: space selects, enter runs
gorun Gorunfile --run        # or run everything, without the picker

The starting file runs on your own machine, and documents every option in comments. Its tasks are marked local = true: a server without SSH settings runs only those, and every other task runs only over SSH. To run on a real server, add one with an ssh table, and remove local = true from the tasks it should run:

[servers.hosts.web-01]
hostname = "web-01.example.com"
    [servers.hosts.web-01.ssh]
    username = "deploy"
    identityfile = "~/.ssh/id_ed25519"

Then check what it will run with gorun Gorunfile --list-servers.

gorun Gorunfile --dump-tasks ./tasks   # write each task as a runnable shell file

Next: the tutorial builds up a real deployment one step at a time.

Documentation

Read To
Tutorial learn gorun step by step, from hello world to a full deployment
The Gorunfile understand every option: tasks, copies, secrets, servers, bundles, groups
Running gorun use the picker, the live view, filters, CI mode and the history
Integrations use the web UI, OpenTelemetry, NATS events, the Go library and shell completion
Reference look up any flag, Gorunfile key, environment variable or shortcut
Recipes try bigger examples against a lab of a hundred SSH servers

Development

make test                     # run the tests
make build                    # build the standard and instrumented binaries
make up                       # start the example lab: a hundred SSH servers and NATS
gorun recipes/Gorunfile -r    # run the lab starter
make web-dev                  # the web UI with live reload

The terminal screenshots are made by docs/screenshots/capture.sh; run it again after changing the UI. The web dashboard screenshots are taken by hand.

Documentation

Overview

Package gorun runs plain shell commands, defined in a Gorunfile, on one or more servers over SSH or on the local machine, in parallel.

The gorun command (in ./cmd) is a thin layer over this package: it adds the picker, the live view and the history. Use the package directly to run Gorunfiles from your own code.

To learn how to write a Gorunfile, start with the tutorial: https://github.com/jenmud/gorun/blob/master/docs/tutorial.md

Gorunfiles

A Gorunfile is TOML. It has a library of named tasks (Task): a shell command, script or template, with optional file copies, sudo, env vars, dependencies, a timeout and retries. Servers (Server) pick tasks from the library by name, directly or through named task lists (Bundle) and shared settings (ServerGroup). A server with SSH settings runs its tasks over SSH; one without them runs on the local machine. A task runs on one kind of server only: a task with local = true (Task.Local) runs only on local servers, and every other task runs only over SSH. Tasks of the other kind, and tasks that depend on them, are left out of a server's pipeline.

title = "Provision app servers"

[tasks.hello]
cmd_template = "echo hello from {{.Name}}"

[servers]
tasks = ["hello"]

[servers.hosts.web-01]
hostname = "web-01.example.com"
    [servers.hosts.web-01.ssh]
    username = "deploy"

Every option is described in https://github.com/jenmud/gorun/blob/master/docs/gorunfile.md.

Loading and running

Config.Load reads and validates a Gorunfile, and Config.ResolvePaths makes its relative paths relative to the file. Config.Run then runs every server's tasks, or just the servers you pass it:

f, err := os.Open("Gorunfile")
if err != nil {
	return err
}
defer f.Close()

var cfg gorun.Config
if err := cfg.Load(f); err != nil {
	return err
}
cfg.ResolvePaths(filepath.Dir(f.Name()))
return cfg.Run(ctx)

Choosing servers and tasks

Config.SelectServers picks servers the way the --server, --tag and --group flags do, and Config.ExpandTaskPatterns expands task names, globs and "@bundle" references the way --task does:

servers, err := cfg.SelectServers(gorun.ServerFilter{Tags: []string{"web"}})
if err != nil {
	return err
}
tasks, err := cfg.ExpandTaskPatterns("@baseline")
if err != nil {
	return err
}
for i := range servers {
	servers[i].TaskNames = tasks
}
return cfg.Run(ctx, servers...)

Config.ServersPipeline returns every server with its task list resolved, as gorun --list-servers shows it.

Running single tasks and running locally

Config.RunTask runs one task (with its dependencies) on some or all servers, whether or not they normally run it, and returns an error when none of them can run it (see Task.Local). Config.RunLocal runs tasks on this machine without any SSH server; only tasks marked local = true run there. LocalServer and Config.LocalServer give a Server that runs locally.

Events

Set Config.OnEvent to follow a run as it happens. It receives a ProcessStartedEvent, a PlanEvent per server, a TaskEvent for every change in a task's TaskState, a ServerErrorEvent when a server can't run, and a ProcessFinishedEvent at the end:

cfg.OnEvent = func(event any) {
	if ev, ok := event.(gorun.TaskEvent); ok && ev.State != gorun.TaskRunning {
		fmt.Printf("%s: %s exit %d\n", ev.Server, ev.Task, ev.ExitCode)
	}
}

Index

Examples

Constants

View Source
const (
	// DefaultTaskTimeout is how long a task may run when it doesn't set its own
	// timeout. It stops a hung command from holding up a run forever.
	DefaultTaskTimeout = 30 * time.Minute

	// DefaultRetryDelay is how long gorun waits between attempts when a task
	// sets retries but not retry_delay. A short pause gives transient failures
	// (a restarting service, a busy package mirror) a moment to settle.
	DefaultRetryDelay = 50 * time.Millisecond

	// RerunSafe and RerunUnsafe are the accepted values of Task.Rerun. An
	// empty value means the author has not said whether rerunning is safe.
	RerunSafe   = "safe"
	RerunUnsafe = "unsafe"
)
View Source
const BundlePrefix = "@"

BundlePrefix marks a task list entry as a reference to a bundle rather than a task, e.g. "@base" for [bundles.base].

Variables

View Source
var ErrNoTasks = errors.New("no tasks to run: local servers only run tasks marked local = true, and other tasks only run over SSH")

ErrNoTasks is returned by Run when no selected server has a task to run. Local servers only run tasks marked local = true, and other tasks only run over SSH.

View Source
var LocalServer = Server{Name: "local"}

LocalServer is a ready-to-use Server that runs tasks on the local machine.

Functions

func CopyFiles

func CopyFiles(client *ssh.Client, server any, task *Task) error

CopyFiles copies files for a task to a server. Templates are executed with server as their data, the same as cmd_template.

func EnvLine added in v0.8.0

func EnvLine(vars map[string]string) (string, error)

EnvLine renders vars as a single `export KEY='value' ...` shell line, keys upper-cased and sorted. It is the exported form of envLine.

func ExpandEnv added in v0.8.0

func ExpandEnv(value string) string

ExpandEnv is the exported form of expandEnv.

func LogFilePath

func LogFilePath() string

LogFilePath returns the file gorun writes its logs to: GORUN_LOG_FILE when set (a leading ~ is expanded), otherwise ~/.gorun/gorun.log.

func LogOutput

func LogOutput() io.Writer

LogOutput returns the current destination for task and server logs, so it can be put back after something interactive silences it.

func NewLogger

func NewLogger(level string, w io.Writer, json bool) *slog.Logger

NewLogger returns a new logger.

func NewSSHClient

func NewSSHClient(ctx context.Context, server Server) (*ssh.Client, error)

NewSSHClient creates a new SSH client connected to the provided server.

func OpenLogFile

func OpenLogFile(path string) (*os.File, error)

OpenLogFile opens path for appending, creating it and its directory if needed.

func SetLogOutput

func SetLogOutput(w io.Writer)

SetLogOutput overrides the destination for task and server logs, so they go to the log file instead of cluttering the terminal.

func StartNATS

func StartNATS()

Types

type Bundle

type Bundle struct {
	Name        string         `toml:"-"` // the <name> in [bundles.<name>]
	Description string         `toml:"description"`
	Tasks       []string       `toml:"tasks"`
	Vars        map[string]any `toml:"vars,omitempty"`
}

Bundle is a named list of tasks, defined as [bundles.<name>]. Task lists refer to it as "@<name>", and it expands to its tasks in order. A bundle may include other bundles.

type Config

type Config struct {
	Title           string            `toml:"title"`
	GorunUUID       string            `toml:"-"`
	LogLevel        string            `toml:"log_level"`
	MaxParallel     int               `toml:"max_parallel"`      // 0 means run every selected host at once
	MaxTaskParallel int               `toml:"max_task_parallel"` // 0 (default) = one at a time; -1 = all at once
	EnvVars         map[string]string `toml:"envvars"`
	Vars            map[string]any    `toml:"vars,omitempty"`
	SSH             SSH               `toml:"ssh"`

	// Tasks is the task library, keyed by task name. Servers pick tasks from it by name.
	Tasks map[string]Task `toml:"tasks"`

	// Bundles are named task lists, referred to as "@<name>" wherever a task list is accepted.
	Bundles map[string]Bundle `toml:"bundles"`

	// Groups hold defaults shared by the servers that join them.
	Groups map[string]ServerGroup `toml:"server_groups"`

	// Servers are the [servers.hosts.<name>] tables, in the order they appear in the file.
	Servers []Server `toml:"-"`

	// OnEvent, when set, receives the events in events.go as tasks run.
	OnEvent func(event any) `toml:"-"`

	// SelectedTasks, when non-empty, limits execution to these tasks (and their
	// dependencies). Bundle references ("@name") are expanded. Used by the --task CLI flag.
	SelectedTasks []string `toml:"-"`
}

Config represents a config file.

func (*Config) AllServers added in v0.5.0

func (c *Config) AllServers() []Server

AllServers returns a copy of every server in the config, in config order. Use it to browse or filter the full inventory (e.g. for a picker or a "run on local" toggle).

func (*Config) ExpandTaskPatterns

func (c *Config) ExpandTaskPatterns(patterns ...string) ([]string, error)

ExpandTaskPatterns turns --task style arguments into task names. Each argument is a task name, a glob such as "deploy-*", or a bundle reference ("@base", or a glob like "@web-*"). A glob must match at least one task or bundle.

func (*Config) ExpandTaskRefs

func (c *Config) ExpandTaskRefs(refs ...string) ([]string, error)

ExpandTaskRefs turns a task list into task names: "@<bundle>" entries are replaced by the bundle's tasks, and repeated names are dropped, keeping the first. Every name must be a task in the library.

func (*Config) Load

func (c *Config) Load(r io.Reader) error

Load reads and updates the config.

func (*Config) LocalServer added in v0.5.0

func (c *Config) LocalServer() Server

LocalServer returns a server that runs on this machine. If the config already defines a server with no SSH configured, that server is returned; otherwise a new "local" server is returned.

func (*Config) ResolvePaths

func (c *Config) ResolvePaths(dir string)

ResolvePaths makes the relative file paths in the config (SSH identity files and task cmd_files) relative to dir, normally the directory holding the config file, so gorun can be run from anywhere.

func (*Config) Run

func (c *Config) Run(ctx context.Context, server ...Server) error

Run runs all the tasks as returned by `Pipeline` on one or more servers.

func (*Config) RunLocal added in v0.5.0

func (c *Config) RunLocal(ctx context.Context, names ...string) error

RunLocal runs the named tasks (or every task when none are given) on the local machine. Only tasks marked local = true run there, and ErrNoTasks is returned when none of them are. Task names may be globs or bundle references ("@name"), just like --task.

Example

Load a Gorunfile and run its tasks on this machine, printing each task as it finishes.

package main

import (
	"context"
	"fmt"
	"log"
	"strings"

	"github.com/jenmud/gorun"
)

func main() {
	gorunfile := `
title = "Example"

[tasks.hello]
cmd = "echo hello"
local = true

[tasks.goodbye]
cmd = "echo goodbye"
local = true
depends_on = ["hello"]
`
	var cfg gorun.Config
	if err := cfg.Load(strings.NewReader(gorunfile)); err != nil {
		log.Fatal(err)
	}

	cfg.OnEvent = func(event any) {
		if ev, ok := event.(gorun.TaskEvent); ok && ev.State == gorun.TaskDone {
			fmt.Printf("%s: %s", ev.Task, ev.Stdout)
		}
	}

	if err := cfg.RunLocal(context.Background(), "goodbye"); err != nil {
		log.Fatal(err)
	}
}
Output:
hello: hello
goodbye: goodbye

func (*Config) RunTask

func (c *Config) RunTask(ctx context.Context, t Task, server ...Server) error

RunTask runs a single task (and its dependencies) on one or more servers. When no servers are given, every server in the config is used. The task does not need to be part of any server's configured task list.

func (*Config) SelectServers

func (c *Config) SelectServers(f ServerFilter) ([]Server, error)

SelectServers returns the servers matching the filter, in config order. Exact names, tags and groups that don't exist are errors (with a suggestion for likely typos), as is a name glob that matches nothing or a filter that leaves no servers.

func (*Config) ServerPipeline

func (c *Config) ServerPipeline(server Server) (Server, error)

ServerPipeline returns the server with its tasks, and their dependencies, resolved into run order.

func (*Config) ServersPipeline

func (c *Config) ServersPipeline() (map[string]Server, error)

ServersPipeline returns every server with its tasks resolved into run order.

func (*Config) TaskNames

func (c *Config) TaskNames() []string

TaskNames returns the task names in dependency order (dependencies first).

type Copy

type Copy struct {
	Src      string `toml:"src"`
	SrcFile  string `toml:"src_file,omitempty"`
	SrcTpl   string `toml:"src_template,omitempty"`
	SrcTmpl  string `toml:"src_tmpl,omitempty"`
	Template string `toml:"template,omitempty"`
	Content  string `toml:"content,omitempty"`
	Dst      string `toml:"dst"`
	DstPath  string `toml:"dst_path,omitempty"`
	Dir      string `toml:"dir,omitempty"`
	Dest     string `toml:"dest,omitempty"`
	Mode     string `toml:"mode,omitempty"`
	Perm     string `toml:"perm,omitempty"`
}

Copy represents a file copy operation.

type PlanEvent

type PlanEvent struct {
	Type      string     `json:"type"`
	GorunUUID string     `json:"gorun_uuid"`
	Server    string     `json:"server"`
	Address   string     `json:"address"`
	Tasks     []string   `json:"tasks"`
	TaskMeta  []TaskMeta `json:"task_meta,omitempty"`
}

PlanEvent is sent once per server, before any task runs, with the tasks in execution order.

type ProcessFinishedEvent

type ProcessFinishedEvent struct {
	Type       string        `json:"type"`
	GorunUUID  string        `json:"gorun_uuid"`
	Success    bool          `json:"success"`
	Duration   time.Duration `json:"duration"`
	TotalTasks int           `json:"total_tasks"`
	Failed     int           `json:"failed"`
	Skipped    int           `json:"skipped"`
	FinishedAt time.Time     `json:"finished_at"`
}

ProcessFinishedEvent is published when a gorun process finishes running.

type ProcessStartedEvent

type ProcessStartedEvent struct {
	Type      string    `json:"type"`
	GorunUUID string    `json:"gorun_uuid"`
	Title     string    `json:"title"`
	Servers   []string  `json:"servers"`
	StartedAt time.Time `json:"started_at"`
	Hostname  string    `json:"hostname"`
	PID       int       `json:"pid"`
}

ProcessStartedEvent is published when a gorun process starts running.

type RunDoneEvent

type RunDoneEvent struct {
	Type      string `json:"type"`
	GorunUUID string `json:"gorun_uuid"`
	Err       error  `json:"error,omitempty"`
}

RunDoneEvent is sent when every server has finished.

type SSH

type SSH struct {
	User         string `toml:"username"`
	Password     string `toml:"password"`
	Port         int    `toml:"port"`
	Identityfile string `toml:"identityfile"`
	ConfigFile   string `toml:"config_file,omitempty"`
	Config       string `toml:"config,omitempty"`
}

SSH represents SSH creds

type Server

type Server struct {
	LogLevel        string `toml:"log_level"`
	MaxTaskParallel int    `toml:"max_task_parallel"` // 0 (default) = one at a time; -1 = all at once
	Name            string `toml:"-"`                 // the <name> in [servers.hosts.<name>]
	Hostname        string `toml:"hostname"`
	SSH             SSH    `toml:"ssh"`

	// TaskNames are the tasks to run, by name. Load replaces them with the server's
	// final task list: its own tasks (or the global and group lists), plus AddTasks,
	// minus SkipTasks, with bundles expanded.
	TaskNames []string `toml:"tasks"`

	// Groups are the [server_groups.<name>] this server joins, in order. Load applies
	// their defaults to the server.
	Groups []string `toml:"groups"`

	// Tags label the server for --tag selection. Load adds its groups' tags.
	Tags []string `toml:"tags"`

	// EnvVars are exported to every task on this server. Load merges in its groups'
	// envvars; a task's own envvars still win.
	EnvVars map[string]string `toml:"envvars"`

	// Vars are template variables for this server (and its tasks). Load merges in its
	// groups' vars; a task's own vars still win in its templates.
	Vars map[string]any `toml:"vars,omitempty"`

	// AddTasks are appended to the server's task list and SkipTasks removed from it.
	AddTasks  []string `toml:"add_tasks"`
	SkipTasks []string `toml:"skip_tasks"`

	// Tasks is the resolved pipeline, including dependencies, set by ServerPipeline.
	Tasks []Task `toml:"-"`
}

Server is a server to connect to and execute tasks.

func (Server) Address

func (s Server) Address() string

Address formats a server's connection address for display ("local" when no SSH is configured).

func (Server) IsLocal added in v0.5.0

func (s Server) IsLocal() bool

IsLocal reports whether the server runs on the local machine (no SSH configured).

type ServerErrorEvent

type ServerErrorEvent struct {
	Type      string `json:"type"`
	GorunUUID string `json:"gorun_uuid"`
	Server    string `json:"server"`
	Err       error  `json:"error"`
}

ServerErrorEvent is sent when a server can't run its tasks at all (e.g. SSH connection failed).

type ServerFilter

type ServerFilter struct {
	Names   []string
	Exclude []string
	Tags    []string
	Groups  []string
}

ServerFilter selects servers. Every set field must match:

  • Names: the server name matches any of these names or globs.
  • Tags: the server has every one of these tags.
  • Groups: the server is in every one of these groups.
  • Exclude: the server name matches none of these names or globs.

func (ServerFilter) IsZero

func (f ServerFilter) IsZero() bool

IsZero reports whether the filter selects every server.

type ServerGroup

type ServerGroup struct {
	Name     string            `toml:"-"` // the <name> in [server_groups.<name>]
	LogLevel string            `toml:"log_level"`
	Tags     []string          `toml:"tags"`
	Tasks    []string          `toml:"tasks"`
	EnvVars  map[string]string `toml:"envvars"`
	Vars     map[string]any    `toml:"vars,omitempty"`
	SSH      SSH               `toml:"ssh"`
}

ServerGroup holds defaults shared by the servers that join it, defined as [server_groups.<name>]. A server joins groups by listing them in its groups key.

type Task

type Task struct {
	LogLevel        string            `toml:"log_level"`
	Name            string            `toml:"-"` // the <name> in [tasks.<name>]
	Sudo            bool              `toml:"sudo"`
	Cmd             string            `toml:"cmd,omitempty"`
	CmdFile         string            `toml:"cmd_file,omitempty"`
	CmdTemplate     string            `toml:"cmd_template,omitempty"`
	CmdTemplateFile string            `toml:"cmd_template_file,omitempty"`
	Copy            []Copy            `toml:"copy,omitempty"`
	Copies          []Copy            `toml:"copies,omitempty"`
	Upload          []Copy            `toml:"upload,omitempty"`
	Files           []Copy            `toml:"files,omitempty"`
	EnvVars         map[string]string `toml:"envvars"`
	Vars            map[string]any    `toml:"vars,omitempty"`
	DependsOn       []string          `toml:"depends_on"`
	Shell           string            `toml:"shell"`
	Timeout         time.Duration     `toml:"timeout,omitempty"`

	// Description is a one-line summary shown in task lists and the TUI.
	Description string `toml:"description,omitempty"`
	// Details is an optional longer explanation shown when a task is expanded.
	Details string `toml:"details,omitempty"`
	// Rerun is RerunSafe or RerunUnsafe. Empty means unspecified.
	Rerun string `toml:"rerun,omitempty"`
	// Local, when true, runs the task only on local servers and skips it on any
	// server that connects over SSH. Tasks without it run only over SSH.
	Local bool `toml:"local,omitempty"`
	// Retries is how many extra times to run a failed task. Zero means run once.
	Retries int `toml:"retries,omitempty"`
	// RetryDelay is how long to wait before each retry. Unset uses
	// DefaultRetryDelay; an explicit zero retries immediately.
	RetryDelay *time.Duration `toml:"retry_delay,omitempty"`
	// RetryUnsafe allows automatic retries for a task marked rerun = "unsafe".
	RetryUnsafe bool `toml:"retry_unsafe,omitempty"`
}

Task is a task to execute on one or more servers.

func (Task) Attempts

func (t Task) Attempts() int

Attempts returns how many times the task may run, including the first try.

func (Task) CanRetry

func (t Task) CanRetry() bool

CanRetry reports whether a failed attempt may be retried. Tasks marked unsafe to rerun require an explicit RetryUnsafe opt-in.

func (*Task) Command

func (t *Task) Command() (string, error)

Command reads the command from either inline cmd or from a file

func (*Task) CommandFor

func (t *Task) CommandFor(server any) (string, error)

CommandFor reads the command from either inline cmd or from a file, and compiles templates with the provided server.

func (Task) RetryDelayDuration

func (t Task) RetryDelayDuration() time.Duration

RetryDelayDuration returns the wait between attempts. A task that doesn't set retry_delay uses DefaultRetryDelay.

func (Task) TimeoutDuration

func (t Task) TimeoutDuration() time.Duration

TimeoutDuration returns the timeout to apply to the task. A zero (or negative) Timeout uses DefaultTaskTimeout.

type TaskEvent

type TaskEvent struct {
	Type      string        `json:"type"`
	GorunUUID string        `json:"gorun_uuid"`
	Server    string        `json:"server"`
	Task      string        `json:"task"`
	State     TaskState     `json:"state"`
	Stdout    string        `json:"stdout,omitempty"`
	Stderr    string        `json:"stderr,omitempty"`
	Command   string        `json:"command,omitempty"`
	ExitCode  int           `json:"exit_code"`
	Err       error         `json:"error,omitempty"`
	Duration  time.Duration `json:"duration"`
	// Attempt and Attempts are set when a task has retries configured. A
	// running event with Attempt greater than one means the previous attempt
	// failed and the task is being retried.
	Attempt  int `json:"attempt,omitempty"`
	Attempts int `json:"attempts,omitempty"`
}

TaskEvent is sent when a task changes state.

type TaskExec

type TaskExec struct {
	// contains filtered or unexported fields
}

TaskExec is a execution task to be run on a server.

func NewLocalTaskExec added in v0.5.0

func NewLocalTaskExec(task ...Task) ([]*TaskExec, error)

NewLocalTaskExec creates TaskExecs that run on the local machine (no SSH).

func NewTaskExec

func NewTaskExec(server *ssh.Client, task ...Task) ([]*TaskExec, error)

NewTaskExec creates and sets up a task to be executed on the remote session.

func (*TaskExec) Completed

func (t *TaskExec) Completed(ctx context.Context) error

Completed marks the task as completed.

func (*TaskExec) Execute

func (t *TaskExec) Execute(ctx context.Context) error

Execute executes the task with the attached SSH client.

func (*TaskExec) Fail

func (t *TaskExec) Fail(ctx context.Context, err error) error

Fail will fail a task.

func (*TaskExec) LocalExecute

func (t *TaskExec) LocalExecute(ctx context.Context) error

LocalExecute executes the task as a local task.

func (*TaskExec) Terminate

func (t *TaskExec) Terminate(ctx context.Context, err error) error

Terminates the task.

type TaskMeta

type TaskMeta struct {
	Name        string `json:"name"`
	Description string `json:"description,omitempty"`
	Details     string `json:"details,omitempty"`
	Rerun       string `json:"rerun,omitempty"`
}

TaskMeta carries the documentation attached to a task in a PlanEvent, so consumers such as the TUI and web dashboard can show descriptions and rerun warnings. Tasks still lists the bare names for older consumers.

type TaskState

type TaskState int

TaskState is the lifecycle state of a task on a server.

const (
	TaskPending TaskState = iota
	TaskRunning
	TaskDone
	TaskFailed
	TaskSkipped
)

Directories

Path Synopsis
cmd
web/ui
templ: version: v0.3.1070
templ: version: v0.3.1070
internal

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL