build

package
v1.3.1 Latest Latest
Warning

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

Go to latest
Published: Jun 29, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package build executes a detected target as a subprocess and reports a structured pass/fail Result with captured output — the raw material the UI turns into a build report.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func EnvUp

func EnvUp(ctx context.Context, env []string, e *detect.ComposeEnv, out io.Writer, services ...string) error

EnvUp brings a compose env up (build, detached) using the given env, then waits for it to become healthy — the `run` counterpart of the env handling Run does inline. Mirrors scripts/test.sh (no --wait on the external podman-compose provider). Progress streams to out.

services, when non-empty, is a positional list of compose service names to bring up (instead of every profile-less service). The runner uses it in global mode to skip services that duplicate a sibling already running from its own repo.

func PrepareEnv

func PrepareEnv(ctx context.Context, t detect.Target, out io.Writer) ([]string, []string, error)

PrepareEnv builds the process environment for a target: os.Environ() plus, when the target has a compose env, Go-allocated host ports, their derived URLs/DSN, standard local test creds for referenced vars, and finally whatever scripts/setup-env.sh still defines (service constants). It is the single source of env truth shared by `build`/`test` (Run) and `run`. The `── env ──` / `── setup-env ──` progress is written to out.

func TearDown

func TearDown(ctx context.Context, e detect.ComposeEnv) error

TearDown removes ONE compose project's containers, volumes AND orphans — scoped to that env via `-p <project> -f <file>`, never a global podman wipe. --remove-orphans cleans up containers the current compose no longer declares (e.g. after a profile change), which is what otherwise triggers `container name … already in use / use --replace`.

Two-pass teardown:

  1. Graceful: `compose down -t 10`. 10s is generous for postgres' shutdown checkpoint (which can stretch past 2s once the DB has dirty buffers from migrations + key rotation), but still snappy on quit.
  2. Force fallback if pass 1 errored: podman pod rm -f + network rm -f scoped to this env. Order matters — removing the pod first frees its containers, which de-references the network so its rm can succeed. podman-compose 1.5.0 occasionally returns success while leaving a running container — that container holds its pod, which holds the network — and the next run then fails to claim the same project name. Errors at this stage are intentionally swallowed: the resources may already be gone (first pass partially succeeded), or may never have come up.

Pod / network naming follows podman-compose's conventions:

  • Pod: "pod_<project>" (podman_compose.py resolve_pod_name, line 2087)
  • Network: "<project>_api" (matches every current service's compose `networks: { api: }` declaration; if a future service uses a different network name we'll need to read e.Networks instead).

Types

type Conflict

type Conflict struct {
	Env        detect.ComposeEnv
	Containers []string
}

Conflict is a compose project that already has containers on the host — almost always the leftover of a previously aborted run that would collide with a target's env (deterministic project names mean the same env reuses the same project).

func EnvConflicts

func EnvConflicts(ctx context.Context, targets []detect.Target) []Conflict

EnvConflicts returns the distinct env projects among targets that already have containers (running or not). It is a fail-safe preflight: running on top of a half-up env from an aborted command is the bug we want to catch.

type LiveLog

type LiveLog struct {
	// contains filtered or unexported fields
}

LiveLog holds the most recent output line per target, written concurrently by the parallel runners and read by the TUI each spinner tick so devs get a brief idea of progress and can spot a stalled command early. A nil *LiveLog is a valid no-op (non-interactive path).

func NewLiveLog

func NewLiveLog() *LiveLog

func (*LiveLog) Line

func (l *LiveLog) Line(id string) string

Line returns the latest captured output line for target id ("" if none).

type Result

type Result struct {
	Target detect.Target

	// Success is true iff the process exited zero.
	Success bool

	// ExitErr is the non-nil error from a failed/aborted process (non-zero
	// exit, context cancellation, or a binary that could not be spawned).
	ExitErr error

	// Output is the combined stdout+stderr, trimmed. On success it is usually
	// noise; on failure it is the thing the user actually needs to see, so it
	// is always captured rather than streamed-and-dropped.
	Output string

	// Duration is wall-clock time spent in the subprocess.
	Duration time.Duration
}

Result is the outcome of running one detect.Target.

func Run

func Run(ctx context.Context, t detect.Target, timeout time.Duration, live *LiveLog) Result

Run executes t.Cmd with t.Args in t.Dir, capturing combined output. It blocks until the process exits or ctx is cancelled. timeout > 0 bounds the whole target (env up + command); env teardown still runs on a detached context so a timed-out target is always cleaned up. live (may be nil) receives the most recent output line for the live TUI tail. It never panics and never returns a partially-zero Result — every field is meaningful.

type Summary

type Summary struct {
	Total  int
	Passed int
	Failed int

	// CumulativeDuration is the sum of every target's own build time. Under
	// the interactive parallel runner this exceeds wall-clock time (overlapping
	// builds are counted in full each), so it is NOT what the report shows as
	// "took" — that is real elapsed time, tracked by the runner and passed in
	// separately. CumulativeDuration is kept as the total work performed.
	CumulativeDuration time.Duration
}

Summary aggregates a set of results for the report screen.

func Summarize

func Summarize(results []Result) Summary

Summarize folds results into counts and cumulative per-target build time. Wall-clock elapsed is the runner's responsibility, not derivable here.

Jump to

Keyboard shortcuts

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