Documentation
¶
Overview ¶
Package renderer contains the logic for formatting and displaying diffs.
Index ¶
- Constants
- func FormatDiff(diffs []diffmatchpatch.Diff, options DiffOptions) string
- func GenerateDiffWithOptions(_ context.Context, current, desired *un.Unstructured, logger logging.Logger, ...) (*t.ResourceDiff, error)
- func GetLineDiff(oldText, newText string) []diffmatchpatch.Diff
- type AffectedResourcesSummary
- type ChangeDetail
- type CompDiffOutput
- type CompDiffRenderer
- type CompactDiffFormatter
- type CompositionDiff
- type DefaultCompDiffRenderer
- type DefaultDiffRenderer
- type DiffFormatter
- type DiffOptions
- type DiffRenderer
- type DownstreamChanges
- type FilterReason
- type FullDiffFormatter
- type OutputError
- type OutputFormat
- type OutputVersion
- type RevisionImpact
- type StructuredCompDiffRenderer
- type StructuredDiffOutput
- type StructuredDiffRenderer
- type Summary
- type XRImpact
- type XRStatus
Constants ¶
const PathLastAppliedConfiguration = "metadata.annotations[kubectl.kubernetes.io/last-applied-configuration]"
PathLastAppliedConfiguration is the ignore-path form of the annotation a client-side `kubectl apply` stamps on the object it applies. Exported because two callers must name the same path and must not drift apart: cleanupForDiff suppresses it from every rendered diff (see displayOnlyIgnoredPaths), and comp's revision-name prediction has to ask whether it is the *only* thing a composition differs by — in which case the resulting revision's identity is not predictable, because the value kubectl writes depends on the user's apply mode rather than on the file.
Variables ¶
This section is empty.
Functions ¶
func FormatDiff ¶
func FormatDiff(diffs []diffmatchpatch.Diff, options DiffOptions) string
FormatDiff formats a slice of diffs according to the provided options.
func GenerateDiffWithOptions ¶
func GenerateDiffWithOptions(_ context.Context, current, desired *un.Unstructured, logger logging.Logger, options DiffOptions) (*t.ResourceDiff, error)
GenerateDiffWithOptions produces a structured diff between two unstructured objects.
func GetLineDiff ¶
func GetLineDiff(oldText, newText string) []diffmatchpatch.Diff
GetLineDiff performs a proper line-by-line diff and returns the raw diffs.
Types ¶
type AffectedResourcesSummary ¶ added in v0.7.0
type AffectedResourcesSummary struct {
Total int `json:"total"`
WithChanges int `json:"withChanges"`
Unchanged int `json:"unchanged"`
WithErrors int `json:"withErrors"`
// FilteredByPolicy counts XRs excluded because of a Manual compositionUpdatePolicy
// (FilterReasonManualPolicy).
FilteredByPolicy int `json:"filteredByPolicy,omitempty"`
// FilteredBySelector counts XRs excluded because their compositionRevisionSelector does not match
// the diffed composition's labels (FilterReasonRevisionSelectorMismatch). Kept separate from
// FilteredByPolicy so the breakdown is visible even in default-discovery mode, where individual
// XR impacts are not surfaced.
FilteredBySelector int `json:"filteredBySelector,omitempty"`
// FilteredByDeletion counts XRs excluded because they are being deleted
// (FilterReasonDeleting). Kept separate from the other filter counters for the same reason:
// the breakdown stays visible in default-discovery mode.
FilteredByDeletion int `json:"filteredByDeletion,omitempty"`
}
AffectedResourcesSummary contains counts of affected resources by status.
type ChangeDetail ¶ added in v0.6.0
type ChangeDetail struct {
Type string `json:"type"`
APIVersion string `json:"apiVersion"`
Kind string `json:"kind"`
Name string `json:"name"`
Namespace string `json:"namespace,omitempty"`
Diff map[string]any `json:"diff"`
// DryRun is present only when this resource's desired state was not
// verified against the apiserver. See dt.DryRunInfo for why absence is the
// success case and what it does not promise for removals.
DryRun *dt.DryRunInfo `json:"dryRun,omitempty"`
}
ChangeDetail represents a single resource change.
This is the shared per-resource wire shape for both commands and both versions: it is reached via xrEntryWire.Changes, and in comp's v1 via DownstreamChanges.Changes. A field added here therefore surfaces in every output without per-command plumbing.
type CompDiffOutput ¶ added in v0.7.0
type CompDiffOutput struct {
Compositions []CompositionDiff
Errors []dt.OutputError // top-level errors (e.g., XRs that failed impact analysis)
// Warnings are non-fatal advisories raised during the run. Like the xr command's, they do not
// affect the exit code and are not attributed to a single composition — they are raised below the
// point where the owning composition is known. They have already been written to stderr when
// raised; this field carries them into structured output. The summary of unverified additions is
// not among them: the renderer derives it from the diffs (see compDryRunWarnings).
Warnings []dt.OutputWarning
}
CompDiffOutput is the top-level output for composition diffs (internal representation). This stores rich ResourceDiff data. Conversion to JSON happens in the renderer.
type CompDiffRenderer ¶ added in v0.7.0
type CompDiffRenderer interface {
// RenderCompDiff renders the complete composition diff output.
// Top-level and tool errors go to DiffOptions.Stderr and are included in
// structured output payloads. Per-composition messages (diffs, "no changes",
// per-composition errors) go to DiffOptions.Stdout as part of the diff narrative.
RenderCompDiff(output *CompDiffOutput) error
}
CompDiffRenderer renders composition diff results. Both human-readable and structured (JSON/YAML) renderers implement this interface.
func NewDefaultCompDiffRenderer ¶ added in v0.7.0
func NewDefaultCompDiffRenderer(logger logging.Logger, diffRenderer DiffRenderer, opts DiffOptions) CompDiffRenderer
NewDefaultCompDiffRenderer creates a new human-readable composition diff renderer.
func NewStructuredCompDiffRenderer ¶ added in v0.7.0
func NewStructuredCompDiffRenderer(logger logging.Logger, opts DiffOptions) CompDiffRenderer
NewStructuredCompDiffRenderer creates a new structured composition diff renderer.
type CompactDiffFormatter ¶
type CompactDiffFormatter struct{}
CompactDiffFormatter formats diffs with limited context lines.
func (*CompactDiffFormatter) Format ¶
func (f *CompactDiffFormatter) Format(diffs []diffmatchpatch.Diff, options DiffOptions) string
Format implements the DiffFormatter interface for CompactDiffFormatter.
type CompositionDiff ¶ added in v0.7.0
type CompositionDiff struct {
Name string
// Error is the per-composition processing error (nil if successful). Its ResourceID is
// "Composition/<name>".
Error *dt.OutputError
CompositionDiff *dt.ResourceDiff // the actual composition diff (nil if unchanged)
AffectedResources AffectedResourcesSummary
ImpactAnalysis []XRImpact
// ImpactAnalysisSkipped records that the affected XRs were deliberately not evaluated, because
// the composition changed by less than --analyze-on asked to analyse. Distinguishes "we did not
// look" from "we looked and found no affected XRs", which would otherwise be indistinguishable.
//
// It does not mean ImpactAnalysis is empty. Composites excluded by update policy, revision
// selector or deletion are identified locally, with no render, so they are reported whether or not
// the analysis ran — in --resource mode as XRStatusFiltered entries here, and always via the
// AffectedResources filter counters (issue #478). What a skip suppresses is the renders, and
// therefore any changed/unchanged/errored verdict about the composites that were kept.
//
// Why the composites went unevaluated is not recoverable from this field alone — read
// RevisionImpact.ChangeScope alongside it. A "none" scope means no CompositionRevision is created
// and so nothing could have changed; anything else means a revision is created and simply was not
// evaluated.
ImpactAnalysisSkipped bool
// MaskedChangesOnly records that the composition differs from the cluster's only in fields
// excluded from the rendered diff — the user's --ignore-paths, or the renderer's display-only
// suppressions. CompositionDiff is nil in that case, but the composition did change, so the
// renderer must not report it as unchanged.
MaskedChangesOnly bool
// RevisionImpact is what applying this composition does to CompositionRevisions, independent of
// whether anything renders differently. Populated whenever the comparison completed, including
// when the composites were not evaluated; left zero for a composition that failed to process,
// where nothing about it was established (see RevisionImpact.determined).
RevisionImpact RevisionImpact
}
CompositionDiff represents the diff result for a single composition (internal). This stores rich ResourceDiff data. Conversion to JSON happens in the renderer.
func (*CompositionDiff) HasChanges ¶ added in v0.7.0
func (c *CompositionDiff) HasChanges() bool
HasChanges returns true if this composition diff has any changes, which is what drives ExitCodeDiffDetected.
Deliberately excluded: RevisionImpact. A composition whose only difference is in masked fields creates a CompositionRevision but has nothing to show and nothing rendering differently, and a GitOps loop re-applying the same manifests would otherwise fail its diff gate on every run. A consumer that does want to gate on revision churn reads revisionImpact.createsRevision from the structured output.
type DefaultCompDiffRenderer ¶ added in v0.7.0
type DefaultCompDiffRenderer struct {
// contains filtered or unexported fields
}
DefaultCompDiffRenderer renders composition diffs in human-readable format.
func (*DefaultCompDiffRenderer) RenderCompDiff ¶ added in v0.7.0
func (r *DefaultCompDiffRenderer) RenderCompDiff(output *CompDiffOutput) error
RenderCompDiff renders the composition diff in human-readable format. Top-level errors go to r.opts.Stderr. Per-composition output (diffs, status messages, per-composition errors) goes to r.opts.Stdout.
type DefaultDiffRenderer ¶
type DefaultDiffRenderer struct {
// contains filtered or unexported fields
}
DefaultDiffRenderer implements the DiffRenderer interface.
func (*DefaultDiffRenderer) RenderDiffs ¶
func (r *DefaultDiffRenderer) RenderDiffs(groups []dt.XRDiffGroup, errs []dt.OutputError, _ []dt.OutputWarning) error
RenderDiffs formats and prints the diffs. Diff output goes to r.diffOpts.Stdout, errors go to r.diffOpts.Stderr.
Identity-bearing groups (the xr command) render as per-input-XR sections, each with a header and per-section summary, followed by an aggregate footer when there is more than one such group. Identity-less groups (the composition renderer's reuse) render as a single flat block, preserving the pre-grouping behavior. The warnings parameter is intentionally unused: warnings reach humans via stderr when they are raised, not at render time. See the DiffRenderer interface comment.
The summary of unverified additions is derived from identity-bearing groups only. An identity-less group is the composition renderer's internal reuse of this one (see dt.XRDiffGroup), which happens once per composition; that renderer writes one run-wide summary itself, so deriving one here as well would repeat it.
func (*DefaultDiffRenderer) SetDiffOptions ¶
func (r *DefaultDiffRenderer) SetDiffOptions(options DiffOptions)
SetDiffOptions updates the diff options used by the renderer.
type DiffFormatter ¶
type DiffFormatter interface {
Format(diffs []diffmatchpatch.Diff, options DiffOptions) string
}
DiffFormatter is the interface that defines the contract for diff formatters.
func NewFormatter ¶
func NewFormatter(compact bool) DiffFormatter
NewFormatter returns a DiffFormatter based on whether compact mode is desired.
type DiffOptions ¶
type DiffOptions struct {
// Stdout is the writer for diff output (defaults to os.Stdout)
Stdout io.Writer
// Stderr is the writer for error output (defaults to os.Stderr)
// Errors are written here following Unix conventions (errors to stderr, output to stdout)
Stderr io.Writer
// Format specifies the output format (diff, json, yaml)
Format OutputFormat
// UseColors determines whether to colorize the output
UseColors bool
// AddPrefix is the prefix for added lines (default "+")
AddPrefix string
// DeletePrefix is the prefix for deleted lines (default "-")
DeletePrefix string
// ContextPrefix is the prefix for unchanged lines (default " ")
ContextPrefix string
// ContextLines is the number of unchanged lines to show before/after changes in compact mode
ContextLines int
// ChunkSeparator is the string used to separate chunks in compact mode
ChunkSeparator string
// Compact determines whether to show a compact diff
Compact bool
// IgnorePaths is a list of paths to ignore when calculating diffs
// Supports both simple paths (e.g., "metadata.annotations") and
// map key paths (e.g., "metadata.annotations[key.name/value]")
IgnorePaths []string
// ForVerdict marks a comparison whose result answers "did this object change?" rather than
// producing output a human reads. Such a comparison keeps the display-only fields *in* the
// objects being compared (see displayOnlyIgnoredPaths in cleanupForDiff), so a difference in one
// of them registers: a field hidden purely to keep the rendered diff readable must never decide
// whether a change exists.
//
// Callers should also clear IgnorePaths for such a comparison, for the same reason — the user's
// masks are a display preference too.
ForVerdict bool
// MinimizeComposition collapses composition changes to a single marker line
// per composition, omitting the full YAML diff body. Only consumed by the
// human-readable composition diff renderer; structured output is unaffected.
MinimizeComposition bool
// OutputVersion selects the schema of structured (JSON/YAML) output. Empty means
// OutputVersionV1. The human-readable diff format ignores it.
OutputVersion OutputVersion
}
DiffOptions holds configuration options for the diff output.
func DefaultDiffOptions ¶
func DefaultDiffOptions() DiffOptions
DefaultDiffOptions returns the default options with colors enabled.
type DiffRenderer ¶
type DiffRenderer interface {
// RenderDiffs formats and outputs diffs, grouped by input XR.
// Diff output goes to DiffOptions.Stdout, errors go to DiffOptions.Stderr.
// The errs parameter contains the union of resource processing errors to
// include in output (the top-level/global error list).
//
// The warnings parameter carries non-fatal advisories for structured output only. Unlike errors,
// warnings have ALREADY been written to stderr, at the moment they were raised (see
// diffprocessor.WarningLogger) — emitting them at render time instead would lose any warning
// raised during a run that fails before rendering, and would report them out of chronological
// order with the work that produced them. The human renderer therefore ignores this parameter.
//
// One kind of warning is instead derived here, from the groups: the summary of added resources
// that could not be verified against the apiserver (see dryRunWarnings). Deciding what to summarise
// is a presentation decision, and the DryRunInfo it is built from only exists once the diffs do.
// Every renderer writes that summary to stderr; a structured one also appends it to warnings[],
// after the warnings passed in.
RenderDiffs(groups []dt.XRDiffGroup, errs []dt.OutputError, warnings []dt.OutputWarning) error
}
DiffRenderer handles rendering diffs to output.
func NewDiffRenderer ¶
func NewDiffRenderer(logger logging.Logger, diffOpts DiffOptions) DiffRenderer
NewDiffRenderer creates a new DefaultDiffRenderer with the given options.
func NewStructuredDiffRenderer ¶ added in v0.6.0
func NewStructuredDiffRenderer(logger logging.Logger, opts DiffOptions) DiffRenderer
NewStructuredDiffRenderer creates a new structured renderer with the specified format.
type DownstreamChanges ¶ added in v0.7.0
type DownstreamChanges struct {
Summary Summary `json:"summary"`
Changes []ChangeDetail `json:"changes"`
}
DownstreamChanges contains the downstream resource changes for an XR. It is part of the v1 (OutputVersionV1) impactAnalysis[] entry only; v2's xrEntryWire carries summary and changes directly.
type FilterReason ¶ added in v0.9.0
type FilterReason string
FilterReason explains why an XRImpact has XRStatusFiltered. It is only meaningful when XRImpact.Status == XRStatusFiltered.
const ( // FilterReasonManualPolicy indicates the XR was excluded because it has a Manual // compositionUpdatePolicy and --include-manual was not set. Such XRs are pinned to a specific // revision and would not adopt the composition change automatically. FilterReasonManualPolicy FilterReason = "manual_policy" // FilterReasonRevisionSelectorMismatch indicates the XR was excluded because it has an Automatic // compositionUpdatePolicy with a compositionRevisionSelector that does not match the labels of // the composition change being diffed. Such XRs would not select the resulting revision. FilterReasonRevisionSelectorMismatch FilterReason = "revision_selector_mismatch" // FilterReasonDeleting indicates the XR was excluded because it has a metadata.deletionTimestamp. // Crossplane's composite reconciler takes its deletion path for such an XR — it tears down // composed resources rather than composing them — so the XR will never adopt the resulting // revision, and rendering it produces no composed resources to diff against. FilterReasonDeleting FilterReason = "deleting" )
type FullDiffFormatter ¶
type FullDiffFormatter struct{}
FullDiffFormatter formats diffs with all context lines.
func (*FullDiffFormatter) Format ¶
func (f *FullDiffFormatter) Format(diffs []diffmatchpatch.Diff, options DiffOptions) string
Format implements the DiffFormatter interface for FullDiffFormatter.
type OutputError ¶ added in v0.7.0
type OutputError = dt.OutputError
OutputError is an alias for dt.OutputError for convenience. Use this type for error handling in structured output.
type OutputFormat ¶ added in v0.6.0
type OutputFormat string
OutputFormat represents the desired output format for diffs.
const ( // OutputFormatDiff is the default human-readable diff format. OutputFormatDiff OutputFormat = "diff" // OutputFormatJSON outputs structured JSON. OutputFormatJSON OutputFormat = "json" // OutputFormatYAML outputs structured YAML. OutputFormatYAML OutputFormat = "yaml" )
type OutputVersion ¶ added in v0.11.0
type OutputVersion string
OutputVersion selects the schema of structured (JSON/YAML) output. Every structured document names its version in its top-level outputVersion field, so a consumer can detect the shape.
const ( // OutputVersionV1 is the original schema: xr emits the deprecated flat changes[] beside xrs[], and // comp's impactAnalysis[] entries inline the XR's identity, wrap changes in downstreamChanges and // carry a per-XR (and per-composition) error string. OutputVersionV1 OutputVersion = "v1" // OutputVersionV2 is the converged schema: xrs[] and impactAnalysis[] hold the same entry type // (xrEntryWire), xr drops the flat changes[], and comp carries structured errors[] per XR and per // composition, with failed compositions also reported in the top-level errors[]. OutputVersionV2 OutputVersion = "v2" )
type RevisionImpact ¶ added in v0.11.0
type RevisionImpact struct {
// ChangeScope is how much of the composition differs, in the terms Crossplane uses to decide
// whether a revision is needed: "none", "metadata" or "spec". Crossplane's Composition.Hash()
// covers labels and annotations as well as spec, so "metadata" still means a revision is created.
ChangeScope string `json:"changeScope"`
// CreatesRevision records whether applying this composition produces a new CompositionRevision.
CreatesRevision bool `json:"createsRevision"`
// RepointedComposites counts the composites that would adopt that revision and reconcile as a
// result: those with an Automatic (or defaulted) compositionUpdatePolicy whose
// compositionRevisionSelector, if any, selects the resulting revision, and which are not being
// deleted. A Manual-policy composite is never counted — it is pinned by compositionRevisionRef, so
// --include-manual keeping it for analysis does not make it re-point (issue #479).
//
// Note this counts composites that re-point, which is not the same as composites whose rendered
// output changes; re-pointing alone usually renders identically.
RepointedComposites int `json:"repointedComposites"`
// PredictedRevisionName is what that revision would be called: "<composition>-<hash[:7]>", derived
// from Crossplane's own Composition.Hash(). When CreatesRevision is false it names the existing
// revision the composites already track, which is the same name by construction — an unchanged
// composition hashes to the same value.
//
// It is what makes a downstream change interpretable: a composed resource whose template reads the
// revision name shows a diff with no other visible cause, and this is the cause. The composites are
// rendered with this value seeded onto their compositionRevisionRef, so such a change is detected
// rather than assumed away.
//
// Absent with CreatesRevision true means the name could not be predicted, which happens when the
// composition differs from the cluster's only by kubectl's last-applied-configuration annotation:
// its post-apply value is a function of how the user applies rather than of the file, so the hash —
// and therefore the name — is unknowable. A warning says so, and nothing is seeded in that case, so
// a revision-observing change would go undetected. Note also that for a composition applied
// client-side *with* other edits the suffix is predicted from the file as supplied and so may differ
// from the eventual one; the change is still detected, its predicted value is just imprecise.
PredictedRevisionName string `json:"predictedRevisionName,omitempty"`
}
RevisionImpact describes what applying a composition does to CompositionRevisions and the composites tracking them, independent of whether any composed resource renders differently.
This is deliberately a typed field rather than a warning. Revision churn is a per-composition fact a CI consumer may want to gate on, and warnings are documented as neither attributed to a composition nor intended for gating — so a flat warning could not say which of several diffed compositions creates a revision.
type StructuredCompDiffRenderer ¶ added in v0.7.0
type StructuredCompDiffRenderer struct {
// contains filtered or unexported fields
}
StructuredCompDiffRenderer renders composition diffs in JSON/YAML format.
func (*StructuredCompDiffRenderer) RenderCompDiff ¶ added in v0.7.0
func (r *StructuredCompDiffRenderer) RenderCompDiff(output *CompDiffOutput) error
RenderCompDiff renders the composition diff in structured format (JSON/YAML). Top-level errors go to both r.opts.Stderr (for human visibility) and the structured output payload. Per-composition data goes to r.opts.Stdout.
type StructuredDiffOutput ¶ added in v0.6.0
type StructuredDiffOutput struct {
// OutputVersion names the schema of this document.
OutputVersion OutputVersion `json:"outputVersion"`
// Summary counts exactly what Changes lists: each distinct change once, however many input XRs
// reach it. Per-input counts are on each Xrs entry; where inputs overlap those can sum to more.
Summary Summary `json:"summary"`
// Changes is the flat, ungrouped list of all resource changes across every
// input XR.
//
// Deprecated: use Xrs for per-input-XR grouping. This field is retained for
// backward compatibility and will be removed in a future major release.
Changes []ChangeDetail `json:"changes"`
// Errors is the union of resource-processing errors across all input XRs
// (the top-level/global error list). Each errored XR also surfaces its
// error inside its own Xrs entry; this list stays complete for consumers
// that read errors here.
Errors []dt.OutputError `json:"errors,omitempty"`
// Xrs groups changes by the input XR/claim that produced them, one entry
// per input in input order. This is the recommended view; the flat Changes
// field above is deprecated.
Xrs []xrEntryWire `json:"xrs"`
// Warnings is the list of non-fatal advisories raised during the run — things worth knowing that
// did not invalidate the diff. Unlike Errors they do NOT affect the exit code, so a consumer
// gating on failure should read Errors. Warnings are not grouped per input XR because they
// originate deep in the call stack, below the point where the owning input is known. They are in
// the order raised, followed by the renderer's summary of unverified additions (see dryRunWarnings).
Warnings []dt.OutputWarning `json:"warnings,omitempty"`
}
StructuredDiffOutput represents the structured output format for diffs. Note: Only JSON tags are used because sigs.k8s.io/yaml uses JSON tags for YAML serialization.
This is the v1 document (OutputVersionV1): the v2 document (structuredDiffOutputV2) plus the deprecated flat Changes. It is only ever derived from the v2 one, by structuredDiffOutputV2.v1.
type StructuredDiffRenderer ¶ added in v0.6.0
type StructuredDiffRenderer struct {
// contains filtered or unexported fields
}
StructuredDiffRenderer renders diffs in structured formats (JSON/YAML).
func (*StructuredDiffRenderer) RenderDiffs ¶ added in v0.6.0
func (r *StructuredDiffRenderer) RenderDiffs(groups []dt.XRDiffGroup, errs []dt.OutputError, warnings []dt.OutputWarning) error
RenderDiffs renders the diffs in the configured structured format.
It emits two views built from the same groups: the deprecated flat changes[]/summary (merged across all groups) for backward compatibility, and the per-input-XR xrs[] grouping. The top-level errors[] is the union passed by the caller.
type Summary ¶ added in v0.6.0
type Summary struct {
Added int `json:"added"`
Modified int `json:"modified"`
Removed int `json:"removed"`
}
Summary contains aggregated counts of changes.
type XRImpact ¶ added in v0.7.0
type XRImpact struct {
corev1.ObjectReference
Status XRStatus
// FilterReason explains a Status == XRStatusFiltered outcome; empty otherwise.
FilterReason FilterReason
// FilterDetail is an optional human-readable explanation for a filtered outcome (e.g. which
// selector failed to match which labels), surfaced to help users self-diagnose the exclusion.
FilterDetail string
// Error is the structured processing error for an XRStatusError impact (nil otherwise), the same
// OutputError the command lists in its top-level errors.
Error *dt.OutputError
Diffs map[string]*dt.ResourceDiff // downstream diffs (nil if unchanged/error)
}
XRImpact represents the impact analysis for a single XR (internal). This stores rich ResourceDiff data. Conversion to JSON happens in the renderer. Embeds corev1.ObjectReference for the common resource identity fields.
type XRStatus ¶ added in v0.7.0
type XRStatus string
XRStatus represents the processing status of an XR in composition diffs.
const ( // XRStatusChanged indicates the XR has downstream resource changes. XRStatusChanged XRStatus = "changed" // XRStatusUnchanged indicates the XR has no downstream resource changes. XRStatusUnchanged XRStatus = "unchanged" // XRStatusError indicates an error occurred while processing the XR. XRStatusError XRStatus = "error" // XRStatusFiltered indicates the XR matched the composition by name but was excluded from // evaluation because it would not adopt the composition change being diffed. The specific cause // is carried separately in XRImpact.FilterReason (outcome and reason are intentionally divorced // so the reason set can grow without expanding the status enum). The XR is surfaced in impact // analysis with no downstream changes so users see the skip explicitly. XRStatusFiltered XRStatus = "filtered" )