Skip to content

render: Replace condition timestamps and sort resources to stabilize output#82

Open
adamwg wants to merge 2 commits into
crossplane:mainfrom
adamwg:awg/stabilize-render
Open

render: Replace condition timestamps and sort resources to stabilize output#82
adamwg wants to merge 2 commits into
crossplane:mainfrom
adamwg:awg/stabilize-render

Conversation

@adamwg
Copy link
Copy Markdown
Member

@adamwg adamwg commented Jun 5, 2026

Description of your changes

The old render command used a static timestamp for status condition lastTransitionTimes so that output was stable across runs with the same inputs. The new render engine calls the real reconciler, and therefore produces real timestamps.

Restore stability by replacing the timestamps in any status conditions returned by the render engine before outputting them. We use the same static timestamp that was present in the old CLI for consistency with its output.

Fixes #50

The old CLI's render command sorted composed resources by the composition-resource-name annotation to ensure output consistency across runs with the same inputs. The real reconciler code used by the new render engine does not sort the results, so we need to sort them client-side to ensure stability.

Fixes #53

I have:

adamwg added 2 commits June 5, 2026 15:02
The old render command used a static timestamp for status condition
`lastTransitionTime`s so that output was stable across runs with the same
inputs. The new render engine calls the real reconciler, and therefore produces
real timestamps.

Restore stability by replacing the timestamps in any status conditions returned
by the render engine before outputting them. We use the same static timestamp
that was present in the old CLI for consistency with its output.

Fixes crossplane#50

Signed-off-by: Adam Wolfe Gordon <[email protected]>
…tion

The old CLI's `render` command sorted composed resources by the
`composition-resource-name` annotation to ensure output consistency across runs
with the same inputs. The real reconciler code used by the new render engine
does not sort the results, so we need to sort them client-side to ensure
stability.

Fixes crossplane#53

Signed-off-by: Adam Wolfe Gordon <[email protected]>
@adamwg adamwg requested review from a team, jcogilvie and tampakrap as code owners June 5, 2026 21:06
@adamwg adamwg requested review from haarchri and removed request for a team June 5, 2026 21:06
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jun 5, 2026

PR changed again? Review this PR in Change Stack to compare snapshots and stay oriented.

Review Change Stack

📝 Walkthrough

Walkthrough

This PR resolves non-determinism in crossplane render output by standardizing condition timestamps to a fixed value and sorting composed resources by annotation. A core helper function replaces LastTransitionTime across runtime objects, integrated into both render op and render xr commands with per-command error handling and resource ordering.

Changes

Render Output Determinism

Layer / File(s) Summary
Core condition timestamp stabilization and tests
cmd/crossplane/render/output.go, cmd/crossplane/render/output_test.go
Introduces ReplaceConditionTimestamps(o runtime.Object) that normalizes all condition LastTransitionTime values to Jan 1, 2024 UTC via conditionTime() helper, with conversion to unstructured representation, status field access, and comprehensive table-driven test coverage for absent/present conditions, idempotency, and typed-object conversion paths.
Render operation command timestamp stabilization
cmd/crossplane/render/op/cmd.go
Post-processes render output by applying ReplaceConditionTimestamps() to the operation and each applied resource, with wrapped error context for operation-level and per-resource diagnostics.
Render composite resource command with timestamp stabilization and deterministic sorting
cmd/crossplane/render/xr/cmd.go
Post-processes render output by applying ReplaceConditionTimestamps() to the composite and composed resources, then stably sorts composed resources by composition-resource-name annotation to ensure consistent ordering; adds slices and strings imports for stable sorting via slices.SortStableFunc() and strings.Compare().

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning Title exceeds 72-character limit at 75 characters but clearly describes the two main changes: replacing condition timestamps and sorting resources to stabilize render output. Shorten title to 72 characters or fewer while preserving the key information about timestamp replacement and resource sorting.
✅ Passed checks (5 passed)
Check name Status Explanation
Description check ✅ Passed Description clearly explains both changes (timestamp stabilization and resource sorting), references the linked issues (#50 and #53), and demonstrates adherence to contribution guidelines.
Linked Issues check ✅ Passed Code changes fully address both linked issues: ReplaceConditionTimestamps() fixes #50 by replacing timestamps with stable values, and sorting composed resources by annotation fixes #53.
Out of Scope Changes check ✅ Passed All changes are directly scoped to addressing the linked issues: timestamp normalization for #50 and resource sorting for #53, with supporting test coverage.
Breaking Changes ✅ Passed PR makes only additive changes: new ReplaceConditionTimestamps() function and post-processing calls. No fields/flags removed, renamed, or required fields added in cmd/** or apis/**.
Feature Gate Requirement ✅ Passed PR does not add experimental features requiring feature gates. Changes are bug fixes (timestamps, resource sorting) in cmd/crossplane/render/, with no modifications to apis/** directory.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
cmd/crossplane/render/xr/cmd.go (1)

345-357: ⚡ Quick win

The sorting logic looks great! The use of slices.SortStableFunc ensures deterministic ordering across runs, and the nil-checks with empty-string defaults are robust.

One small consistency observation: the sorting logic (lines 350, 353) uses xcrd.AnnotationKeyCompositionResourceName, but line 367 below uses render.AnnotationKeyCompositionResourceName in the error message. While both likely refer to the same annotation key string, it would be more maintainable to use the same constant reference throughout this file. Which constant do you prefer to standardize on?

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/crossplane/render/xr/cmd.go` around lines 345 - 357, The file mixes two
constants for the same annotation key—xcrd.AnnotationKeyCompositionResourceName
and render.AnnotationKeyCompositionResourceName—causing inconsistency; pick one
constant and replace the other so the code uses a single canonical symbol
throughout (e.g., update the sorting block or the error message to consistently
reference either xcrd.AnnotationKeyCompositionResourceName or
render.AnnotationKeyCompositionResourceName), ensuring all uses (including in
slices.SortStableFunc over out.ComposedResources and any error messages) refer
to the chosen constant.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@cmd/crossplane/render/xr/cmd.go`:
- Around line 345-357: The file mixes two constants for the same annotation
key—xcrd.AnnotationKeyCompositionResourceName and
render.AnnotationKeyCompositionResourceName—causing inconsistency; pick one
constant and replace the other so the code uses a single canonical symbol
throughout (e.g., update the sorting block or the error message to consistently
reference either xcrd.AnnotationKeyCompositionResourceName or
render.AnnotationKeyCompositionResourceName), ensuring all uses (including in
slices.SortStableFunc over out.ComposedResources and any error messages) refer
to the chosen constant.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 19b56d26-f8b8-4e7e-aa9e-c894ec852794

📥 Commits

Reviewing files that changed from the base of the PR and between 5ed17c9 and ddc2f67.

📒 Files selected for processing (4)
  • cmd/crossplane/render/op/cmd.go
  • cmd/crossplane/render/output.go
  • cmd/crossplane/render/output_test.go
  • cmd/crossplane/render/xr/cmd.go

@haarchri
Copy link
Copy Markdown
Member

haarchri commented Jun 6, 2026

@adamwg for sorting this is related to: crossplane/crossplane#7341

@LorenzBischof
Copy link
Copy Markdown

LorenzBischof commented Jun 6, 2026

Thank you @adamwg for these fixes!

@adamwg for sorting this is related to: crossplane/crossplane#7341

Yes, it is and the behaviour appears when using the CLI, but compared to the changes in this PR, it should not be fixed client side in the CLI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

crossplane render output not sorted crossplane render generates current lastTransitionTime timestamps that are non-deterministic

3 participants