gitops

package
v0.7.0 Latest Latest
Warning

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

Go to latest
Published: Jul 11, 2026 License: AGPL-3.0, AGPL-3.0-only Imports: 21 Imported by: 0

Documentation

Overview

Package gitops provides Flux CD graph discovery, change impact analysis, and reconciliation coordination.

Core rule: if Flux already knows it, StageFreight discovers it — never asks for it. No duplicated topology config. No declared kustomization lists. Flux is truth. StageFreight is the intelligence + evidence layer.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func BuildKubeconfig

func BuildKubeconfig(ctx context.Context, cfg config.ClusterConfig, rctx *runtime.RuntimeContext, desired map[string]config.ToolConstraint) error

BuildKubeconfig creates an isolated kubeconfig for the target cluster. CA is resolved from environment: <PREFIX>_CA_FILE or <PREFIX>_CA_B64. OIDC token is resolved from STAGEFREIGHT_OIDC. All ephemeral files are registered for cleanup on rctx.Resolved.

func BuildRoots added in v0.7.0

func BuildRoots(graph *FluxGraph) []string

BuildRoots returns the unique, normalized, non-empty kustomization paths in the graph — the set of directories to `kustomize build` exactly once. Multiple Flux Kustomizations pointing at the same path collapse to a single root, so shared manifests are not rendered (and re-validated) once per owner. Deterministic: lexically sorted.

func CycleNodes added in v0.7.0

func CycleNodes(graph *FluxGraph) map[KustomizationKey]bool

CycleNodes returns the set of kustomizations that cannot be topologically placed — those in, or downstream of, a dependency cycle. These are the keys a validation verdict marks as failed with a cycle reason: the dependency intent is incoherent and Flux itself would deadlock on them.

func DanglingDeps added in v0.7.0

func DanglingDeps(graph *FluxGraph) map[KustomizationKey][]KustomizationKey

DanglingDeps returns, per kustomization, the dependsOn references that point at a kustomization not present in the discovered graph. The referrer is the key a validation verdict marks — its declared dependency cannot be satisfied from this repository.

func DuplicatePaths

func DuplicatePaths(graph *FluxGraph) map[string][]KustomizationKey

DuplicatePaths returns paths owned by multiple kustomizations.

func GetChangedFiles

func GetChangedFiles(repoDir, base, head string) ([]string, error)

GetChangedFiles returns files changed between two refs using three-dot (merge-base) diff semantics, with two-dot fallback if merge-base fails.

func NormalizePath

func NormalizePath(p string) string

NormalizePath cleans a path for consistent matching.

func SortKeys

func SortKeys(keys []KustomizationKey)

SortKeys sorts kustomization keys lexically by namespace/name.

func SortedKinds added in v0.7.0

func SortedKinds(m map[string]int) []string

SortedKinds returns the kinds of a count map in descending count, then name.

Types

type BootstrapState

type BootstrapState struct {
	Required bool
	Reason   string
}

BootstrapState indicates whether Flux bootstrapping is needed.

func DetectBootstrapRequired

func DetectBootstrapRequired(graph *FluxGraph) BootstrapState

DetectBootstrapRequired checks if Flux bootstrapping is needed. Stub for now — returns false. Hook wired for future extension.

type Finding added in v0.7.0

type Finding struct {
	Severity Status
	Source   string
	Message  string
	// Schema carries the normalized, provenance-bearing form of a schema-validation
	// finding (core-schema / crd-catalog): the offending field, interpreted rule, and
	// the raw validator transcript for the escape hatch. Nil for non-schema findings
	// (graph/render) — those use Message directly.
	Schema *SchemaFinding
}

Finding is one piece of evidence against a Kustomization. Severity carries its authority class and Source its provenance, so operators can distinguish "Kubernetes will reject this" (authoritative) from "a community catalog thinks this might be wrong" (heuristic). Sources: "graph" (dependsOn integrity), "render" (kustomize build / raw-manifest stream), "core-schema" (built-in Kubernetes schemas — authoritative), "crd-catalog" (datreeio CRD catalog — advisory; see docs/architecture/gitops-fluxcd-validation.md).

type FluxBackend

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

FluxBackend implements runtime.LifecycleBackend for Flux CD reconciliation.

func (*FluxBackend) Capabilities

func (f *FluxBackend) Capabilities() []runtime.Capability

func (*FluxBackend) Cleanup

func (f *FluxBackend) Cleanup(rctx *runtime.RuntimeContext)

Cleanup is handled by rctx.Resolved cleanup funcs registered in Prepare.

func (*FluxBackend) Execute

Execute runs flux reconcile on the planned set. Idempotent: repeated execution converges to the same state.

func (*FluxBackend) Name

func (f *FluxBackend) Name() string

func (*FluxBackend) Plan

Plan discovers the Flux graph, computes impact, and builds the reconcile set. Deterministic: identical config + inputs → identical output.

func (*FluxBackend) Prepare

func (f *FluxBackend) Prepare(ctx context.Context, cfg *config.Config, rctx *runtime.RuntimeContext) error

Prepare builds an isolated kubeconfig for the target cluster. Skipped if no cluster config is present (local dev).

func (*FluxBackend) Validate

func (f *FluxBackend) Validate(ctx context.Context, cfg *config.Config, rctx *runtime.RuntimeContext) error

Validate checks that the flux CLI is available and cluster config is complete.

type FluxGraph

type FluxGraph struct {
	Kustomizations map[KustomizationKey]KustomizationNode
	ReverseDeps    map[KustomizationKey][]KustomizationKey
}

FluxGraph is the discovered dependency graph of Flux Kustomizations.

func DiscoverFluxGraph

func DiscoverFluxGraph(root string) (*FluxGraph, error)

DiscoverFluxGraph walks the repo and discovers all Flux Kustomization objects. Builds forward and reverse dependency graphs. No config needed — everything is derived from the actual manifests.

type FluxReconcileResult

type FluxReconcileResult struct {
	Kustomization string
	Namespace     string
	Attempted     bool
	Success       bool
	Duration      time.Duration
	Ready         bool
	Message       string
}

FluxReconcileResult reports the outcome of reconciling one kustomization. Kept for backward compatibility with existing CLI output rendering.

func Reconcile

func Reconcile(rootDir string, keys []KustomizationKey, dryRun bool) []FluxReconcileResult

Reconcile executes flux reconcile on the given kustomizations in order. Legacy function — new code should use FluxBackend via the runtime.

type ImpactResult

type ImpactResult struct {
	ChangedFiles         []string
	DirectlyAffected     []KustomizationKey
	TransitivelyAffected []KustomizationKey
	ReconcileSet         []KustomizationKey // topologically sorted
	UnmappedFiles        []string           // changed files not under any kustomization path
}

ImpactResult describes which kustomizations are affected by a set of changes.

func ComputeImpact

func ComputeImpact(graph *FluxGraph, files []string) ImpactResult

ComputeImpact determines which kustomizations are affected by changed files. Walks the reverse dependency graph to find transitive dependents.

type KustomizationKey

type KustomizationKey struct {
	Namespace string
	Name      string
}

KustomizationKey uniquely identifies a Flux Kustomization. Identity is (namespace, name) — never bare name alone.

func Orphans

func Orphans(graph *FluxGraph) []KustomizationKey

Orphans returns kustomizations with no dependents and no dependencies.

func ReconcileOrder added in v0.7.0

func ReconcileOrder(graph *FluxGraph) []KustomizationKey

ReconcileOrder returns the kustomizations in dependency order: a kustomization's dependencies always appear before it. This is what Flux's own controller honors via spec.dependsOn — reconciling in this order accelerates convergence and makes the reconcile output read top-down instead of randomly.

Order is by dependency DEPTH (longest path from a root), then lexically within a depth — a wavefront that mirrors how Flux actually reconciles: Flux runs every kustomization concurrently and gates each on its deps being Ready, so the nodes sharing a depth are exactly the ones Flux fires together. Depth-first (not a greedy lexical walk) is what keeps a shallow leaf — e.g. a bootstrap Job that only dependsOn an early phase — in its own early wave instead of being pushed to the end just because a deeper node sorts before it lexically. Still a valid topological order (a node's depth is always strictly greater than any dep's) and deterministic (identical graphs → identical sequences).

DependsOn edges to kustomizations not present in the graph are ignored (Flux tolerates cross-source dependencies). Cycles are broken deterministically: any nodes that cannot be topologically placed are appended in lexical order so reconcile still covers the whole estate rather than silently dropping them.

func TopoSort

func TopoSort(graph *FluxGraph, subset []KustomizationKey) []KustomizationKey

TopoSort produces a deterministic topological order for a subset of the graph. Dependencies come before dependents. Ties broken by namespace/name sort.

func (KustomizationKey) String

func (k KustomizationKey) String() string

type KustomizationNode

type KustomizationNode struct {
	Key       KustomizationKey
	Path      string // normalized, repo-root relative
	DependsOn []KustomizationKey
	SourceRef string
}

KustomizationNode is a discovered Flux Kustomization with its dependencies.

type SchemaFinding added in v0.7.0

type SchemaFinding struct {
	Kind      string
	Name      string
	Version   string
	Field     string // dotted instance path incl. the offending property; "" if unparsed
	Rule      string // interpreted violation, phrased operator-side; "" if unparsed
	SchemaURL string // the schema authority the check ran against; "" if absent
	Raw       string // original validator message, verbatim (escape hatch)
}

SchemaFinding is the structured, provenance-carrying form of a schema-validation finding. It separates what we can MECHANICALLY DERIVE from the validator output (kind, name, the offending field, the violated rule) from the raw validator transcript (the escape hatch). Field and Rule are best-effort: when the message can't be parsed with confidence they stay empty and the renderer falls back to Raw. The renderer must never synthesize meaning the transcript doesn't support — no operator folklore, only statements derivable from schema + manifest + result.

func (SchemaFinding) Parsed added in v0.7.0

func (s SchemaFinding) Parsed() bool

Parsed reports whether the violation was understood well enough to render an interpreted line. When false, callers show Raw rather than inventing meaning.

type Status added in v0.7.0

type Status int

Status is a per-Kustomization verdict outcome.

const (
	Pass Status = iota
	Warn
	Fail
)

func (Status) String added in v0.7.0

func (s Status) String() string

type ValidationMeta added in v0.7.0

type ValidationMeta struct {
	Roots          int
	Skipped        string // non-empty: validation could not run (e.g. tool unavailable)
	KustomizeVer   string
	KubeconformVer string
	Validated      map[string]int // kind -> count checked against a known schema
	NoSchema       map[string]int // kind -> count with no available schema
}

ValidationMeta carries repository-scoped facts that are not per-Kustomization verdicts: tool versions, a skip reason, and schema coverage (kinds checked vs kinds with no available schema). Coverage gaps are reported, never failed.

func ValidateManifests added in v0.7.0

func ValidateManifests(ctx context.Context, rootDir string, desired map[string]config.ToolConstraint) (map[KustomizationKey]Verdict, *ValidationMeta, error)

ValidateManifests discovers the Flux graph and returns a verdict per Kustomization plus repository-scoped meta. The error return is reserved for infrastructure failures (graph discovery, pinned tool resolution); a repo with no Flux content returns an empty map and zero-roots meta.

type Verdict added in v0.7.0

type Verdict struct {
	Status   Status
	Findings []Finding
}

Verdict is the validation outcome for one Flux Kustomization.

Jump to

Keyboard shortcuts

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