Documentation
¶
Overview ¶
Package runner turns a declared tool (a config.RunnerSpec) into something that runs: it merges the tool's effective config, expands its argument and environment templates, executes the subprocess, and reads the output through the spec's parser.
The native checks stickler implements itself are NOT registered here — they are injected (see Registry), which is what keeps this package from depending on the checks that depend on it.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ExecCommand ¶
ExecCommand is the default Command, executing a real subprocess. On failure the returned error wraps ErrExec with the captured stderr so the underlying reason (config error, panic, load failure) reaches the caller's message.
The timeout has to reach the checker's CHILDREN, and it did not ¶
CommandContext kills the direct child only, and cmd.Output() then waits on the stdout pipe — which a surviving GRANDCHILD still holds open. So a checker that forks ignored --timeout entirely: measured with a `#!/bin/sh` wrapper around `sleep 3600`, a 3-second timeout ran for as long as an outer cap allowed, and the run hung rather than failing. That is any shell-wrapped checker, and both real ones qualify -- yze and golangci-lint each spawn `go list`.
Two settings close it, and both are needed:
- Setpgid puts the child in its OWN process group, so the whole tree can be signalled rather than the one process stickler forked.
- Cancel signals that group, and WaitDelay bounds the wait on the pipes AFTERWARDS. Without WaitDelay, Output() still blocks on a pipe an escaped grandchild holds; without the group, the signal reaches nobody but the shell that already exited.
[types.Config] says "Timeout bounds an entire lint pass, so a wedged linter cannot hang the run forever". This is where that sentence becomes true. A wedged linter that hangs the gate is worse than one that fails it: go-yze's own ErrNotRegularFile doc calls that outcome "the one nobody can diagnose from a stuck CI job".
Types ¶
type Command ¶
Command runs an external tool and returns its stdout. A non-nil error includes a non-zero exit; callers that can still parse the stdout (linters exit non-zero when they report findings) treat the output as authoritative.
type Context ¶
Context carries what config-file runners need to build their effective configuration: the repo directory holding the base config files and the resolved per-tool overlays keyed by runner name.
type EnvVar ¶
type EnvVar string
EnvVar is one KEY=value environment entry a runner's subprocess receives on top of the inherited environment. A key set here shadows the ambient value: the entries are appended after os.Environ, and the last occurrence of a key wins for the started process.
type Parser ¶
type Parser func(out []byte) ([]goyze.Diagnostic, error)
Parser turns a tool's stdout into normalized diagnostics. A non-nil error means the tool self-reported a fatal problem (bad config, internal error). This is the only per-tool code in the runner layer.
type Registry ¶
Registry is everything a selected name may resolve to: the declared tool specs, and the native checks stickler implements itself.
Native is INJECTED rather than looked up here. A registry of native checks inside this package would make it depend on the check packages, which depend on it — the composition root supplies them instead, and the dependency stays one-way.
type Skipped ¶ added in v0.15.0
type Skipped struct {
Runner config.RunnerName
Missing string
}
Skipped is one runner that was selected and had nothing to run against: the runner, and the file whose absence says so.
It is RETURNED rather than swallowed. A tool that did not run and a tool that found nothing produce the same silence, and the difference is the whole verdict -- so the run says which runners it did not use, and why, in the same breath as what it found.
func Build ¶
func Build( command Command, registry Registry, selection config.RunnerSelection, ctx Context, ) ([]suite.Runner, []Skipped, error)
Build resolves the selected runners against the registry into generic runners. The selection is applied to every defined spec plus every native check, so a configuration that says nothing gets all of them; a config-defined spec with a native check's name overrides it, so a repository can rewire even a native check without a recompile. An unknown name, or a spec naming an unknown parser, fails with ErrUnknownRunner.
A selection that resolves to NONE is ErrNoRunners rather than the default set. The two used to be one empty list -- the directives were applied to an empty base rather than to the defaults, so `runners: {remove: [yze]}` came out empty and empty meant "run everything", which re-enabled the runner it names. Both halves are fixed here: the directives apply to the defaults, so a removal removes and the rest survive, and an empty result fails the run, because a gate that judges nothing exits exactly like a gate that found nothing.