ci
import "github.com/danmestas/dagnats/ci"Package ci parses .dagnats/ci.yml CI specs and compiles them into dag.WorkflowDef instances ready for submission to a DagNats engine.
This package lives at the module root (not under internal/) so the dagnats-ci add-on module — which cannot import github.com/danmestas/dagnats’s internal/ tree — can depend on it directly, mirroring the openapi/ package’s promotion (#614). Core DagNats stays spec-agnostic: the mounted /v1/ci/* control-plane endpoints (internal/api/rest_ci.go) are the only place ci.yml awareness enters the control plane.
Index
- Constants
- func CompileYAMLWith(name string, spec []byte, opts CompileOptions) (CompileResult, []Diagnostic)
- func Parse(spec []byte) (Spec, []Diagnostic)
- type Check
- type CheckRetry
- type CompileOptions
- type CompileResult
- type Defaults
- type DeployStep
- type Diagnostic
- type On
- type PullRequest
- type Push
- type Schedule
- type Spec
Constants
DiagnosticsMax bounds how many diagnostics Parse/Compile will accumulate before giving up and reporting a single “too many errors” sentinel. A pathological or generated spec with thousands of independent errors must not turn a single compile request into an unbounded response body.
const DiagnosticsMax = 100func CompileYAMLWith
func CompileYAMLWith(name string, spec []byte, opts CompileOptions) (CompileResult, []Diagnostic)CompileYAMLWith compiles ci.yml bytes of either shape. A spec with a top-level jobs: key is the Actions-shaped spec; anything else compiles exactly as CompileYAML always has.
func Parse
func Parse(spec []byte) (Spec, []Diagnostic)Parse decodes YAML bytes into a Spec, accumulating a Diagnostic (rather than failing fast) for every field that fails to decode. It parses via yaml.Node first so each diagnostic carries the offending field’s Line and Column — authors can jump straight to the problem in their ci.yml instead of pattern-matching a stack-trace-flavored error string.
type Check
Check declares one CI check step backed by exactly one runner: Call (a Dagger function name, compiled to the “dagger.call” task type) or Task (a plain task type, compiled verbatim for any worker that speaks the ordinary worker protocol). Setting both, or neither, is a compile-time diagnostic (#671) — see compileCheck. Needs lists check names that must complete before this check runs. Timeout is a Go duration string (e.g. “15m”). Retries is shorthand for a fixed-delay retry policy; Retry is the full policy. Setting both is a compile-time diagnostic (#681) — see compileCheckRetry. WorkerGroup scopes this check to a worker group, mapped onto the compiled step’s WorkerGroup field (#695); combining it with a dotted compiled task type (including every call: check, which always compiles to “dagger.call”) is a compile-time diagnostic — see compileWorkerGroupDiagnostics.
type Check struct {
Call string `yaml:"call"`
Task string `yaml:"task"`
Needs []string `yaml:"needs"`
Timeout string `yaml:"timeout"`
Retries int `yaml:"retries"`
Retry *CheckRetry `yaml:"retry"`
WorkerGroup string `yaml:"worker_group"`
}type CheckRetry
CheckRetry is the full retry policy for a check, mapped onto dag.RetryPolicy by compileCheckRetry. InitialDelay and MaxDelay are Go duration strings, parsed the same way Check.Timeout is. Strategy is one of “fixed”, “linear”, “exponential” ("" defaults to “fixed”, matching dag.RetryPolicy’s zero value).
type CheckRetry struct {
MaxAttempts int `yaml:"max_attempts"`
Strategy string `yaml:"strategy"`
InitialDelay string `yaml:"initial_delay"`
MaxDelay string `yaml:"max_delay"`
Multiplier float64 `yaml:"multiplier"`
}type CompileOptions
CompileOptions carries the caller-supplied inputs a ci.yml cannot hold. TaskNamespace is required by a jobs: spec: every job compiles to task “<TaskNamespace>.job” in worker group TaskNamespace. A checks: spec ignores it.
type CompileOptions struct {
TaskNamespace string
}type CompileResult
CompileResult is a successful compile: the workflow, plus, for a jobs: spec, the spec’s on: block normalised to JSON (event name to filter object) and otherwise uninterpreted. On is nil for a checks: spec and whenever the compile reported diagnostics.
type CompileResult struct {
Workflow dag.WorkflowDef
On json.RawMessage
}type Defaults
Defaults carry workflow-wide settings inherited by every step. Module is the Dagger module path in the repository (usually “.”). Engine is advisory only in Phase 1; workers provision Dagger themselves.
type Defaults struct {
Module string `yaml:"module"`
Engine string `yaml:"engine"`
}type DeployStep
DeployStep declares an optional deploy stage that follows the CI checks. Call and Task are mutually exclusive, same as Check (#671) — see compileDeploy. Approval==“required” inserts a durable human-gate step before execution. Branches limits deployment to specific push targets (never PR heads). WorkerGroup mirrors Check.WorkerGroup (#695).
type DeployStep struct {
Call string `yaml:"call"`
Task string `yaml:"task"`
Needs []string `yaml:"needs"`
Approval string `yaml:"approval"`
Branches []string `yaml:"branches"`
Timeout string `yaml:"timeout"`
WorkerGroup string `yaml:"worker_group"`
}type Diagnostic
Diagnostic reports one problem found while parsing or compiling a ci.yml spec. Line and Column are 1-based YAML source positions (0 when the diagnostic has no source position, e.g. one raised inside Compile after the original bytes are no longer available — see Compile’s doc comment). Field names the offending ci.yml field or check/deploy step, when known.
type Diagnostic struct {
Line int `json:"line,omitempty"`
Column int `json:"column,omitempty"`
Field string `json:"field,omitempty"`
Message string `json:"message"`
}func Compile
func Compile(name string, s Spec) (dag.WorkflowDef, []Diagnostic)Compile converts a parsed Spec into a dag.WorkflowDef ready for the DagNats engine. name becomes WorkflowDef.Name. Unlike the pre-#633 fail-fast compiler, every problem found (unknown Needs references, invalid timeouts, unsupported deploy config, dag.Validate failures) is accumulated into the returned Diagnostic slice instead of stopping at the first one, so a spec author fixes every mistake in one pass. The returned WorkflowDef is valid (has passed dag.Validate) only when the Diagnostic slice is empty.
Diagnostics raised here have no YAML source position (Line/Column are 0) because Compile receives an already-decoded Spec, not the original bytes. Callers that hold the raw ci.yml text should use CompileYAML instead, which threads Parse’s positions through for the fields it can decode.
func CompileYAML
func CompileYAML(name string, spec []byte) (dag.WorkflowDef, []Diagnostic)CompileYAML is the thin composition of Parse and Compile for callers that hold ci.yml bytes directly (the CLI, the /v1/ci/compile handler). Parse diagnostics — which do carry source positions — short-circuit before Compile ever runs, since a Spec that failed to decode has no meaningful checks/deploy to compile.
type On
On describes which GitHub events trigger the CI run.
type On struct {
PullRequest *PullRequest `yaml:"pull_request"`
Push *Push `yaml:"push"`
Schedule *Schedule `yaml:"schedule"`
}type PullRequest
PullRequest restricts CI runs to the listed target branches.
type PullRequest struct {
Branches []string `yaml:"branches"`
}type Push
Push restricts CI runs to the listed push target branches.
type Push struct {
Branches []string `yaml:"branches"`
}type Schedule
Schedule triggers CI on a cron expression, routed through a DagNats cron trigger. This is a DagNats differentiator — ephemeral CI runners have no cron primitive.
type Schedule struct {
Cron string `yaml:"cron"`
}type Spec
Spec is the parsed form of a .dagnats/ci.yml file. The On block records which GitHub events trigger CI; Checks and Deploy describe what to run.
type Spec struct {
On On `yaml:"on"`
Defaults Defaults `yaml:"defaults"`
Checks map[string]Check `yaml:"checks"`
Deploy *DeployStep `yaml:"deploy"`
}Generated by gomarkdoc