golang

package
v0.2.18 Latest Latest
Warning

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

Go to latest
Published: Jul 15, 2026 License: MIT Imports: 32 Imported by: 0

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

View Source
const (
	SettingHotReload                 = "hot-reload"
	SettingDebugSymbols              = "debug-symbols"
	SettingRaceConditionDetectionRun = "race-condition-detection-run"
)

Setting name constants shared by all Go agents.

View Source
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.

View Source
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.

View Source
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

func ClassifyEnvError(raw string, runErr error) (reason, detail string)

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

DeployGoKubernetes deploys a Go service to Kubernetes. Handles environment variable setup, config maps, secrets, and kustomize generation.

func DeriveFormula added in v0.2.13

func DeriveFormula(sourceDir string) (cmd []string, output string, ok bool)

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

func IsGoFormula(command []string) bool

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

func SplitSourceDir(sourceDir string) (moduleRoot, buildTarget string)

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 DockerEnv added in v0.1.155

type DockerEnv struct {
	Key   string
	Value string
}

DockerEnv is a key-value pair for Docker environment variables.

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 NewNativeGoRunner(ctx context.Context, dir string, relativeSource string) (*GoRunnerEnvironment, error)

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 (*GoRunnerEnvironment) GoModuleHandling

func (r *GoRunnerEnvironment) GoModuleHandling(ctx context.Context) error

func (*GoRunnerEnvironment) Init

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) Stop

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

func (*LineCapture) Write added in v0.1.155

func (lc *LineCapture) Write(p []byte) (n int, err error)

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.

Jump to

Keyboard shortcuts

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