Documentation
¶
Overview ¶
Package golang is the Go-specific runner: build, test, and run Go programs in any of the supported execution environments (native, Docker, Nix) with consistent behavior.
The GoRunnerEnvironment manages module download, binary build with caching, and process lifecycle; the package also supplies the agent-side helpers (agent_builder, agent_runtime, agent_test) that the go-grpc / go agents embed.
Index ¶
- Constants
- func BuildGoDocker(ctx context.Context, builder *services.BuilderWrapper, ...) (*builderv0.BuildResponse, error)
- func ClassifyEnvError(raw string, runErr error) (reason, detail string)
- func DeployGoKubernetes(ctx context.Context, builder *services.BuilderWrapper, ...) (*builderv0.DeploymentResponse, error)
- func DeriveFormula(sourceDir string) (cmd []string, output string, ok bool)
- func DestroyGoRuntime(ctx context.Context, runtimeCtx *basev0.RuntimeContext, ...) error
- func IsGoFormula(command []string) bool
- func RenderTestSelection(selection *runtimev0.TestSelection) ([]string, error)
- func RunFormula(ctx context.Context, sourceDir string, command []string, selectors []string) (*runtimev0.TestResponse, error)
- func RunGoBuild(ctx context.Context, env *GoRunnerEnvironment, sourceLocation string, ...) (string, error)
- func RunGoLint(ctx context.Context, env *GoRunnerEnvironment, sourceLocation string, ...) (string, error)
- func SetGoRuntimeContext(runtimeContext *basev0.RuntimeContext) *basev0.RuntimeContext
- func SplitSourceDir(sourceDir string) (moduleRoot, buildTarget string)
- type BuildOptions
- type DockerEnv
- type DockerTemplating
- type GoAgentSettings
- type GoRunnerEnvironment
- func CreateRunner(ctx context.Context, runtimeCtx *basev0.RuntimeContext, cfg RunnerConfig) (*GoRunnerEnvironment, error)
- func NewDockerGoRunner(ctx context.Context, image *resources.DockerImage, dir string, ...) (*GoRunnerEnvironment, error)
- func NewNativeGoRunner(ctx context.Context, dir string, relativeSource string) (*GoRunnerEnvironment, error)
- func NewNixGoRunner(ctx context.Context, dir string, relativeSource string) (*GoRunnerEnvironment, error)
- func (r *GoRunnerEnvironment) BinName(hash string) string
- func (r *GoRunnerEnvironment) BuildBinary(ctx context.Context) error
- func (r *GoRunnerEnvironment) BuildTargetPath(ctx context.Context, hash string) string
- func (r *GoRunnerEnvironment) Env() runners.RunnerEnvironment
- func (r *GoRunnerEnvironment) GoModuleHandling(ctx context.Context) error
- func (r *GoRunnerEnvironment) Init(ctx context.Context) error
- func (r *GoRunnerEnvironment) LocalCacheDir(ctx context.Context) string
- func (r *GoRunnerEnvironment) LocalTargetPath(ctx context.Context, hash string) string
- func (r *GoRunnerEnvironment) Runner(args ...string) (runners.Proc, error)
- func (r *GoRunnerEnvironment) Setup(ctx context.Context)
- func (r *GoRunnerEnvironment) Shutdown(ctx context.Context) error
- func (r *GoRunnerEnvironment) Stop(ctx context.Context) error
- func (r *GoRunnerEnvironment) UsedCache() bool
- func (r *GoRunnerEnvironment) WithCGO(b bool)
- func (r *GoRunnerEnvironment) WithDebugSymbol(debug bool)
- func (r *GoRunnerEnvironment) WithEnvironmentVariables(ctx context.Context, envs ...*resources.EnvironmentVariable)
- func (r *GoRunnerEnvironment) WithFile(file string, location string)
- func (r *GoRunnerEnvironment) WithGoModDir(dir string)
- func (r *GoRunnerEnvironment) WithLocalCacheDir(dir string)
- func (r *GoRunnerEnvironment) WithOutput(out io.Writer)
- func (r *GoRunnerEnvironment) WithPort(ctx context.Context, port uint32)
- func (r *GoRunnerEnvironment) WithRaceConditionDetection(b bool)
- func (r *GoRunnerEnvironment) WithWorkspace(b bool)
- type LineCapture
- type LintOptions
- type RunnerConfig
- type StreamingTestWriter
- type StructuredTestRun
- type TestEvent
- type TestOptions
- type TestSummary
Constants ¶
const ( SettingHotReload = "hot-reload" SettingDebugSymbols = "debug-symbols" SettingRaceConditionDetectionRun = "race-condition-detection-run" )
Setting name constants shared by all Go agents.
const ( // EnvErrorModuleBroken: the module metadata itself prevents any build or // test — go.mod parse errors, unsupported go directive, missing go.sum // entries, unresolvable module requirements. Repairing the module // metadata is an ENVIRONMENT action, not a code fix. EnvErrorModuleBroken = "go-module-broken" // EnvErrorToolchainMissing: the `go` binary is not available to the // runner at all. EnvErrorToolchainMissing = "go-toolchain-missing" // EnvErrorNoTestsExecuted / EnvErrorNoTestsMatchedSelectors mirror the // python runner's structural zero-case reasons — SAME strings, so // language-blind consumers route both runners identically. A run that // grades zero cases is never a pass, even on exit 0. EnvErrorNoTestsExecuted = "no-tests-executed" EnvErrorNoTestsMatchedSelectors = "no-tests-matched-selectors" )
Environment-block reasons for Go module runs. They appear inside the `env-blocked (<reason>): <detail>` result message.
const MaxCapturedOutputBytesPerCase = 32 * 1024 // 32 KiB
MaxCapturedOutputBytesPerCase caps the per-case captured_output stored in the structured TestResponse. Above this we truncate + surface the count via TestTruncation. Tuned to "enough for a stack trace and a hundred lines of context" — most failures fit in a few KB; multi-MB stdout is a tool misconfiguration.
const OutputGoTestJSON = "gotest-json"
OutputGoTestJSON is the formula output format produced by `go test -json`.
Variables ¶
This section is empty.
Functions ¶
func BuildGoDocker ¶ added in v0.1.155
func BuildGoDocker(ctx context.Context, builder *services.BuilderWrapper, req *builderv0.BuildRequest, location string, requirements *builders.Dependencies, builderFS embed.FS, goVersion, alpineVersion string, opts ...func(*DockerTemplating)) (*builderv0.BuildResponse, error)
BuildGoDocker generates templates and builds a Docker image for a Go service.
func ClassifyEnvError ¶ added in v0.2.13
ClassifyEnvError decides whether a failed run was blocked by the ENVIRONMENT (reason != "") rather than failing tests or broken user code. The classification is deliberately narrow: module metadata / toolchain / module-resolution problems are environmental; a compile error in the code under test is NOT (that is the code's fault and an edit can fix it).
func DeployGoKubernetes ¶ added in v0.1.155
func DeployGoKubernetes(ctx context.Context, builder *services.BuilderWrapper, req *builderv0.DeploymentRequest, envVars *resources.EnvironmentVariableManager, deploymentFS embed.FS) (*builderv0.DeploymentResponse, error)
DeployGoKubernetes deploys a Go service to Kubernetes. Handles environment variable setup, config maps, secrets, and kustomize generation.
func DeriveFormula ¶ added in v0.2.13
DeriveFormula derives the module-local test formula for a Go module: `go test -json ./...` when sourceDir contains a go.mod. Mirrors python.DeriveFormula's contract (ok=false when this plugin does not own the project).
func DestroyGoRuntime ¶ added in v0.1.155
func DestroyGoRuntime(ctx context.Context, runtimeCtx *basev0.RuntimeContext, runtimeImage *resources.DockerImage, cacheLocation, workspacePath, relativeSource, uniqueName string) error
DestroyGoRuntime cleans up cache and shuts down container runtime if applicable.
func IsGoFormula ¶ added in v0.2.13
IsGoFormula reports whether a supplied formula command belongs to this runner (a `go` invocation).
func RenderTestSelection ¶ added in v0.2.15
func RenderTestSelection(selection *runtimev0.TestSelection) ([]string, error)
RenderTestSelection translates a language-neutral selection to the private selector inputs consumed by the Go runner. This translation belongs in the execution plugin: callers never construct Go package or -run syntax.
func RunFormula ¶ added in v0.2.13
func RunFormula(ctx context.Context, sourceDir string, command []string, selectors []string) (*runtimev0.TestResponse, error)
RunFormula executes a Go test formula in sourceDir and returns the structured proto response. Command may be empty (derived via DeriveFormula). Selectors follow the shared convention: package-shaped selectors ("./pkg", "example.com/x") REPLACE the command's package scope; other selectors are LITERAL test names ("TestFoo", "TestFoo/case") — regexp-escaped and anchored into `-run`, so "TestFoo" never selects "TestFooBar" and bracketed subtest names stay literal.
The run always sets GOWORK=off: a formula run tests THIS module in isolation, and a go.work in any parent directory (common when fixtures live inside a bigger repo) must not leak into module resolution.
func RunGoBuild ¶ added in v0.1.155
func RunGoBuild(ctx context.Context, env *GoRunnerEnvironment, sourceLocation string, envVars []*resources.EnvironmentVariable, opts ...BuildOptions) (string, error)
RunGoBuild runs `go build` with an optional target and returns combined output.
func RunGoLint ¶ added in v0.1.155
func RunGoLint(ctx context.Context, env *GoRunnerEnvironment, sourceLocation string, envVars []*resources.EnvironmentVariable, opts ...LintOptions) (string, error)
RunGoLint runs `go vet` with an optional target and returns combined output.
func SetGoRuntimeContext ¶ added in v0.1.155
func SetGoRuntimeContext(runtimeContext *basev0.RuntimeContext) *basev0.RuntimeContext
SetGoRuntimeContext resolves which backend the Go plugin runs on. The Go plugin's preference order is LOCAL-FIRST — "run locally if you can, then nix, then docker": native → nix → container.
The incoming kind is an ENVIRONMENT hint, not a hard pin: `native`, `nix`, and `free` all mean "host-based", and the plugin auto-detects the best AVAILABLE host backend. So a Docker-free run whose global default is `nix` still runs Go natively when the Go toolchain is present — no flake needed, and nothing hard-fails on a missing one (the bug that broke `codefly run` without Docker). Only an explicit `container` request forces Docker isolation. Hard per-service/ per-agent choices still flow in via preferences.codefly.yaml: pinning `container` is honored here; pinning `native`/`nix` resolves through the same local-first order (native wins when the toolchain is present).
nil-safe. Returns a fresh RuntimeContext — callers assign it to their struct.
func SplitSourceDir ¶ added in v0.1.155
SplitSourceDir splits a source directory like "code/cmd/server" into a module root ("code") and a build target ("./cmd/server"). For "code" alone, returns ("code", ".").
Types ¶
type BuildOptions ¶ added in v0.1.155
type BuildOptions struct {
// Target is a package path (e.g. "./handlers") or empty for "./...".
Target string
}
BuildOptions controls how go build is invoked.
type DockerTemplating ¶ added in v0.1.155
type DockerTemplating struct {
Components []string
Envs []DockerEnv
GoVersion string
AlpineVersion string
SourceDir string // e.g. "code/cmd/server" — the Go main package location
ModuleRoot string // e.g. "code" — where go.mod lives
BuildTarget string // e.g. "./cmd/server" — package to build (relative to ModuleRoot)
}
DockerTemplating holds template parameters for Dockerfile generation.
type GoAgentSettings ¶ added in v0.1.155
type GoAgentSettings struct {
HotReload bool `yaml:"hot-reload"`
DebugSymbols bool `yaml:"debug-symbols"`
RaceConditionDetectionRun bool `yaml:"race-condition-detection-run"`
WithCGO bool `yaml:"with-cgo"`
WithWorkspace bool `yaml:"with-workspace"`
SourceDir string `yaml:"source-dir"`
}
GoAgentSettings holds settings common to all Go service agents. Agent-specific settings (e.g. RestEndpoint for go-grpc) are defined in each agent and embed this struct.
func (*GoAgentSettings) GoSourceDir ¶ added in v0.1.155
func (s *GoAgentSettings) GoSourceDir() string
GoSourceDir returns the configured source directory, defaulting to "code".
func (*GoAgentSettings) Validate ¶ added in v0.2.15
func (s *GoAgentSettings) Validate() error
Validate rejects source roots that can escape the service directory. The value is loaded from service.codefly.yaml and is later passed to directory creation, tool execution, Docker mounts, and destroy paths, so validation belongs at the shared settings boundary rather than in one runtime backend.
type GoRunnerEnvironment ¶
type GoRunnerEnvironment struct {
// contains filtered or unexported fields
}
GoRunnerEnvironment is a runner for go - Init:
- go modules handling
- binary building
- Start:
- start the binary
func CreateRunner ¶ added in v0.1.155
func CreateRunner(ctx context.Context, runtimeCtx *basev0.RuntimeContext, cfg RunnerConfig) (*GoRunnerEnvironment, error)
CreateRunner creates a GoRunnerEnvironment based on the runtime context. For container runtimes, the caller is responsible for port bindings (agent-specific).
func NewDockerGoRunner ¶
func NewDockerGoRunner(ctx context.Context, image *resources.DockerImage, dir string, relativeSource string, name string) (*GoRunnerEnvironment, error)
func NewNativeGoRunner ¶ added in v0.1.89
func NewNixGoRunner ¶ added in v0.1.155
func NewNixGoRunner(ctx context.Context, dir string, relativeSource string) (*GoRunnerEnvironment, error)
NewNixGoRunner creates a Go runner that uses Nix for reproducible builds. All tools (go, buf, protoc) come from the flake.nix in dir.
func (*GoRunnerEnvironment) BinName ¶
func (r *GoRunnerEnvironment) BinName(hash string) string
func (*GoRunnerEnvironment) BuildBinary ¶
func (r *GoRunnerEnvironment) BuildBinary(ctx context.Context) error
func (*GoRunnerEnvironment) BuildTargetPath ¶
func (r *GoRunnerEnvironment) BuildTargetPath(ctx context.Context, hash string) string
func (*GoRunnerEnvironment) Env ¶
func (r *GoRunnerEnvironment) Env() runners.RunnerEnvironment
func (*GoRunnerEnvironment) GoModuleHandling ¶
func (r *GoRunnerEnvironment) GoModuleHandling(ctx context.Context) error
func (*GoRunnerEnvironment) LocalCacheDir ¶
func (r *GoRunnerEnvironment) LocalCacheDir(ctx context.Context) string
func (*GoRunnerEnvironment) LocalTargetPath ¶
func (r *GoRunnerEnvironment) LocalTargetPath(ctx context.Context, hash string) string
func (*GoRunnerEnvironment) Runner ¶ added in v0.1.89
func (r *GoRunnerEnvironment) Runner(args ...string) (runners.Proc, error)
func (*GoRunnerEnvironment) Setup ¶
func (r *GoRunnerEnvironment) Setup(ctx context.Context)
func (*GoRunnerEnvironment) Shutdown ¶
func (r *GoRunnerEnvironment) Shutdown(ctx context.Context) error
func (*GoRunnerEnvironment) UsedCache ¶
func (r *GoRunnerEnvironment) UsedCache() bool
func (*GoRunnerEnvironment) WithCGO ¶ added in v0.1.144
func (r *GoRunnerEnvironment) WithCGO(b bool)
func (*GoRunnerEnvironment) WithDebugSymbol ¶
func (r *GoRunnerEnvironment) WithDebugSymbol(debug bool)
func (*GoRunnerEnvironment) WithEnvironmentVariables ¶
func (r *GoRunnerEnvironment) WithEnvironmentVariables(ctx context.Context, envs ...*resources.EnvironmentVariable)
func (*GoRunnerEnvironment) WithFile ¶
func (r *GoRunnerEnvironment) WithFile(file string, location string)
func (*GoRunnerEnvironment) WithGoModDir ¶
func (r *GoRunnerEnvironment) WithGoModDir(dir string)
func (*GoRunnerEnvironment) WithLocalCacheDir ¶
func (r *GoRunnerEnvironment) WithLocalCacheDir(dir string)
func (*GoRunnerEnvironment) WithOutput ¶
func (r *GoRunnerEnvironment) WithOutput(out io.Writer)
func (*GoRunnerEnvironment) WithPort ¶
func (r *GoRunnerEnvironment) WithPort(ctx context.Context, port uint32)
func (*GoRunnerEnvironment) WithRaceConditionDetection ¶
func (r *GoRunnerEnvironment) WithRaceConditionDetection(b bool)
func (*GoRunnerEnvironment) WithWorkspace ¶ added in v0.1.144
func (r *GoRunnerEnvironment) WithWorkspace(b bool)
type LineCapture ¶ added in v0.1.155
type LineCapture struct {
// contains filtered or unexported fields
}
LineCapture implements io.Writer and accumulates all written data with newlines preserved (the native runner strips trailing whitespace).
func (*LineCapture) String ¶ added in v0.1.155
func (lc *LineCapture) String() string
type LintOptions ¶ added in v0.1.155
type LintOptions struct {
// Target is a package path (e.g. "./handlers") or empty for "./...".
Target string
}
LintOptions controls how go vet is invoked.
type RunnerConfig ¶ added in v0.1.155
type RunnerConfig struct {
RuntimeImage *resources.DockerImage
WorkspacePath string
RelativeSource string
UniqueName string
CacheLocation string
Settings *GoAgentSettings
}
RunnerConfig holds the parameters needed to create a Go runner environment.
type StreamingTestWriter ¶ added in v0.1.155
type StreamingTestWriter struct {
LineCapture
OnEvent func(TestEvent)
}
StreamingTestWriter is a LineCapture that ALSO invokes a callback for every `go test -json` event as it arrives. Used when callers want real-time per-test progress rather than waiting for the full TestSummary at the end — typical case is forwarding events to a TUI via the agent's log channel.
Non-JSON lines are buffered but not surfaced through the callback, so the sink sees only structured events.
func (*StreamingTestWriter) Write ¶ added in v0.1.155
func (w *StreamingTestWriter) Write(p []byte) (int, error)
Write parses each line as a TestEvent and invokes OnEvent on success. Malformed lines are still buffered (via the embedded LineCapture) so ParseTestJSON can do its own defensive pass at the end — but they don't produce spurious events.
type StructuredTestRun ¶ added in v0.1.157
type StructuredTestRun struct {
// Started captures wall-clock start (the first event). Used to
// derive Run.duration when the run completes.
Started time.Time
// Suites — one per Go package, indexed by import path. The
// hierarchy is flat for Go (Go has no nested packages-in-packages
// grouping that go test surfaces; the proto's recursive shape
// supports nested for jest/pytest, unused here).
Suites map[string]*structuredSuite
// Coverage — populated when `go test -cover` is run; we observe
// the coverage line in package-output.
CoveragePct float32
// contains filtered or unexported fields
}
StructuredTestRun is the SOTA representation built by walking `go test -json` events. Holds the full hierarchy + per-case captured output. Convertible to runtimev0.TestResponse via ToProtoResponse, OR to the legacy flat *TestSummary via Legacy for callers that haven't migrated yet.
Build by calling ParseTestJSONStructured; access via the methods.
func ParseTestJSONStructured ¶ added in v0.1.157
func ParseTestJSONStructured(raw string) *StructuredTestRun
ParseTestJSONStructured walks every `go test -json` event in raw and returns the structured representation. Equivalent in coverage to ParseTestJSON but preserves the full tree.
Order of operations matters: we observe `run` before any other event for a case to set startedAt; the terminal action sets state + elapsed.
func (*StructuredTestRun) ToProtoResponse ¶ added in v0.1.157
func (r *StructuredTestRun) ToProtoResponse(runner, suiteName string, duration time.Duration) *runtimev0.TestResponse
ToProtoResponse constructs the runtimev0.TestResponse with BOTH the structured tree (preferred) AND the legacy flat fields populated (for backward compat). Single source of truth: every count/value in the legacy fields is computed from the structured tree.
runner is the runner identifier ("go-test"); suiteName echoes TestRequest.suite. duration is the wall-clock for the whole run (caller measures it).
type TestEvent ¶ added in v0.1.155
type TestEvent struct {
Action string `json:"Action"`
Package string `json:"Package"`
ImportPath string `json:"ImportPath"`
Test string `json:"Test"`
Output string `json:"Output"`
Elapsed float64 `json:"Elapsed"`
}
TestEvent represents one line of `go test -json` output.
type TestOptions ¶ added in v0.1.155
type TestOptions struct {
// Target is a package path (e.g. "./handlers", "./..."). For test
// name patterns prefer Filters — Target stays a directory scope.
// Empty runs all tests ("./...").
Target string
Verbose bool
Race bool
Timeout string // e.g. "30s"
// Coverage enables `-cover` instrumentation. Off by default because it
// roughly doubles test-binary compile time; opt in per TestRequest.
Coverage bool
// Filters are name regex patterns (multiple combined with OR) passed
// to `go test -run`. Equivalent to `-run "(p1|p2|...)"`.
Filters []string
// ExtraArgs are appended verbatim to the `go test` command line after
// our flags and the package — power-user passthrough.
ExtraArgs []string
// OnEvent, when non-nil, is invoked for every `go test -json` event as
// it is written to stdout. Enables real-time progress streaming to the
// TUI / logger without waiting for RunGoTests to return. The full
// summary is still built from the same underlying output after the
// process exits.
OnEvent func(TestEvent)
}
TestOptions controls how go test is invoked.
type TestSummary ¶ added in v0.1.155
type TestSummary struct {
Run int32
Passed int32
Failed int32
Skipped int32
Coverage float32
Failures []string
// contains filtered or unexported fields
}
TestSummary holds the parsed results of a `go test -json` run.
func ParseTestJSON ¶ added in v0.1.155
func ParseTestJSON(raw string) *TestSummary
ParseTestJSON parses the accumulated output of `go test -json -cover`.
func RunGoTests ¶ added in v0.1.155
func RunGoTests(ctx context.Context, env *GoRunnerEnvironment, sourceLocation string, envVars []*resources.EnvironmentVariable, opts ...TestOptions) (*TestSummary, error)
RunGoTests runs `go test -json` with optional target/flags and returns parsed results. `-cover` is opt-in via TestOptions.Coverage.
When env.LocalCacheDir(ctx) is non-empty, the full raw stdout from `go test -json` is persisted to <cacheDir>/last-test.json after the run regardless of pass/fail. This gives operators a debug surface richer than the TestSummary we return to the caller: failing tests can be re-parsed by hand, exit-2 collection errors are recoverable, and the exact set of events the agent saw is reproducible.
func (*TestSummary) SummaryLine ¶ added in v0.1.155
func (s *TestSummary) SummaryLine() string
SummaryLine formats a one-line summary string.