crossplane-contrib / crossplane-contrib/crossplane-diff

Converge comp and xr per-XR structured output onto a single shape

Open
#410 0 comments 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Go
Stars
42
Forks
15
Avg merge
10h 26m
Merged PRs (30d)
33

Description

### What problem are you facing?

The `comp` and `xr` commands both emit a per-XR entry in their structured (`-o json`/`-o yaml`) output, but the two shapes diverge, so a CI wrapper that consumes both commands cannot parse them with one code path:

- **`comp`** — `impactAnalysis[]`, each entry **inlines** a `corev1.ObjectReference` (apiVersion/kind/name/namespace as top-level fields of the entry), carries a single `error` **string**, and wraps changes in a `downstreamChanges: { summary, changes }` object.
- **`xr`** — `xrs[]` (added in #405), each entry **nests** identity under an `xr:` object, carries a richer `errors[]` (`[]OutputError`, with `validationFailures[]`), and exposes `summary` + `changes[]` as sibling fields.

The `xrs[]` shape was designed deliberately, when it was added, to be the *converged target*: it was additive/greenfield (no existing consumers), so it could be shaped as the eventual standard rather than to match `comp`'s legacy shape. On every axis where they differ, `xr`'s shape is the intended one and `comp`'s is the legacy. So this is a "migrate `comp` onto `xr`'s shape", not a mutual reconciliation.

This is intentionally deferred until the next time we're already making a **breaking** change to `comp`'s structured output, because converging is inherently breaking for `comp` consumers and there's no reason to spend a separate breaking event on it now.

### How could Crossplane help solve your problem?

At the next breaking `comp` structured-output change, converge the two per-XR entry types (`comp`'s `xrImpactWire` and `xr`'s `xrDiffWire`) onto a single shared wire shape — `xr`'s — so wrappers parse `comp` and `xr` identically. Concretely, the `comp`-side changes required:

1. **Error model:** `comp`'s per-XR `error string` → `errors []OutputError` (the richer model, with `validationFailures[]`, that `xr` already emits).
2. **Identity representation:** `comp` inlines `corev1.ObjectReference` at the top of each entry; converge to `xr`'s nested `xr: {}` carrying only apiVersion/kind/name/namespace. Nesting separates "which XR" from "what happened to it"; the projection keeps the public schema free of `ObjectReference`'s server-side fields (uid/resourceVersion/fieldPath). Do **not** regress `xr` to `comp`'s inlined form.
3. **Changes wrapper:** reconcile `comp`'s `downstreamChanges: { summary, changes }` wrapper vs. `xr`'s flatter sibling `summary` + `changes[]`. Prefer `xr`'s flatter shape unless the nested wrapper earns its keep. (Note: the name `downstreamChanges` is wrong for `xr`, where the XR itself is a change — a converged name should be neutral, e.g. `changes`.)
4. **Filter concepts:** `comp`'s `filterReason`/`filterDetail` are `comp`-only (no analogue in `xr`); keep them as optional fields on the unified entry, populated only by `comp`.
5. **Bundle with:** removing the deprecated flat `xr` `changes[]` field (deprecated in favor of `xrs[]` in #405).

**End state:** one per-XR entry type both commands emit.

Background: the `xrs[]` grouping was added in #409 (fixes #405). The full rationale and this checklist are recorded in that PR's `.requirements/…/REQUIREMENTS.md` (Decision 5 + Future Work).

Contributor guide

Open the contributing guide

Research direction

Start with the comp and xr structured-output entry points and the xrImpactWire and xrDiffWire types. Read Decision 5 and Future Work in the .requirements/…/REQUIREMENTS.md referenced from PR #409 before confirming the intended xr shape. Done means both commands emit one per-XR shape, comp retains its optional filter fields, and the deprecated flat xr changes[] field is removed.

Written by the indexing model from the issue text.

Assessment

Tech stack
go
Domain
cli
Issue type
Refactor
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
50/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.