contracts

package
v0.1.17 Latest Latest
Warning

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

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

Documentation

Overview

build_gate_config.go defines Build Gate validation configuration types.

These types configure how Build Gate validation runs before/after mig execution.

build_gate_image_rule.go defines Build Gate image mapping types for stack-based image selection.

These types configure how Build Gate resolves runtime images when Stack Gate is enabled. Image rules map stack expectations (language, release, tool) to container images with specificity-based resolution.

## Resolution Algorithm

The resolver selects images based on specificity:

  • Specificity 4: language + tool + release (most specific, highest priority)
  • Specificity 3: language + tool
  • Specificity 2: language + release
  • Specificity 1: language-only (broad fallback)

When multiple rules match, the highest specificity wins. Ties at the same specificity level with different images are configuration errors.

## Related Files

  • build_gate_image_rule_parse.go: Parsing from map[string]any
  • build_gate_image_rule_wire.go: Wire serialization to map[string]any
  • build_gate_image_resolver.go: Runtime resolution implementation

build_gate_image_rule_parse.go provides parsing functions for Build Gate image rules.

These functions parse BuildGateImageRule from map[string]any intermediate representations (from JSON/YAML input).

command_spec.go provides polymorphic command handling for mig specs.

CommandSpec represents container commands that can be specified in two forms:

  • Shell string: Executed via /bin/sh -c (e.g., "echo hello && ls -la")
  • Exec array: Executed directly without shell wrapper (e.g., ["/bin/sh", "-c", "echo"])

Both forms are first-class citizens of the mig spec schema, enabling:

  • Simple commands using a single shell string for convenience.
  • Complex commands using exec arrays for precise control over arguments.

The type implements JSON and YAML marshaling/unmarshaling to support both forms transparently in spec files.

hydra.go defines Hydra canonical stored-entry parsers and validators for the envs/in/out/home/tmp contract fields.

Canonical stored-entry formats:

  • in: "shortHash:dst" where dst starts with /in/
  • out: "shortHash:dst" where dst starts with /out/
  • home: "shortHash:dst{:ro}" where dst is $HOME-relative (no leading /)
  • tmp: "shortHash:dst" where dst starts with /tmp/

shortHash is a hex-only, colon-free prefix of the full content hash.

Package contracts defines shared workflow types.

migs_spec.go provides the core typed model for Mig run specifications. This eliminates drift between CLI/server/nodeagent spec parsing by providing a single source of truth for spec structure.

## Canonical Spec Shape

The MigSpec type supports a single canonical shape:

  • All runs use steps[] (even single-step runs).
  • Global build gate policy lives under build_gate.

## Related Files

The Mig spec implementation is split across several files:

  • migs_spec.go: Core types (MigSpec, MigStep) and validation
  • command_spec.go: Polymorphic command handling (CommandSpec)
  • build_gate_config.go: Build gate configuration types
  • migs_spec_parse.go: JSON parsing functions

## Usage

Parse specs using ParseMigSpecJSON (in migs_spec_parse.go):

spec, err := contracts.ParseMigSpecJSON(jsonBytes)
if err != nil {
    return err // structured validation error
}
// Use typed fields: spec.Steps, spec.BuildGate, etc.

migs_spec_parse.go provides JSON parsing for Mig specifications.

Usage:

spec, err := contracts.ParseMigSpecJSON(jsonBytes)
if err != nil {
    return err // structured validation error with field paths
}

YAML files are accepted at the CLI boundary by loading into map[string]any, marshaling to JSON, and validating via ParseMigSpecJSON.

job_image.go provides stack-aware image resolution for mig specs.

This file implements the JobImage type that supports two canonical forms:

  • Universal image (string): A single image used for all build stacks.
  • Stack-specific image (map): Different images per detected build stack.

Both forms are intentionally supported as first-class citizens of the mig spec schema. The dual-form design enables:

  • Simple configurations using a single image string for stack-agnostic migs.
  • Optimized configurations using stack-specific images for tools like Maven or Gradle that benefit from dedicated container environments.

## Stack Resolution Rules

When resolving an image for a given stack:

  1. If JobImage is a string, return that string (universal image).
  2. If JobImage is a map: a. Prefer an exact stack key match (e.g., "java-maven", "java-gradle"). b. Fall back to "default" when present and no exact match exists. c. Return an error when neither a matching key nor "default" is present.

## Supported Stack Names

The following stack names are recognized for image resolution:

  • "java-maven": Maven-based Java projects (pom.xml detected)
  • "java-gradle": Gradle-based Java projects (build.gradle detected)
  • "java": Generic Java projects (no build tool detected)
  • "unknown": No recognized stack markers found
  • "default": Fallback key in stack maps

stack_gate_spec.go defines Stack Gate types for explicit stack expectations.

Stack Gate allows mig specs to declare explicit expectations about the repository's technology stack (language, build tool, release version). This enables:

  • Validation of contradictory multi-step runs before execution
  • Stack-based image selection for mig containers
  • Chain validation across step boundaries (outbound → inbound)

## Wire Format

Stack Gate configuration appears in the steps[] array:

steps:
  - name: java11-to-17
    image: ghcr.io/iw2rmb/ploy/migs-orw:latest
    stack:
      inbound:
        enabled: true
        expect: { language: java, tool: maven, release: "11" }
      outbound:
        enabled: true
        expect: { language: java, tool: maven, release: "17" }

stack_gate_spec_parse.go provides parsing functions for Stack Gate configuration.

These functions parse Stack Gate specs from map[string]any intermediate representations (from JSON/YAML input).

Index

Constants

View Source
const (
	PLOYStackLanguageEnv = "PLOY_STACK_LANGUAGE"
	PLOYStackToolEnv     = "PLOY_STACK_TOOL"
	PLOYStackReleaseEnv  = "PLOY_STACK_RELEASE"
)
View Source
const SchemaVersion = "2025-09-27.1"

SchemaVersion identifies the JSON envelope version used by workflow run envelopes, checkpoints, and artifact messages. It must be included in all published envelopes so consumers can validate and evolve parsers safely.

Variables

View Source
var ValidHydraSections = map[string]bool{
	"pre_gate":  true,
	"post_gate": true,
	"mig":       true,
}

ValidHydraSections lists the known section names for typed Hydra overlays.

Functions

func ApplyBuildGatePhaseToGateSpec

func ApplyBuildGatePhaseToGateSpec(spec *StepGateSpec, phase *BuildGatePhaseConfig)

ApplyBuildGatePhaseToGateSpec copies the gate execution fields from a BuildGatePhaseConfig into the corresponding fields of a StepGateSpec. StackDetect is set only when phase.Stack has a non-empty mode.

func CopyEnv

func CopyEnv(env map[string]string) map[string]string

CopyEnv returns a shallow copy of the given environment map. Returns nil when the input is empty or nil.

func ExpandImageTemplate

func ExpandImageTemplate(image string, stack *StackExpectation) (string, error)

ExpandImageTemplate expands stack and env placeholders in image templates.

Supported stack placeholders:

  • ${stack.language}
  • ${stack.release}
  • ${stack.tool}

Supported env placeholders:

  • $VAR
  • ${VAR}

Returns an error when:

  • an unknown stack placeholder is used
  • a required stack value is unavailable
  • an environment variable placeholder is unresolved

func MarshalJobMeta

func MarshalJobMeta(m *JobMeta) ([]byte, error)

MarshalJobMeta encodes a JobMeta struct to JSON bytes suitable for storing in jobs.meta JSONB.

Returns an error if m is nil or if the metadata fails validation. Callers must provide a valid JobMeta with a recognized Kind field.

func MergeEnv

func MergeEnv(base, override map[string]string) map[string]string

MergeEnv returns a new map containing all entries from base with override entries applied on top. Returns nil when both inputs are empty or nil.

func MigSpecSchemaJSON

func MigSpecSchemaJSON() ([]byte, error)

MigSpecSchemaJSON returns the embedded mig JSON Schema bytes.

func ParseReleaseValue

func ParseReleaseValue(v any, field string) (string, error)

ParseReleaseValue converts a release value (string, int, or float) to a string. This normalizes map-backed JSON/YAML values so all parser paths share the same release coercion semantics.

func StackFieldsMatch

func StackFieldsMatch(lang, tool, release, wantLang, wantTool, wantRelease string) bool

StackFieldsMatch compares two (language, tool, release) tuples. Language and tool are compared case-insensitively after trimming whitespace. Release is compared after trimming only (case-sensitive). Empty "want" fields are treated as wildcards (always match).

func ValidateHomeDestination

func ValidateHomeDestination(dst string) error

ValidateHomeDestination validates a home destination path without requiring a full canonical entry. The destination must be relative, non-empty, cleaned, and free of path traversal.

func ValidateHydraHomeEntries

func ValidateHydraHomeEntries(entries []string, prefix string) error

ValidateHydraHomeEntries validates a slice of canonical `home` entries.

func ValidateHydraInEntries

func ValidateHydraInEntries(entries []string, prefix string) error

ValidateHydraInEntries validates a slice of canonical `in` entries.

func ValidateHydraOutEntries

func ValidateHydraOutEntries(entries []string, prefix string) error

ValidateHydraOutEntries validates a slice of canonical `out` entries.

func ValidateHydraSection

func ValidateHydraSection(section string) error

ValidateHydraSection returns an error if section is not a known Hydra section.

func ValidateHydraTmpEntries

func ValidateHydraTmpEntries(entries []string, prefix string) error

ValidateHydraTmpEntries validates a slice of canonical `tmp` entries.

func ValidateMigSpecJSON

func ValidateMigSpecJSON(raw []byte) error

ValidateMigSpecJSON validates raw JSON against the embedded mig JSON Schema.

Types

type BuildGateConfig

type BuildGateConfig struct {
	// Disabled skips Build Gate jobs when true.
	Disabled bool `json:"disabled,omitempty" yaml:"disabled,omitempty"`

	// Pre configures stack detection policy for the pre-gate phase.
	Pre *BuildGatePhaseConfig `json:"pre,omitempty" yaml:"pre,omitempty"`

	// Post configures stack detection policy for the post-gate phase.
	Post *BuildGatePhaseConfig `json:"post,omitempty" yaml:"post,omitempty"`

	// Images provides mig-level image mapping overrides for Build Gate image resolution.
	// These rules override the default mapping file.
	Images []BuildGateImageRule `json:"images,omitempty" yaml:"images,omitempty"`
}

BuildGateConfig configures Build Gate validation for a mig run.

type BuildGateImageMapping

type BuildGateImageMapping struct {
	// Images holds the image rules from this source.
	Images []BuildGateImageRule
}

BuildGateImageMapping holds rules from a single source for validation. Each precedence level (default file, cluster inline, mig override) has its own mapping that is validated independently before merging.

func (BuildGateImageMapping) Validate

func (m BuildGateImageMapping) Validate(prefix string) error

Validate checks that the mapping is well-formed. Validation rules:

  • Each rule must have language (required)
  • Each rule must have image (required)
  • No duplicate selectors within this mapping

The prefix parameter is used for error messages (e.g., "build_gate.images").

type BuildGateImageRule

type BuildGateImageRule struct {
	// Stack holds the stack expectation to match against.
	// Language is required. Release and Tool are optional wildcards.
	Stack StackExpectation `json:"stack,omitempty" yaml:"stack,omitempty"`

	// Image is the container image URL to use when this rule matches.
	// Required field.
	Image string `json:"image,omitempty" yaml:"image,omitempty"`
}

BuildGateImageRule maps a stack expectation to a Build Gate runtime image. Each rule matches requests where the expectation fields match (or are wildcards).

func (BuildGateImageRule) Matches

func (r BuildGateImageRule) Matches(exp StackExpectation) bool

Matches returns true if this rule matches the given expectation. A rule matches when:

  • Language matches exactly (both required)
  • Release matches exactly when rule.Release is set
  • Tool matches exactly when rule.Tool is set

func (BuildGateImageRule) SelectorKey

func (r BuildGateImageRule) SelectorKey() string

SelectorKey returns a unique key for duplicate detection. Two rules with the same selector key define the same match criteria and should not coexist within the same precedence level.

Format: "language:release:tool" (empty release/tool become "*").

func (BuildGateImageRule) Specificity

func (r BuildGateImageRule) Specificity() int

Specificity returns the matching priority of this rule. Higher values indicate more specific matches:

  • 4: language + tool + release
  • 3: language + tool
  • 2: language + release
  • 1: language-only

type BuildGateLogFinding

type BuildGateLogFinding struct {
	Code     string `json:"code,omitempty"`
	Severity string `json:"severity"`
	Message  string `json:"message"`
	Evidence string `json:"evidence,omitempty"`
}

BuildGateLogFinding records a normalized build log finding used for guidance.

func (BuildGateLogFinding) Validate

func (f BuildGateLogFinding) Validate() error

Validate ensures log finding entries include required guidance details.

type BuildGatePhaseConfig

type BuildGatePhaseConfig struct {
	// Stack configures stack detection behavior for this gate phase.
	Stack *BuildGateStackConfig `json:"stack,omitempty" yaml:"stack,omitempty"`
}

BuildGatePhaseConfig configures a single phase of Build Gate execution. This holds optional stack detection configuration and prep overrides.

type BuildGateResourceUsage

type BuildGateResourceUsage struct {
	// Limits configured for the container (0 means unlimited/not set).
	LimitNanoCPUs    int64 `json:"limit_nano_cpus"`
	LimitMemoryBytes int64 `json:"limit_memory_bytes"`

	// Observed usage during the container lifetime.
	CPUTotalNs      uint64 `json:"cpu_total_ns"`
	MemUsageBytes   uint64 `json:"mem_usage_bytes"`
	MemMaxBytes     uint64 `json:"mem_max_bytes"`
	BlkioReadBytes  uint64 `json:"blkio_read_bytes"`
	BlkioWriteBytes uint64 `json:"blkio_write_bytes"`
	SizeRwBytes     *int64 `json:"size_rw_bytes,omitempty"`
}

BuildGateResourceUsage captures container limits and observed usage metrics from the gate execution container.

type BuildGateStackConfig

type BuildGateStackConfig struct {
	Mode     BuildGateStackMode `json:"mode,omitempty" yaml:"mode,omitempty"`
	Language string             `json:"language,omitempty" yaml:"language,omitempty"`
	Tool     string             `json:"tool,omitempty" yaml:"tool,omitempty"`
	Release  string             `json:"release,omitempty" yaml:"release,omitempty"`
}

BuildGateStackConfig configures expected stack information for a gate phase.

func (*BuildGateStackConfig) UnmarshalJSON

func (s *BuildGateStackConfig) UnmarshalJSON(data []byte) error

UnmarshalJSON handles numeric release values (e.g., YAML `release: 11` → JSON number).

type BuildGateStackMode

type BuildGateStackMode string

BuildGateStackMode controls how a phase stack config interacts with detection.

const (
	BuildGateStackModeForced   BuildGateStackMode = "forced"
	BuildGateStackModeStrict   BuildGateStackMode = "strict"
	BuildGateStackModeFallback BuildGateStackMode = "fallback"
)

type BuildGateStageMetadata

type BuildGateStageMetadata struct {
	LogDigest    types.Sha256Digest           `json:"log_digest,omitempty"`
	StaticChecks []BuildGateStaticCheckReport `json:"static_checks,omitempty"`
	// ExecutedCommand is the exact gate command shell payload executed by the
	// gate container.
	ExecutedCommand string `json:"executed_command,omitempty"`
	// Detected captures the resolved gate stack identity used for this gate
	// execution, including optional release matching.
	Detected    *StackExpectation     `json:"detected_stack,omitempty"`
	LogFindings []BuildGateLogFinding `json:"log_findings,omitempty"`
	// RuntimeImage is the container image name used to run the gate container.
	// Not serialized in JSON APIs.
	RuntimeImage string `json:"-"`
	// StackGate captures the outcome of Stack Gate pre-check validation.
	// Present only when Stack Gate mode is enabled.
	StackGate *StackGateResult `json:"stack_gate,omitempty"`
	// LogsText carries the raw build logs text for node-local processing.
	// Not serialized in JSON APIs.
	LogsText string `json:"-"`
	// Resources summarizes container limits and observed usage for the gate run.
	// Not serialized in JSON APIs.
	Resources *BuildGateResourceUsage `json:"-"`
	// BugSummary is a short one-line description of the gate failure.
	// Max 200 chars, no newlines.
	BugSummary string `json:"bug_summary,omitempty"`
}

BuildGateStageMetadata captures build gate metadata published with checkpoints.

func (BuildGateStageMetadata) DetectedStack

func (m BuildGateStageMetadata) DetectedStack() MigStack

DetectedStack returns the MigStack derived from the first static check's tool. This provides deterministic stack identification for stack-aware image selection in mig steps.

The detected stack is derived from the Build Gate's tool detection:

  • "maven" tool → MigStackJavaMaven
  • "gradle" tool → MigStackJavaGradle
  • "java" tool → MigStackJava
  • unknown/empty → MigStackUnknown

This method ensures the same stack value is visible to mig executions, enabling consistent image resolution.

func (BuildGateStageMetadata) DetectedStackExpectation

func (m BuildGateStageMetadata) DetectedStackExpectation() *StackExpectation

DetectedStackExpectation returns the normalized detected stack expectation. For backward compatibility with older metadata payloads, it falls back to static_checks[0] when detected_stack is absent.

func (BuildGateStageMetadata) Validate

func (m BuildGateStageMetadata) Validate() error

Validate ensures build gate metadata entries are well formed.

type BuildGateStaticCheckFailure

type BuildGateStaticCheckFailure struct {
	RuleID   string `json:"rule_id,omitempty"`
	File     string `json:"file,omitempty"`
	Line     int    `json:"line,omitempty"`
	Column   int    `json:"column,omitempty"`
	Severity string `json:"severity"`
	Message  string `json:"message"`
}

BuildGateStaticCheckFailure captures a single diagnostic from a static check tool.

func (BuildGateStaticCheckFailure) Validate

func (f BuildGateStaticCheckFailure) Validate() error

Validate ensures static check failure entries include required details.

type BuildGateStaticCheckReport

type BuildGateStaticCheckReport struct {
	Language string                        `json:"language,omitempty"`
	Tool     string                        `json:"tool"`
	Passed   bool                          `json:"passed"`
	Failures []BuildGateStaticCheckFailure `json:"failures,omitempty"`
}

BuildGateStaticCheckReport summarises an individual static analysis invocation.

func (BuildGateStaticCheckReport) Validate

func (r BuildGateStaticCheckReport) Validate() error

Validate ensures the static check report is well formed.

type BuildMeta

type BuildMeta struct {
	// Tool identifies the build tool (e.g., "maven", "gradle", "npm", "bazel").
	Tool string `json:"tool,omitempty"`
	// Command is the full command line executed (for diagnostics).
	Command string `json:"command,omitempty"`
	// StatusDetails provides additional context on build outcome.
	StatusDetails string `json:"status_details,omitempty"`
	// Metrics contains arbitrary build metrics (e.g., compilation time, test count).
	Metrics map[string]interface{} `json:"metrics,omitempty"`
}

BuildMeta captures metadata for build tool invocations stored in jobs.meta. This consolidates fields previously tracked in the separate builds table.

type CommandSpec

type CommandSpec struct {
	// Shell holds the command when specified as a single shell string.
	// When non-empty, the command is executed via ["/bin/sh", "-c", Shell].
	Shell string

	// Exec holds the command when specified as an exec array.
	// When non-nil, the command is executed directly without a shell wrapper.
	Exec []string
}

CommandSpec represents a container command as either a shell string or exec array. This type encapsulates the polymorphic command representation in mig specs.

JSON/YAML Examples:

# Shell string form (executed via /bin/sh -c):
command: "echo hello && ls -la"

# Exec array form (executed directly):
command: ["/bin/sh", "-c", "echo hello"]

func ParseCommandSpec

func ParseCommandSpec(v any) (CommandSpec, error)

ParseCommandSpec parses a command value from map-backed JSON/YAML input. Supported forms:

  • string: shell command
  • []string: exec command
  • []any: exec command elements must all be strings

func (CommandSpec) IsEmpty

func (c CommandSpec) IsEmpty() bool

IsEmpty returns true if no command is specified.

func (CommandSpec) IsZero

func (c CommandSpec) IsZero() bool

IsZero lets encoding/json omit empty commands from parent structs.

func (CommandSpec) MarshalJSON

func (c CommandSpec) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler for CommandSpec. Serializes as a string when Shell is set, or as an array when Exec is set.

func (CommandSpec) MarshalYAML

func (c CommandSpec) MarshalYAML() (interface{}, error)

MarshalYAML implements yaml.Marshaler for CommandSpec.

func (CommandSpec) ToSlice

func (c CommandSpec) ToSlice() []string

ToSlice converts the command to a []string suitable for container execution. Returns nil if the command is empty.

Conversion rules:

  • Exec array: returned as-is
  • Shell string: wrapped as ["/bin/sh", "-c", Shell]
  • Empty: returns nil

func (*CommandSpec) UnmarshalJSON

func (c *CommandSpec) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler for CommandSpec. Accepts both string and array forms from JSON.

func (*CommandSpec) UnmarshalYAML

func (c *CommandSpec) UnmarshalYAML(node *yaml.Node) error

UnmarshalYAML implements yaml.Unmarshaler for CommandSpec.

type GateClaimContext

type GateClaimContext struct {
	CycleName string `json:"cycle_name"`
}

GateClaimContext carries concrete gate execution routing.

func (*GateClaimContext) Normalize

func (c *GateClaimContext) Normalize()

type JobImage

type JobImage struct {
	// Universal holds the image when specified as a single string.
	// When non-empty, this image is used regardless of detected stack.
	Universal string

	// ByStack holds stack-specific images when image is specified as a map.
	// Keys are stack names (e.g., "java-maven", "java-gradle", "default").
	// When non-nil and non-empty, stack resolution rules apply.
	ByStack map[MigStack]string
}

JobImage represents a mig container image specification supporting two canonical forms: universal images (single string) and stack-specific images (map by stack). Both forms are first-class schema options.

YAML/JSON Examples:

# Universal image (string form) — used for all stacks:
image: ghcr.io/iw2rmb/ploy/migs-openrewrite:latest

# Stack-specific images (map form) — per-stack optimization:
image:
  default: ghcr.io/iw2rmb/ploy/migs-openrewrite:latest
  java-maven: ghcr.io/iw2rmb/ploy/orw-cli:latest
  java-gradle: ghcr.io/iw2rmb/ploy/orw-cli:latest

func ParseJobImage

func ParseJobImage(v any) (JobImage, error)

ParseJobImage parses an image specification from an untyped value. Both canonical forms are accepted:

  • string: Parsed as a universal image (used for all stacks).
  • map[string]any or map[string]string: Parsed as stack-specific images.

Returns an empty JobImage for nil input without error.

func (JobImage) IsEmpty

func (m JobImage) IsEmpty() bool

IsEmpty returns true if no image is specified in either form.

func (JobImage) IsStackSpecific

func (m JobImage) IsStackSpecific() bool

IsStackSpecific returns true if the image is specified as a stack map.

func (JobImage) IsUniversal

func (m JobImage) IsUniversal() bool

IsUniversal returns true if the image is specified as a universal string.

func (JobImage) MarshalJSON

func (m JobImage) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler for JobImage. Serializes as a string when Universal is set, or as a map when ByStack is set.

func (JobImage) MarshalYAML

func (m JobImage) MarshalYAML() (any, error)

MarshalYAML implements yaml.Marshaler for JobImage. Serializes as a string when Universal is set, or as a map when ByStack is set.

func (JobImage) ResolveImage

func (m JobImage) ResolveImage(stack MigStack) (string, error)

ResolveImage resolves the image for the given stack using resolution rules:

  1. If JobImage is a universal string, return that string.
  2. If JobImage is a stack map: a. Prefer an exact stack key match. b. Fall back to "default" when present. c. Return an error when neither exists.

The stack parameter should come from Build Gate detection (e.g., "java-maven"). An empty JobImage returns an error. An empty stack uses "unknown" as default.

func (JobImage) String

func (m JobImage) String() string

String returns a human-readable representation for debugging.

func (*JobImage) UnmarshalJSON

func (m *JobImage) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler for JobImage. Accepts both string and map forms from JSON.

func (*JobImage) UnmarshalYAML

func (m *JobImage) UnmarshalYAML(value *yaml.Node) error

UnmarshalYAML implements yaml.Unmarshaler for JobImage. Accepts both string and map forms from YAML.

type JobKind

type JobKind string

JobKind identifies the execution type for a job in the unified queue. All execution units (migs, gates, builds) are stored in the jobs table with their kind indicated by this field.

const (
	// JobKindMig indicates a mig execution job (pre_gate, mig, post_gate).
	JobKindMig JobKind = "mig"
	// JobKindGate indicates a build gate validation job.
	JobKindGate JobKind = "gate"
	// JobKindBuild indicates a build tool invocation job (maven, gradle, npm, etc.).
	JobKindBuild JobKind = "build"
)

func (JobKind) Valid

func (k JobKind) Valid() bool

Valid returns true if the job kind is a recognized value.

type JobMeta

type JobMeta struct {
	// Kind identifies the job type: "mig", "gate", or "build".
	Kind JobKind `json:"kind"`

	// GateMetadata contains build gate validation metadata when Kind is JobKindGate.
	// This includes static check results, log findings, and digest information.
	GateMetadata *BuildGateStageMetadata `json:"gate,omitempty"`

	// Build contains build tool metadata when Kind is JobKindBuild.
	// This includes tool name, command, status details, and metrics.
	Build *BuildMeta `json:"build,omitempty"`

	// MigStepName stores the user-defined step name from MigSpec.Steps[i].Name
	// for mig jobs. Used by the CLI to display a friendly name in --follow mode.
	// Only populated for mig jobs (kind="mig") when a step name is provided.
	MigStepName string `json:"mig_step_name,omitempty"`

	// MigStepIndex stores the concrete mig step index selected for this job.
	// Populated for mig jobs so execution does not depend on job name parsing.
	MigStepIndex *int `json:"mig_step_index,omitempty"`

	// GateCycleName stores the concrete gate cycle name used by gate jobs.
	// Examples: pre-gate, post-gate.
	GateCycleName string `json:"gate_cycle_name,omitempty"`
}

JobMeta is the structured metadata stored in jobs.meta JSONB. It provides a unified schema for gate, build, and mig metadata, enabling the jobs table to serve as the single execution primitive for all workflow stages.

JSON shape example:

{
  "kind": "gate",
  "gate": { "log_digest": "...", "static_checks": [...] },
  "build": null
}

The kind field is always present and determines which optional metadata section (gate/build) is populated. Mig jobs typically have kind="mig" with no gate or build metadata.

func NewBuildJobMeta

func NewBuildJobMeta(build *BuildMeta) *JobMeta

NewBuildJobMeta creates a JobMeta for build tool invocation jobs.

func NewGateJobMeta

func NewGateJobMeta(gate *BuildGateStageMetadata) *JobMeta

NewGateJobMeta creates a JobMeta for gate validation jobs. The gate metadata can be populated later via UpdateGateMeta.

func NewMigJobMeta

func NewMigJobMeta() *JobMeta

NewMigJobMeta creates a JobMeta for mig execution jobs. This is a convenience constructor for the common case of mig jobs that don't carry gate or build metadata.

func NewMigJobMetaWithStepName

func NewMigJobMetaWithStepName(stepName string) *JobMeta

NewMigJobMetaWithStepName creates a JobMeta for mig execution jobs with a user-defined step name. The step name is used by the CLI to display a friendly name in --follow mode.

func UnmarshalJobMeta

func UnmarshalJobMeta(data []byte) (*JobMeta, error)

UnmarshalJobMeta decodes JSON bytes from jobs.meta JSONB into a JobMeta struct.

Returns an error for invalid payloads:

  • Empty bytes, empty JSON objects ("{}"), or JSON null are rejected.
  • Missing or invalid "kind" field is rejected.
  • Payloads that fail JobMeta.Validate() are rejected.

All job metadata must now be structured with an explicit kind field. Use NewMigJobMeta/NewGateJobMeta/NewBuildJobMeta to create valid metadata.

func (JobMeta) Validate

func (m JobMeta) Validate() error

Validate ensures JobMeta is well-formed.

type ManifestReference

type ManifestReference struct {
	Name    string `json:"name"`
	Version string `json:"version"`
}

ManifestReference identifies a workflow manifest by name and version.

func (ManifestReference) Validate

func (m ManifestReference) Validate() error

Validate requires both name and version to be non‑empty strings.

type MigClaimContext

type MigClaimContext struct {
	StepIndex int `json:"step_index"`
}

MigClaimContext carries the concrete mig step selected for execution.

type MigSpec

type MigSpec struct {

	// JobID is the claimed job ID injected into the spec at claim time.
	JobID types.JobID `json:"job_id,omitempty" yaml:"job_id,omitempty"`

	// APIVersion is an optional schema version identifier (e.g., "ploy.mig/v1alpha1").
	// Informational only; the control plane forwards specs as opaque JSON.
	APIVersion string `json:"apiVersion,omitempty" yaml:"apiVersion,omitempty"`

	// Name is an optional stable name for publishing and selecting this spec.
	Name string `json:"name,omitempty" yaml:"name,omitempty"`

	// Description is optional human-readable context for this spec.
	Description string `json:"description,omitempty" yaml:"description,omitempty"`

	// Steps holds the ordered list of mig steps.
	// A spec must contain at least one step.
	Steps []MigStep `json:"steps,omitempty" yaml:"steps,omitempty"`

	// Envs holds environment variables applied to every step (step envs overrides on conflicts).
	Envs map[string]string `json:"envs,omitempty" yaml:"envs,omitempty"`

	// BuildGate configures Build Gate validation policy.
	// Applies globally to all steps.
	BuildGate *BuildGateConfig `json:"build_gate,omitempty" yaml:"build_gate,omitempty"`

	// BundleMap maps content hashes used in In/Out/Home/Tmp entries to their
	// spec bundle download identifiers (bundle IDs). Populated by the CLI
	// compiler during spec submission. The nodeagent uses this to resolve
	// shortHash → bundleID for resource download during materialization.
	BundleMap map[string]string `json:"bundle_map,omitempty" yaml:"bundle_map,omitempty"`
}

MigSpec is the canonical typed representation of a mig run specification. All specs use steps[]; multi-step runs have len(steps) > 1.

Wire compatibility: This struct marshals to/from JSON with stable field names that match the existing spec schema. The JSON tags are the source of truth for wire format compatibility.

Validation: Use Validate() to check structural correctness after parsing. ParseMigSpecJSON calls Validate() automatically and returns structured errors for invalid input.

func ParseMigSpecJSON

func ParseMigSpecJSON(data []byte) (*MigSpec, error)

ParseMigSpecJSON parses a mig specification from JSON bytes. Returns a validated MigSpec or an error for invalid/malformed input.

func (MigSpec) Validate

func (s MigSpec) Validate() error

Validate checks that the spec is structurally valid. Returns nil if valid, or a descriptive error for invalid specs.

Validation rules:

  • steps must be non-empty and each step must have a non-empty image.
  • Stack Gate phases must not be disabled with expectations set.

type MigStack

type MigStack string

MigStack represents a detected build stack for image resolution.

const (
	// MigStackJavaMaven indicates a Maven-based Java project (pom.xml present).
	MigStackJavaMaven MigStack = "java-maven"

	// MigStackJavaGradle indicates a Gradle-based Java project (build.gradle present).
	MigStackJavaGradle MigStack = "java-gradle"

	// MigStackJava indicates a generic Java project (no specific build tool).
	MigStackJava MigStack = "java"

	// MigStackUnknown indicates no recognized stack markers were found.
	MigStackUnknown MigStack = "unknown"

	// MigStackDefault is the fallback key used in stack-specific image maps.
	MigStackDefault MigStack = "default"
)

func ToolToMigStack

func ToolToMigStack(tool string) MigStack

ToolToMigStack converts a Build Gate tool name to a MigStack constant. Tool names come from BuildGateStaticCheckReport.Tool after gate execution.

Conversion rules:

  • "maven" → MigStackJavaMaven
  • "gradle" → MigStackJavaGradle
  • "java" → MigStackJava
  • "" or unknown → MigStackUnknown

This function enables deterministic stack-aware image selection after Build Gate detection, ensuring mig steps use the correct stack-specific images based on the workspace's detected build system.

type MigStep

type MigStep struct {
	// Name is an optional human-readable name for this step.
	Name string `json:"name,omitempty" yaml:"name,omitempty"`

	// Image is the container image for this step (required).
	// Supports both universal images (string) and stack-specific images (map).
	Image JobImage `json:"image,omitempty" yaml:"image,omitempty"`

	// Command is the container command override for this step (optional).
	// Can be a shell string or an exec array.
	Command CommandSpec `json:"command,omitempty,omitzero" yaml:"command,omitempty"`

	// Envs holds environment variables specific to this step.
	Envs map[string]string `json:"envs,omitempty" yaml:"envs,omitempty"`

	// Options holds strict, step-scoped runtime options.
	Options MigStepOptions `json:"options,omitempty,omitzero" yaml:"options,omitempty"`

	// In lists canonical read-only input entries ("shortHash:/in/dst").
	In []string `json:"in,omitempty" yaml:"in,omitempty"`

	// Out lists canonical read-write output entries ("shortHash:/out/dst").
	Out []string `json:"out,omitempty" yaml:"out,omitempty"`

	// Home lists canonical home-relative entries ("shortHash:dst{:ro}").
	Home []string `json:"home,omitempty" yaml:"home,omitempty"`

	// Tmp lists canonical writable temporary entries ("shortHash:/tmp/dst").
	Tmp []string `json:"tmp,omitempty" yaml:"tmp,omitempty"`

	// Stack configures Stack Gate validation for this step.
	// Inbound validates pre-mig expectations; Outbound validates post-mig expectations.
	Stack *StackGateSpec `json:"stack,omitempty" yaml:"stack,omitempty"`
}

MigStep describes a single mig step in a run (steps[] array). Each step has its own image, command, and environment configuration. Steps execute sequentially with shared workspace, each running gate+mig.

type MigStepOptions

type MigStepOptions struct {
	MountDockerSocket bool `json:"mount_docker_socket,omitempty" yaml:"mount_docker_socket,omitempty"`
}

MigStepOptions describes strict runtime options accepted under steps[].options.

func (MigStepOptions) IsZero

func (o MigStepOptions) IsZero() bool

type ParsedStoredEntry

type ParsedStoredEntry struct {
	Hash     string
	Dst      string
	ReadOnly bool
}

ParsedStoredEntry holds the result of parsing a canonical stored entry.

func ParseStoredHomeEntry

func ParseStoredHomeEntry(s string) (ParsedStoredEntry, error)

ParseStoredHomeEntry parses a canonical `home` entry: "shortHash:dst{:ro}". dst must be relative (no leading /) and must not traverse above $HOME. Mode defaults to rw; optional :ro suffix forces read-only.

func ParseStoredInEntry

func ParseStoredInEntry(s string) (ParsedStoredEntry, error)

ParseStoredInEntry parses a canonical `in` entry: "shortHash:dst". dst must be absolute and start with "/in/".

func ParseStoredOutEntry

func ParseStoredOutEntry(s string) (ParsedStoredEntry, error)

ParseStoredOutEntry parses a canonical `out` entry: "shortHash:dst". dst must be absolute and start with "/out/".

func ParseStoredTmpEntry

func ParseStoredTmpEntry(s string) (ParsedStoredEntry, error)

ParseStoredTmpEntry parses a canonical `tmp` entry: "shortHash:dst". dst must be absolute and start with "/tmp/".

func (ParsedStoredEntry) CanonicalHomeEntry

func (p ParsedStoredEntry) CanonicalHomeEntry() string

CanonicalHomeEntry reconstructs the canonical stored home entry string from parsed fields: "hash:dst" or "hash:dst:ro".

type RepoMaterialization

type RepoMaterialization struct {
	URL           types.RepoURL   `json:"url,omitempty"`
	BaseRef       types.GitRef    `json:"base_ref,omitempty"`
	Commit        types.CommitSHA `json:"commit,omitempty"`
	WorkspaceHint string          `json:"workspace_hint,omitempty"`
}

RepoMaterialization describes repository inputs required for a workflow run.

func (RepoMaterialization) Validate

func (r RepoMaterialization) Validate() error

Validate ensures repo metadata is well formed when provided.

type StackExpectation

type StackExpectation struct {
	// Language is the expected programming language (e.g., "java", "go", "python").
	Language string `json:"language,omitempty" yaml:"language,omitempty"`

	// Tool is the expected build tool (e.g., "maven", "gradle", "npm").
	Tool string `json:"tool,omitempty" yaml:"tool,omitempty"`

	// Release is the expected version/release (e.g., "11", "17", "3.9").
	// Stored as string to handle both integer and string release values in YAML.
	Release string `json:"release,omitempty" yaml:"release,omitempty"`
}

StackExpectation describes expected stack characteristics. All fields are optional; omitted fields indicate "any" for that dimension.

func NormalizeStackExpectation

func NormalizeStackExpectation(expect *StackExpectation) *StackExpectation

NormalizeStackExpectation returns a trimmed copy of expect. Nil or fully-empty values normalize to nil.

func (StackExpectation) Equal

func (e StackExpectation) Equal(other StackExpectation) bool

Equal returns true if both expectations have identical field values.

func (StackExpectation) IsEmpty

func (e StackExpectation) IsEmpty() bool

IsEmpty returns true if no expectation fields are set.

func (*StackExpectation) UnmarshalJSON

func (e *StackExpectation) UnmarshalJSON(data []byte) error

UnmarshalJSON handles numeric release values (e.g., YAML `release: 11` → JSON number).

type StackGatePhaseSpec

type StackGatePhaseSpec struct {
	// Enabled controls whether this phase is active.
	// When false, the phase is skipped entirely.
	Enabled bool `json:"enabled,omitempty" yaml:"enabled,omitempty"`

	// Expect defines the stack expectations for this phase.
	// Only validated when Enabled is true.
	Expect *StackExpectation `json:"expect,omitempty" yaml:"expect,omitempty"`
}

StackGatePhaseSpec configures a single phase (inbound or outbound) of Stack Gate.

func (StackGatePhaseSpec) Equal

Equal returns true if both phase specs have identical configuration.

func (StackGatePhaseSpec) IsEmpty

func (p StackGatePhaseSpec) IsEmpty() bool

IsEmpty returns true if the phase spec has default values (disabled, no expect).

type StackGateResult

type StackGateResult struct {
	Enabled      bool              `json:"enabled"`
	Expected     *StackExpectation `json:"expected,omitempty"`
	Detected     *StackExpectation `json:"detected,omitempty"`
	RuntimeImage string            `json:"runtime_image,omitempty"`
	Result       string            `json:"result,omitempty"` // "pass", "mismatch", "unknown"
	Reason       string            `json:"reason,omitempty"`
}

StackGateResult captures the outcome of Stack Gate pre-check validation.

func (StackGateResult) Validate

func (r StackGateResult) Validate() error

Validate ensures stack gate result is well formed.

type StackGateSpec

type StackGateSpec struct {
	// Inbound configures pre-mig stack validation.
	// Validates that the repository matches expectations before the mig runs.
	Inbound *StackGatePhaseSpec `json:"inbound,omitempty" yaml:"inbound,omitempty"`

	// Outbound configures post-mig stack validation.
	// Validates that the mig produced the expected stack transformation.
	Outbound *StackGatePhaseSpec `json:"outbound,omitempty" yaml:"outbound,omitempty"`
}

StackGateSpec configures Stack Gate for a mig step. Inbound validates pre-mig expectations; Outbound validates post-mig expectations.

func (StackGateSpec) Equal

func (s StackGateSpec) Equal(other StackGateSpec) bool

Equal returns true if both stack gate specs have identical configuration.

func (StackGateSpec) IsEmpty

func (s StackGateSpec) IsEmpty() bool

IsEmpty returns true if no stack gate configuration is present.

func (StackGateSpec) MarshalJSON

func (s StackGateSpec) MarshalJSON() ([]byte, error)

MarshalJSON returns nil for empty StackGateSpec so that parent structs with omitempty will omit the field entirely.

type StageName

type StageName string

StageName identifies a workflow stage by name.

It is a distinct type to prevent mixing arbitrary strings with stage identifiers in contracts while preserving JSON compatibility (marshals as a plain string).

type StepArtifact

type StepArtifact struct {
	Name string
	Type string
}

StepArtifact describes an artifact emitted after execution.

type StepGateSpec

type StepGateSpec struct {
	Enabled bool
	Env     map[string]string

	// ImageOverrides holds mig-level image mapping overrides for gate execution.
	// These rules override the default mapping file.
	ImageOverrides []BuildGateImageRule

	// StackDetect configures stack detection behavior for this gate.
	// mode=forced uses the configured language/release and detects tool when omitted.
	// mode=strict requires detection to match the configured stack.
	// mode=fallback uses detection when complete, otherwise the configured stack.
	StackDetect *BuildGateStackConfig

	// RepoURL is the Git repository URL for remote gate execution.
	// Populated from StartRunRequest.RepoURL when building manifests.
	RepoURL types.RepoURL

	// RepoID is the repo identifier for this execution.
	// Used for gate job/runtime correlation.
	RepoID types.MigRepoID

	// Ref is the Git reference (commit SHA, branch, or tag) for remote gate execution.
	// Derived from CommitSHA > BaseRef precedence when building manifests.
	Ref types.GitRef

	// DiffPatch is an optional gzipped unified diff (base64-encoded) to apply
	// on top of the cloned repo_url+ref baseline, avoiding full archive uploads.
	// The diff captures all changes relative to the initial repo_url+ref clone.
	DiffPatch []byte

	// StackGate holds the Stack Gate configuration for this step.
	// Used for pre/post gate validation of stack expectations.
	StackGate *StepGateStackSpec
}

StepGateSpec configures Build Gate validation post step execution.

The RepoURL and Ref fields provide repo metadata for HTTP-based gate execution, enabling remote Build Gate workers to clone and validate the repository without requiring direct workspace access. These fields are populated from the run's StartRunRequest and threaded through manifests.

Ref precedence (set by manifest builders):

  1. CommitSHA — pinned commit when available (ensures deterministic validation).
  2. BaseRef — fallback for baseline validations.

type StepGateStackSpec

type StepGateStackSpec struct {
	// Enabled controls whether Stack Gate validation is active for this phase.
	Enabled bool

	// Expect holds the stack expectations to validate.
	// Only validated when Enabled is true.
	Expect *StackExpectation
}

StepGateStackSpec holds the effective Stack Gate configuration for a gate phase. This is threaded into manifests from the step's StackGateSpec.

type StepInput

type StepInput struct {
	Name        string
	MountPath   string
	Mode        StepInputMode
	SnapshotCID types.CID
	DiffCID     types.CID
	Hydration   *StepInputHydration
}

StepInput describes repository state presented to the container.

type StepInputArtifactRef

type StepInputArtifactRef struct {
	CID    types.CID          `json:"cid"`
	Digest types.Sha256Digest `json:"digest,omitempty"`
	Size   int64              `json:"size,omitempty"`
}

StepInputArtifactRef references a snapshot or diff artifact.

type StepInputHydration

type StepInputHydration struct {
	BaseSnapshot StepInputArtifactRef   `json:"base_snapshot,omitempty"`
	Diffs        []StepInputArtifactRef `json:"diffs,omitempty"`
	Repo         *RepoMaterialization   `json:"repo,omitempty"`
}

StepInputHydration describes how to materialise repository state for an input.

type StepInputMode

type StepInputMode string

StepInputMode describes how the input is mounted into the container.

const (
	// StepInputModeReadOnly mounts the input read-only.
	StepInputModeReadOnly StepInputMode = "ro"
	// StepInputModeReadWrite mounts the input read-write.
	StepInputModeReadWrite StepInputMode = "rw"
)

type StepManifest

type StepManifest struct {
	ID         types.StepID
	Name       string
	Image      string
	Command    []string
	Args       []string
	WorkingDir string
	Envs       map[string]string
	Inputs     []StepInput
	Outputs    []StepOutput
	Artifacts  []StepArtifact
	Gate       *StepGateSpec
	Resources  StepResourceSpec
	// Options holds arbitrary run-specific options.
	// Read options via OptionString/OptionBool helpers to avoid scattered type
	// assertions in callers. This field is not validated and values are never
	// logged.
	Options map[string]any

	// In lists canonical read-only input entries ("shortHash:/in/dst").
	In []string

	// Out lists canonical read-write output entries ("shortHash:/out/dst").
	Out []string

	// Home lists canonical home-relative entries ("shortHash:dst{:ro}").
	Home []string

	// Tmp lists canonical writable temporary entries ("shortHash:/tmp/dst").
	Tmp []string

	// BundleMap maps content hashes to spec bundle download identifiers.
	// The nodeagent uses this to resolve Hydra entry hashes → bundleIDs
	// for resource download during staged materialization.
	BundleMap map[string]string
}

StepManifest defines the execution contract for a single Mig step.

func (StepManifest) OptionBool

func (m StepManifest) OptionBool(key string) (bool, bool)

OptionBool returns the option value for key when it is of type bool. It returns the bool and true on exact type match; otherwise it returns false and false. The lookup is safe on a zero-value manifest or when Options is nil.

func (StepManifest) OptionString

func (m StepManifest) OptionString(key string) (string, bool)

OptionString returns the option value for key when it is of type string. It returns the string and true on exact type match; otherwise it returns an empty string and false. The lookup is safe on a zero-value manifest or when Options is nil.

func (StepManifest) Validate

func (m StepManifest) Validate() error

Validate ensures the manifest is well-formed.

type StepOutput

type StepOutput struct {
	Name string
	Path string
	Type string
}

StepOutput describes expected paths produced by the container.

type StepResourceSpec

type StepResourceSpec struct {
	CPU    types.CPUmilli
	Memory types.Bytes
	Disk   types.Bytes
	GPU    string
}

StepResourceSpec captures runtime resource hints.

func (StepResourceSpec) ToLimits

func (s StepResourceSpec) ToLimits() (nanoCPUs int64, memoryBytes int64, diskBytes int64, storageSizeOpt string)

ToLimits converts the resource hints into concrete container limit values.

Returns Docker‑compatible quantities:

  • nanoCPUs: 1e9 per CPU (millis → nanos via CPUmilli.DockerNanoCPUs).
  • memoryBytes: raw bytes for memory limit (0 means unlimited).
  • diskBytes: raw bytes for writable layer limit (best‑effort; 0 means unlimited).
  • storageSizeOpt: string form for Docker storage option "size" when supported by the storage driver (empty when unlimited).

type SubjectSet

type SubjectSet struct {
	CheckpointStream string
	ArtifactStream   string
	StatusStream     string
}

SubjectSet contains the per‑run subjects used for publishing workflow events. Empty strings are returned when the run ID is blank to signal that publishing should be skipped by callers.

func SubjectsForRun

func SubjectsForRun(runID types.RunID) SubjectSet

SubjectsForRun derives the subjects used to publish checkpoints, artifacts, and status events for a given run ID. When the provided run ID is empty or whitespace, all fields in the returned set are empty.

type WorkflowRun

type WorkflowRun struct {
	SchemaVersion string              `json:"schema_version"`
	RunID         types.RunID         `json:"run_id"`
	Manifest      ManifestReference   `json:"manifest"`
	Repo          RepoMaterialization `json:"repo,omitempty"`
}

WorkflowRun is the envelope used when submitting or claiming a workflow run. It carries the schema version, the opaque run identifier, the manifest reference (name/version), and optional repository materialization details for nodes to hydrate workspaces.

func (WorkflowRun) Validate

func (r WorkflowRun) Validate() error

Validate checks that required fields are present and that embedded structures are valid. It requires a non‑empty schema version and run ID, a valid `Manifest`, and (when provided) a valid `Repo`.

Jump to

Keyboard shortcuts

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