Skip to content

Keep normal deletion quiet without hiding real errors - #2307

Merged
nadaverell merged 4 commits into
mainfrom
fix/expected-deleting-condition
Oct 26, 2026
Merged

nadaverell merged 4 commits into
mainfrom
fix/expected-deleting-condition

Conversation

@nadaverell

@nadaverell nadaverell commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Normal Crossplane-style deletion reports Ready=False/Deleting while external cleanup proceeds. Radar currently raises a warning immediately and can choose that summary instead of a specific reconciliation error later in the conditions.

Treat only this condition as expected during Radar’s existing ten-minute termination window, including bounded API-server clock skew. Continue selecting independent errors: current or undated evidence first, qualified older-generation evidence next, and overdue or uncertain Deleting only as a fallback. Existing stuck-deletion folding keeps one canonical termination finding while preserving a separate reconciliation error. Failure onset remains the selected condition’s timestamp.

This adds only deletion interpretation, tests and contract documentation. It changes no endpoint, wire shape, informer routing or authorization.

Validation:

  • Complete internal/issues suite and full frontend/embed/Go make build passed on d5af3a670d27b940c53881862e3bf766fd2bfaaa.
  • Actual EKS API requests on 18 owned synthetic CRD fixtures: reviewed parent and feature build with identical detector source, flat/grouped views, three repeated reads. Five finalizer-held deletions aged naturally past ten minutes; fresh normal deletion became quiet, explicit errors remained visible, and overdue deletion handed off to one canonical termination finding.
  • Actual condition recovery and reblock preserved fault identity with the new condition onset. Core HTTP and frontend-load smoke passed.
  • Controls cover missing/far-future deletion evidence, bounded clock skew, unknown condition onset, representation authority, stale evidence, and the richer termination checker being unavailable.

The ten-minute window is an existing Radar heuristic, not a provider deadline. Legitimate long cleanup may still warn. The pre-existing whole-object observed-generation and suspension gates remain: a real delete increments generation and can leave a pre-deletion error withheld until the controller catches up or a readable prolonged-deletion finding appears. This limit is documented and tested. The EKS status fixtures prove Radar’s path; they do not claim real cloud cleanup or Crossplane-controller timing.

@nadaverell
nadaverell requested a review from hisco as a code owner October 25, 2026 17:40
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

PR Summary by Qodo

Keep expected pause and deletion conditions quiet without hiding errors

🐞 Bug fix 🧊 Tests 📝 Documentation 🕐 20-40 Minutes

Grey Divider

AI Description

â€Ē Suppress explicitly annotated Crossplane pauses and normal early deletion in generic condition
 issues.
â€Ē Prefer independent failures over deletion summaries while preserving generation filters and
 condition onset.
â€Ē Test selection and termination folding; document the pause and deletion boundaries.
Diagram

graph TD
  A["CRD conditions"] --> B["Existing gates"] --> C{"Expected state?"}
  C -->|yes| D["Continue scan"] --> E{"Selected evidence?"}
  C -->|no| E
  E -->|specific| F["Failure issue"] --> H["Termination folding"]
  E -->|deleting| G["Deletion fallback"] --> H
Loading
High-Level Assessment

Keep the condition-level selection approach. Suppressing an entire paused or deleting resource would hide independent errors; changing termination folding or the existing generation gate would broaden the behavior change. The selector also reuses the termination warning threshold already shared with the termination detector.

Files changed (4) +376 / -9

Bug fix (1) +30 / -9
source_conditions.goDeprioritize expected pause and deletion conditions +30/-9

Deprioritize expected pause and deletion conditions

â€Ē Skips explicitly annotated Crossplane pause conditions and Ready=False/Deleting during the existing ten-minute termination window. Retains overdue or uncertain Deleting as a last fallback behind current and qualified older-generation failures, without changing the selected condition's timestamp.

internal/issues/source_conditions.go

Tests (1) +330 / -0
source_conditions_test.goExercise pause, deletion, and failure precedence +330/-0

Exercise pause, deletion, and failure precedence

â€Ē Adds flat and grouped issue tests for annotation authority, condition representations, clock skew, missing timestamps, stale evidence, and onset identity. Verifies that termination folding avoids duplicate deletion findings without hiding independent errors, while the existing whole-object generation gate remains in effect.

internal/issues/source_conditions_test.go

Documentation (2) +16 / -0
integrations.mdDocument the explicit Crossplane pause rule +2/-0

Document the explicit Crossplane pause rule

â€Ē Clarifies that only Synced=False/ReconcilePaused with crossplane.io/paused exactly "true" is quiet in Issues. Other failures remain eligible, and empty managementPolicies are outside this rule.

docs/integrations.md

mcp.mdDocument deletion-condition timing and coverage limits +14/-0

Document deletion-condition timing and coverage limits

â€Ē Explains the ten-minute expected-deletion window, bounded clock skew, and the priority of independent failures. Documents the existing generation gate that can withhold pre-deletion errors until observation catches up.

docs/mcp.md

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) ðŸŽĻ UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Remediation recommended

1. Missing deletion time hides real errors ✓ Resolved
Description
findActionableCondition returns Ready: Deleting immediately when the deletion timestamp is
absent, zero, or in the future, rather than keeping it as a fallback. If that condition precedes an
independent Synced: ReconcileError, the loop never examines the error and the issue reports
deletion instead.
Code

internal/issues/source_conditions.go[R287-288]

+			if condition.Type != "Ready" || condition.Reason != "Deleting" || deletion == nil || deletion.IsZero() || deletion.After(now) {
+				return condition, true
Evidence
The generic detector uses the helper's single returned condition to construct its issue. The
condition reader takes the first matching false entry, so a leading Ready/Deleting entry reaches the
new early return before a later Synced failure can be selected; the added tests exercise uncertain
timestamps and independent failures separately, but not together.

internal/issues/source_conditions.go[159-170]
internal/issues/source_conditions.go[279-297]
pkg/conditions/conditions.go[94-133]
internal/issues/source_conditions_test.go[97-105]
internal/issues/source_conditions_test.go[116-133]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
An absent, zero, or future deletion timestamp causes `findActionableCondition` to return `Ready: Deleting` before examining later independent errors.
## Fix Focus Areas
- internal/issues/source_conditions.go[276-297]
- internal/issues/source_conditions_test.go[88-175]
## Recommended Fix
Keep `Ready: Deleting` as a fallback for uncertain timestamps, just as for overdue deletion. Continue searching other condition types and return the fallback only if no actionable condition is found. Add cases combining each uncertain timestamp with a later independent failure.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
ðŸ’Ą Did you know, you can type 'qodo, fix this' on a finding and the fix lands right on your PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@nadaverell
nadaverell changed the base branch from fix/actionable-condition-selection to main October 25, 2026 18:01
@nadaverell nadaverell closed this Oct 25, 2026
@nadaverell nadaverell reopened this Oct 25, 2026
Comment thread internal/issues/source_conditions.go Outdated
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit 1ee72ad

@nadaverell
nadaverell changed the base branch from main to fix/actionable-condition-selection October 25, 2026 19:33
@nadaverell
nadaverell changed the base branch from fix/actionable-condition-selection to main October 25, 2026 19:35
@nadaverell
nadaverell force-pushed the fix/expected-deleting-condition branch from 7ae3f12 to 1d7261f Compare October 25, 2026 19:35
@nadaverell
nadaverell changed the base branch from main to fix/paused-reconcile-condition October 25, 2026 19:46
@nadaverell
nadaverell force-pushed the fix/paused-reconcile-condition branch from 7dce015 to 6ed9b98 Compare October 26, 2026 00:52
@nadaverell
nadaverell changed the base branch from fix/paused-reconcile-condition to main October 26, 2026 01:00
@nadaverell
nadaverell force-pushed the fix/expected-deleting-condition branch from 1d7261f to 2760862 Compare October 26, 2026 01:10
@nadaverell
nadaverell changed the base branch from main to fix/paused-reconcile-condition October 26, 2026 01:27
@nadaverell
nadaverell changed the base branch from fix/paused-reconcile-condition to main October 26, 2026 08:34
@nadaverell
nadaverell force-pushed the fix/expected-deleting-condition branch from 9971a9e to d5af3a6 Compare October 26, 2026 08:35
@nadaverell
nadaverell changed the base branch from main to fix/paused-reconcile-condition October 26, 2026 08:47
@nadaverell
nadaverell force-pushed the fix/paused-reconcile-condition branch from 87197c4 to 749b2e9 Compare October 26, 2026 11:50
@nadaverell
nadaverell force-pushed the fix/expected-deleting-condition branch from d5af3a6 to cd5e0c5 Compare October 26, 2026 11:57
@nadaverell
nadaverell changed the base branch from fix/paused-reconcile-condition to main October 26, 2026 13:48
@nadaverell nadaverell closed this Oct 26, 2026
@nadaverell nadaverell reopened this Oct 26, 2026
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

Code review by qodo was updated up to the latest commit cd5e0c5

@nadaverell
nadaverell changed the base branch from main to fix/paused-reconcile-condition October 26, 2026 14:04
Base automatically changed from fix/paused-reconcile-condition to main October 26, 2026 15:43
@nadaverell
nadaverell force-pushed the fix/expected-deleting-condition branch from cd5e0c5 to 4303f3f Compare October 26, 2026 15:49
@nadaverell
nadaverell merged commit 39f7ed4 into main Oct 26, 2026
19 of 20 checks passed
@nadaverell
nadaverell deleted the fix/expected-deleting-condition branch October 26, 2026 16:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant