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
- func Command(ctx context.Context, name string, args ...string) *exec.Cmd
- func CommandNoContext(name string, args ...string) *exec.Cmd
- func EffectiveTimeout(d time.Duration) time.Duration
- func EffectiveTimeoutUpTo(d, ceiling time.Duration) time.Duration
- func Environ() []string
- func HostEnv() []string
- func LookPath(name string) (string, error)
- func ScrubEnv(parent, pass, extra []string) []string
- func Sensitive(name string) bool
- func ValidEnvName(name string) bool
- func WithContext(ctx context.Context, r Runner) context.Context
- type DeniedError
- type Deny
- type Exec
- type Fake
- type Func
- type LineFunc
- type LineRunner
- type Result
- type Runner
- type Spec
- type Status
Constants ¶
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.
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 ¶
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 ¶
CommandNoContext is Command for callers that have no context to pass.
func EffectiveTimeout ¶
EffectiveTimeout applies the default and the maximum to a requested timeout.
func EffectiveTimeoutUpTo ¶ added in v5.5.0
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 ¶
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 ¶
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 ¶
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 ¶
ValidEnvName reports whether name is a portable environment variable name.
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.
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.
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.
type LineFunc ¶
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 ¶
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.
type Runner ¶
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 ¶
FromContext returns the Runner ctx carries, or Exec when it carries none.
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 Status = "unavailable" // StatusError means the command could not be started or waited on for another reason. StatusError Status = "error" )
Outcomes of Run.