Help us shape the future of Go! Take the 2026 Go Developer Survey

runner

package
v5.6.3 Latest Latest
Warning

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

Go to latest
Published: Oct 24, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Overview

Package runner runs an external command with the limits a tool needs when it executes something it did not write: a scrubbed environment, a timeout that kills the whole process tree, a cap on captured output, and a distinct outcome for a binary that is not installed. It never goes through a shell.

The package carries no policy about what the command prints. Callers (lint scanners today; verifiers and plan/apply later) decide what an outcome means.

Index

Constants

View Source
const (
	// DefaultTimeout is how long a command may run when Spec.Timeout is zero.
	DefaultTimeout = 2 * time.Minute
	// MaxTimeout is the longest timeout a Spec may request.
	MaxTimeout = 15 * time.Minute
	// HardMaxTimeout is the longest timeout any caller may grant through Spec.MaxTimeout.
	HardMaxTimeout = 6 * time.Hour
	// DefaultMaxOutput is the per-stream capture cap in bytes.
	DefaultMaxOutput int64 = 32 << 20
)

Limits applied when a Spec leaves them unset or asks for more than allowed.

View Source
const RunTokenEnv = "AI_RULEZ_RUN_TOKEN"

RunTokenEnv names the variable that tags every process a run starts on unix, so the run can find a helper that left its process tree. Its value is a colon-separated list of run tokens: a run started inside another run appends its own, so the outer run still recognizes the inner one's helpers. It is not a secret, and scrubbed environments keep it.

Variables

This section is empty.

Functions

func Command

func Command(ctx context.Context, name string, args ...string) *exec.Cmd

Command builds an exec.Cmd for a caller that has to stream a child's output or wire its standard streams itself, which Runner does not cover. Starting it is the caller's business; the package gitutil builds its git invocations with it.

func CommandNoContext

func CommandNoContext(name string, args ...string) *exec.Cmd

CommandNoContext is Command for callers that have no context to pass.

func EffectiveTimeout

func EffectiveTimeout(d time.Duration) time.Duration

EffectiveTimeout applies the default and the maximum to a requested timeout.

func EffectiveTimeoutUpTo added in v5.5.0

func EffectiveTimeoutUpTo(d, ceiling time.Duration) time.Duration

EffectiveTimeoutUpTo is EffectiveTimeout under a ceiling the caller granted: ceiling is clamped to [1s, HardMaxTimeout], and zero means MaxTimeout. A ceiling below the default lowers the default with it.

func Environ

func Environ() []string

Environ returns the environment of this process, for building the environment of a child. Library code takes an environment from its Host; this is for the code that starts the process and has none to inherit from.

func HostEnv

func HostEnv() []string

HostEnv is os.Environ(), for callers that scrub the real environment.

func LookPath

func LookPath(name string) (string, error)

LookPath finds name on PATH. A binary found only through a relative PATH entry is reported as an error (exec.ErrDot), not returned. It exists so library packages that must know whether a tool is installed do not import os/exec themselves.

func ScrubEnv

func ScrubEnv(parent, pass, extra []string) []string

ScrubEnv builds a child environment from parent (KEY=VALUE entries, usually os.Environ()): only the base allowlist, any LC_* locale variable, and the names in pass survive (pass is trusted: reject Sensitive names before calling when the command must not reach the network). extra entries (KEY=VALUE) are added last and win. NO_COLOR=1 and TERM=dumb are set unless extra overrides them. The result is sorted, so the same inputs always give the same environment.

func Sensitive

func Sensitive(name string) bool

Sensitive reports whether passing the variable to a command that must not reach the network is unsafe: proxy settings, and anything that looks like a credential or a known provider key.

func ValidEnvName

func ValidEnvName(name string) bool

ValidEnvName reports whether name is a portable environment variable name.

func WithContext

func WithContext(ctx context.Context, r Runner) context.Context

WithContext returns ctx carrying r, for call chains that pass a context but no options (an include fetch). A nil r leaves ctx unchanged.

Types

type DeniedError

type DeniedError struct{ Argv []string }

DeniedError reports a command a Deny runner refused.

func (*DeniedError) Error

func (e *DeniedError) Error() string

type Deny

type Deny struct{}

Deny is the Runner of a context that must not start a process: every command is StatusUnavailable, with ErrDenied carrying the argv.

func (Deny) Run

func (Deny) Run(_ context.Context, spec Spec) Result

Run implements Runner.

func (Deny) RunLines

func (d Deny) RunLines(ctx context.Context, spec Spec, _ LineFunc) Result

RunLines implements LineRunner for Deny: nothing is started.

type Exec

type Exec struct{}

Exec is the Runner that starts a real process through Run. It is the default everywhere a Runner is optional, and keeps the behavior callers had before the runner was injectable.

func (Exec) Run

func (Exec) Run(ctx context.Context, spec Spec) Result

Run implements Runner.

func (Exec) RunLines

func (Exec) RunLines(ctx context.Context, spec Spec, onLine LineFunc) Result

RunLines implements LineRunner for Exec.

type Fake

type Fake struct {
	// Handle computes the answer for a spec; nil answers StatusOK with no output.
	Handle func(spec Spec) Result
	// contains filtered or unexported fields
}

Fake is a Runner for tests: it records every Spec and answers with Handle (a zero Result with StatusOK when Handle is nil). It is safe for concurrent use.

func (*Fake) Calls

func (f *Fake) Calls() []Spec

Calls returns a copy of the recorded specs, in call order.

func (*Fake) Run

func (f *Fake) Run(_ context.Context, spec Spec) Result

Run implements Runner.

type Func

type Func func(ctx context.Context, spec Spec) Result

Func adapts a function to a Runner.

func (Func) Run

func (f Func) Run(ctx context.Context, spec Spec) Result

Run implements Runner.

type LineFunc

type LineFunc func(line []byte) (stop bool)

LineFunc receives one line of a command's standard output (without its newline) and reports whether the command may stop now. The slice is only valid during the call.

type LineRunner

type LineRunner interface {
	RunLines(ctx context.Context, spec Spec, onLine LineFunc) Result
}

LineRunner is a Runner that can also hand a command's standard output to the caller line by line while it runs and end the command early. The eval adapters use it to stop a harness at its first decision instead of paying for the rest of its run.

func AsLineRunner

func AsLineRunner(r Runner) (LineRunner, bool)

AsLineRunner returns r as a LineRunner: the real process runner for nil, r itself when it can stream, and ok false otherwise.

type Result

type Result struct {
	Status Status
	// ExitCode is the exit status, or -1 when the command did not exit normally.
	ExitCode int
	Stdout   []byte
	Stderr   []byte
	// StdoutTruncated and StderrTruncated report output beyond MaxOutput.
	StdoutTruncated bool
	StderrTruncated bool
	// Timeout is the effective timeout that applied.
	Timeout  time.Duration
	Duration time.Duration
	// Err is the underlying error for every status other than StatusOK.
	Err error
}

Result is what a run produced. Apart from Duration, it is a pure function of the command's behavior: output is returned byte for byte, never reordered.

func Run

func Run(ctx context.Context, spec Spec) Result

Run executes spec and returns its outcome. It never panics and never returns an error: failures are a Status. ctx cancellation is reported as StatusError.

type Runner

type Runner interface {
	Run(ctx context.Context, spec Spec) Result
}

Runner runs an external command. Library code that has to start a process takes a Runner instead of calling os/exec, so an embedding service can deny, record or fake every command. Run never returns an error: a failure is the Result's Status, as for the package-level Run.

func FromContext

func FromContext(ctx context.Context) Runner

FromContext returns the Runner ctx carries, or Exec when it carries none.

func Or

func Or(r Runner) Runner

Or returns r, or Exec when r is nil.

type Spec

type Spec struct {
	// Argv is the command and its arguments; Argv[0] is looked up on PATH unless it contains a separator.
	Argv []string
	// Dir is the working directory; empty means the current directory.
	Dir string
	// Env is the complete environment (KEY=VALUE) of the child. It is ignored when InheritEnv is set.
	// Build it with ScrubEnv; an empty Env gives the child no environment at all.
	Env []string
	// InheritEnv passes the parent's full environment to the child. Prefer an explicit Env.
	InheritEnv bool
	// Stdin is the data piped to the child; nil connects it to the null device.
	Stdin []byte
	// Timeout bounds the run; zero means DefaultTimeout and values above MaxTimeout are lowered to it.
	Timeout time.Duration
	// MaxTimeout raises the ceiling on Timeout above MaxTimeout, up to
	// HardMaxTimeout; zero keeps MaxTimeout. The caller owns the policy that grants it.
	MaxTimeout time.Duration
	// MaxOutput caps each of stdout and stderr in bytes; zero means DefaultMaxOutput. Output past the
	// cap is discarded (the child is not blocked) and reported through Result.*Truncated.
	MaxOutput int64
	// ShortLived marks a trusted command that finishes quickly and does not
	// detach helpers on purpose (git). The runner then skips the descendant
	// watcher and reads the process table once after the command instead of
	// several times; the group kill, run token and marker descriptor still
	// apply. Never set it for scanners, verifiers or evaluated commands.
	ShortLived bool
}

Spec describes one command. The zero value of every field except Argv is usable.

type Status

type Status string

Status is the coarse outcome of a run.

const (
	// StatusOK means the command ran and exited with status 0.
	StatusOK Status = "ok"
	// StatusExit means the command ran and exited non-zero.
	StatusExit Status = "exit"
	// StatusTimeout means the command was killed at its timeout.
	StatusTimeout Status = "timeout"
	// StatusUnavailable means the executable was not found or is not executable.
	StatusUnavailable Status = "unavailable"
	// StatusError means the command could not be started or waited on for another reason.
	StatusError Status = "error"
)

Outcomes of Run.

Jump to

Keyboard shortcuts

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