Skip to content

CNTRLPLANE-3691: Decouple NodePool condition handling from CAPI reconciliation#9032

Open
hypershift-jira-solve-ci[bot] wants to merge 3 commits into
openshift:mainfrom
hypershift-community:fix-CNTRLPLANE-3691
Open

CNTRLPLANE-3691: Decouple NodePool condition handling from CAPI reconciliation#9032
hypershift-jira-solve-ci[bot] wants to merge 3 commits into
openshift:mainfrom
hypershift-community:fix-CNTRLPLANE-3691

Conversation

@hypershift-jira-solve-ci

@hypershift-jira-solve-ci hypershift-jira-solve-ci Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

What this PR does / why we need it:

Decouples NodePool condition management from CAPI.Reconcile() by introducing a CAPIResult struct that carries condition information back to the caller. Previously, CAPI.Reconcile() was setting NodePool conditions inline, mixing CAPI resource reconciliation with NodePool status management. This made capi.go harder to reason about and violated separation of concerns.

The caller in nodepool_controller.go now sets conditions on the NodePool after the CAPI reconciliation completes, centralizing condition management in the controller layer.

Conditions moved:

  • NodePoolUpdatingPlatformMachineTemplateConditionType
  • NodePoolAutorepairEnabledConditionType
  • NodePoolReadyConditionType (from both MachineDeployment and MachineSet)

No behavioral change — the same conditions are set under the same circumstances.

Tests are updated to capture and validate the CAPIResult returned by capi.Reconcile(), and a pre-existing test bug is fixed where conditions accumulated on capi.conditions were not applied to the NodePool.

Which issue(s) this PR fixes:

Fixes https://redhat.atlassian.net/browse/CNTRLPLANE-3691

Special notes for your reviewer:

This is a pure refactor with no behavioral change. The diff is large because condition-setting logic moves from capi.go to nodepool_controller.go, but the conditions themselves and when they are set remain identical.

Checklist:

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

Always review AI generated responses prior to use.
Generated with Claude Code via openshift-developer plugin


Note: This PR was auto-generated by the jira-agent periodic CI job in response to CNTRLPLANE-3691. See the full report for token usage, cost breakdown, and detailed phase output.

Summary by CodeRabbit

  • Bug Fixes
    • Improved NodePool status reporting by reliably propagating readiness, platform update, and autorepair-related conditions.
    • Prevented MachineHealthChecks from being reconciled until the NodePool reaches the ignition endpoint.
    • Enhanced MachineHealthCheck error handling to produce more consistent reconciliation outcomes.
  • Tests
    • Expanded reconciliation tests to validate the produced NodePool conditions across autorepair/ignition scenarios and MachineSet readiness transitions.

OpenShift CI Bot and others added 2 commits July 16, 2026 09:16
CAPI.Reconcile() was setting NodePool conditions inline, mixing CAPI
resource reconciliation with NodePool status management. This made
capi.go harder to reason about and violated separation of concerns.

Introduce a CAPIResult struct returned by CAPI.Reconcile() that carries
condition information back to the caller. The caller in
nodepool_controller.go now sets conditions on the NodePool after
the CAPI reconciliation completes, centralizing condition management
in the controller layer.

Conditions moved:
- NodePoolUpdatingPlatformMachineTemplateConditionType
- NodePoolAutorepairEnabledConditionType
- NodePoolReadyConditionType (from both MachineDeployment and MachineSet)

No behavioral change — the same conditions are set under the same
circumstances.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Capture and validate the CAPIResult returned by capi.Reconcile() in
TestCAPIReconcile, TestCAPIReconcile_machineset, and fix a pre-existing
test bug in TestReconcileMachineDeploymentStatus where conditions
accumulated on capi.conditions were not applied to the NodePool.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jul 17, 2026
@openshift-ci-robot

openshift-ci-robot commented Jul 17, 2026

Copy link
Copy Markdown

@hypershift-jira-solve-ci[bot]: This pull request references CNTRLPLANE-3691 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set.

Details

In response to this:

What this PR does / why we need it:

Decouples NodePool condition management from CAPI.Reconcile() by introducing a CAPIResult struct that carries condition information back to the caller. Previously, CAPI.Reconcile() was setting NodePool conditions inline, mixing CAPI resource reconciliation with NodePool status management. This made capi.go harder to reason about and violated separation of concerns.

The caller in nodepool_controller.go now sets conditions on the NodePool after the CAPI reconciliation completes, centralizing condition management in the controller layer.

Conditions moved:

  • NodePoolUpdatingPlatformMachineTemplateConditionType
  • NodePoolAutorepairEnabledConditionType
  • NodePoolReadyConditionType (from both MachineDeployment and MachineSet)

No behavioral change — the same conditions are set under the same circumstances.

Tests are updated to capture and validate the CAPIResult returned by capi.Reconcile(), and a pre-existing test bug is fixed where conditions accumulated on capi.conditions were not applied to the NodePool.

Which issue(s) this PR fixes:

Fixes https://redhat.atlassian.net/browse/CNTRLPLANE-3691

Special notes for your reviewer:

This is a pure refactor with no behavioral change. The diff is large because condition-setting logic moves from capi.go to nodepool_controller.go, but the conditions themselves and when they are set remain identical.

Checklist:

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

Always review AI generated responses prior to use.
Generated with Claude Code via openshift-developer plugin

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

CAPI.Reconcile now returns a CAPIResult containing accumulated NodePool conditions. CAPI reconciliation appends conditions for MachineTemplate updates, autorepair and spot health checks, and machine readiness. The NodePool reconciler applies returned conditions to status while retaining existing requeue behavior. Tests cover returned conditions, ignition gating, readiness propagation, timeout settings, and updated callback signatures.

Sequence Diagram(s)

sequenceDiagram
  participant NodePoolReconciler
  participant CAPI
  participant MachineResources
  NodePoolReconciler->>CAPI: Reconcile(ctx)
  CAPI->>MachineResources: Reconcile machines and health checks
  MachineResources-->>CAPI: Status and errors
  CAPI-->>NodePoolReconciler: CAPIResult with conditions
  NodePoolReconciler->>NodePoolReconciler: Apply conditions to NodePool status
Loading

Possibly related PRs

Suggested reviewers: ironcladlou, csrwng

🚥 Pre-merge checks | ✅ 10 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Test Structure And Quality ⚠️ Warning TestCAPIReconcile still checks MHC deletion with hardcoded test-cp-namespace, so the assertion is vacuous and doesn't verify the real control-plane namespace. Use controlpaneNamespace in that Get so the test validates the actual MHC deletion path against the created fake object.
✅ Passed checks (10 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: moving NodePool condition handling out of CAPI reconciliation.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed The added/updated test titles are static literals; none interpolate runtime values, generated IDs, timestamps, or other dynamic data.
Topology-Aware Scheduling Compatibility ✅ Passed Touched code only moves NodePool conditions between functions; no new scheduling constraints, selectors, affinity, spread, or PDB logic were introduced.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed Only standard unit tests changed; no new Ginkgo DSL, IPv4 literals, or external network calls were found in the modified files.
No-Weak-Crypto ✅ Passed Changed files add NodePool condition refactors/tests only; no MD5/SHA1/DES/RC4/3DES/Blowfish/ECB, custom crypto, or secret-token compares found.
Container-Privileges ✅ Passed No changed manifest/pod-spec lines set privileged=true, hostPID/Network/IPC, SYS_ADMIN, or allowPrivilegeEscalation=true.
No-Sensitive-Data-In-Logs ✅ Passed PR diff adds no logs exposing secrets/tokens/PII; changed logging only uses generic condition/result/resource fields.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci openshift-ci Bot added area/hypershift-operator Indicates the PR includes changes for the hypershift operator and API - outside an OCP release and removed do-not-merge/needs-area labels Jul 17, 2026
@openshift-ci

openshift-ci Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: hypershift-jira-solve-ci[bot]
Once this PR has been reviewed and has the lgtm label, please assign csrwng for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci
openshift-ci Bot requested review from csrwng and ironcladlou July 17, 2026 10:11

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
hypershift-operator/controllers/nodepool/capi_test.go (1)

1884-1890: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the expected condition contract, not merely a non-empty result.

These assertions pass if only an unrelated condition is returned. Add expected condition type/status assertions per fixture, particularly for autorepair and ready-condition paths.

  • hypershift-operator/controllers/nodepool/capi_test.go#L1884-L1890: assert the conditions expected from the initial reconciliation.
  • hypershift-operator/controllers/nodepool/capi_test.go#L2000-L2003: assert the expected condition after rollout completion.
  • hypershift-operator/controllers/nodepool/capi_test.go#L2172-L2182: assert the in-place reconciliation condition set.

As per coding guidelines, “Unit test any code changes and additions.”

🤖 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 `@hypershift-operator/controllers/nodepool/capi_test.go` around lines 1884 -
1890, Strengthen the condition assertions in
hypershift-operator/controllers/nodepool/capi_test.go at lines 1884-1890,
2000-2003, and 2172-2182: use each fixture’s expected condition type and status,
including autorepair, ready-condition, rollout-completion, and in-place
reconciliation paths, rather than only checking that conditions are non-empty.
Update the tests around the capi.Reconcile calls and add or adjust unit-test
expectations for every affected scenario.

Source: Coding guidelines

🤖 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.

Inline comments:
In `@hypershift-operator/controllers/nodepool/capi.go`:
- Around line 150-151: Preserve accumulated conditions after CAPI reconciliation
begins: in CAPI.Reconcile, return the accumulated CAPIResult alongside errors on
every subsequent error path, including the MachineSet failure near
hypershift-operator/controllers/nodepool/capi.go:150-151. In
hypershift-operator/controllers/nodepool/nodepool_controller.go:429-440, apply
any non-nil CAPIResult before handling and returning the reconciliation error.

---

Nitpick comments:
In `@hypershift-operator/controllers/nodepool/capi_test.go`:
- Around line 1884-1890: Strengthen the condition assertions in
hypershift-operator/controllers/nodepool/capi_test.go at lines 1884-1890,
2000-2003, and 2172-2182: use each fixture’s expected condition type and status,
including autorepair, ready-condition, rollout-completion, and in-place
reconciliation paths, rather than only checking that conditions are non-empty.
Update the tests around the capi.Reconcile calls and add or adjust unit-test
expectations for every affected scenario.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 1b60cd96-8142-43b2-8179-b7be4e59fd53

📥 Commits

Reviewing files that changed from the base of the PR and between 3b49a4a and 159b233.

📒 Files selected for processing (3)
  • hypershift-operator/controllers/nodepool/capi.go
  • hypershift-operator/controllers/nodepool/capi_test.go
  • hypershift-operator/controllers/nodepool/nodepool_controller.go

Comment on lines +150 to 151
return nil, fmt.Errorf("failed to reconcile MachineSet %q: %w",
client.ObjectKeyFromObject(ms).String(), err)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve accumulated conditions when CAPI reconciliation fails.

A condition is appended before these later failures, but CAPI.Reconcile returns nil, err; the controller therefore returns before applying it. Previously, the inline status mutation was patched even on reconcile errors, so this loses status updates such as the platform-template condition.

  • hypershift-operator/controllers/nodepool/capi.go#L150-L151: return the accumulated CAPIResult on every error path reached after condition collection begins.
  • hypershift-operator/controllers/nodepool/nodepool_controller.go#L429-L440: apply a non-nil result before handling and returning the error.
📍 Affects 2 files
  • hypershift-operator/controllers/nodepool/capi.go#L150-L151 (this comment)
  • hypershift-operator/controllers/nodepool/nodepool_controller.go#L429-L440
🤖 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 `@hypershift-operator/controllers/nodepool/capi.go` around lines 150 - 151,
Preserve accumulated conditions after CAPI reconciliation begins: in
CAPI.Reconcile, return the accumulated CAPIResult alongside errors on every
subsequent error path, including the MachineSet failure near
hypershift-operator/controllers/nodepool/capi.go:150-151. In
hypershift-operator/controllers/nodepool/nodepool_controller.go:429-440, apply
any non-nil CAPIResult before handling and returning the reconciliation error.

@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 45.45455% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 44.27%. Comparing base (4fa09b1) to head (9e1ffa7).
⚠️ Report is 57 commits behind head on main.

Files with missing lines Patch % Lines
hypershift-operator/controllers/nodepool/capi.go 53.57% 13 Missing ⚠️
...erator/controllers/nodepool/nodepool_controller.go 0.00% 5 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #9032      +/-   ##
==========================================
+ Coverage   44.11%   44.27%   +0.16%     
==========================================
  Files         772      781       +9     
  Lines       96227    98553    +2326     
==========================================
+ Hits        42449    43636    +1187     
- Misses      50832    51867    +1035     
- Partials     2946     3050     +104     
Files with missing lines Coverage Δ
...erator/controllers/nodepool/nodepool_controller.go 42.96% <0.00%> (-0.39%) ⬇️
hypershift-operator/controllers/nodepool/capi.go 76.39% <53.57%> (+4.43%) ⬆️

... and 44 files with indirect coverage changes

Flag Coverage Δ
cmd-support 38.32% <ø> (+0.08%) ⬆️
cpo-hostedcontrolplane 46.78% <ø> (+0.61%) ⬆️
cpo-other 45.22% <ø> (+0.08%) ⬆️
hypershift-operator 54.30% <45.45%> (+0.20%) ⬆️
other 33.59% <ø> (+1.47%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bryan-cox bryan-cox left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Overall this is a clean, well-scoped refactor. The CAPIResult struct approach is solid and the test bug fix in TestReconcileMachineDeploymentStatus is a genuine improvement. A few observations inline.

capiClusterName string
scaleFromZeroPlatform hyperv1.PlatformType
upsert.ApplyProvider
conditions []hyperv1.NodePoolCondition

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit (judgement call): The conditions field on CAPI acts as a builder for CAPIResult.ConditionsReconcile() could build the slice locally and return it directly, avoiding the mutable struct field. Not blocking, but something to consider if this area gets touched again.

Also worth noting for a follow-up: capi.go still directly mutates nodePool.Status.Replicas (lines 655, 1055), nodePool.Status.Version (lines 635, 1033), and nodePool.Annotations (lines 641-651). The Jira spec says "capi.go focuses purely on CAPI resource reconciliation" — conditions are now decoupled, but these other status mutations remain. A follow-up issue to decouple those would complete the separation of concerns.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed on both points. Building the slice locally in Reconcile() and returning it directly would be cleaner — noted for a future pass. And yes, the remaining Status.Replicas, Status.Version, and Annotations mutations in capi.go are the next candidates for decoupling per the Jira scope.


AI-assisted response via Claude Code

if cond := FindStatusCondition(nodePool.Status.Conditions, hyperv1.NodePoolReachedIgnitionEndpoint); cond == nil || cond.Status != corev1.ConditionTrue {
log.Info("ReachedIgnitionEndpoint is false, MachineHealthCheck won't be created until this is true")
return nil
return &CAPIResult{Conditions: c.conditions}, nil

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Good: this early return now correctly preserves conditions accumulated before this point (specifically NodePoolUpdatingPlatformMachineTemplateConditionType). In the old code, SetStatusCondition was called inline before this return so they were already applied — the new code maintains that behavior by returning c.conditions here. Verified this is behavior-preserving.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks for verifying — that was the key invariant: conditions accumulated before the early return must still be returned to the caller.


AI-assisted response via Claude Code

}
for _, condition := range capiResult.Conditions {
SetStatusCondition(&nodePool.Status.Conditions, condition)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The Jira spec suggested a "dedicated function" for condition-setting. This inline loop is simpler and arguably better for a 3-line operation. If the number of condition sources grows (e.g., decoupling Status.Replicas and Status.Version from capi.go too), this could graduate to a applyCAPIConditions(nodePool, capiResult) helper.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed — the inline loop is proportional to the current scope. If additional condition sources land (e.g., decoupled Replicas/Version), graduating to an applyCAPIConditions helper makes sense.


AI-assisted response via Claude Code


capi.reconcileMachineDeploymentStatus(logr.Discard(), tc.machineDeployment, templateCR)
for _, cond := range capi.conditions {
SetStatusCondition(&nodePool.Status.Conditions, cond)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Good catch — this fixes a pre-existing test bug. Before this change, reconcileMachineDeploymentStatus accumulated conditions on capi.conditions but nothing applied them to nodePool.Status.Conditions, so the Ready condition assertions below were passing vacuously against stale state.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks — the test was indeed asserting against stale state before this fix.


AI-assisted response via Claude Code

@@ -2344,7 +2351,7 @@ func TestGlobalPSManagedLabelOnMachines(t *testing.T) {
},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: This &CAPIResult{Conditions: capi.conditions} construction is duplicated in the KubeVirt test case below (~line 2500). Both test helpers reach into capi.conditions directly, coupling the test to the internal accumulation mechanism. Minor — this is test scaffolding and the duplication is tolerable.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Acknowledged — the duplication is intentional scaffolding for now. If this area evolves, extracting a buildCAPIResult(capi) test helper would clean it up.


AI-assisted response via Claude Code

@bryan-cox

Copy link
Copy Markdown
Member

Unit test coverage is not passing codecov/patch either.

Add test cases for previously uncovered code paths:
- ReachedIgnitionEndpoint not set with AutoRepair enabled (early return)
- MachineSet ReadyCondition propagation to CAPIResult
- Validate specific condition types (UpdatingPlatformMachineTemplate,
  AutorepairEnabled) in existing test assertions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@hypershift-jira-solve-ci

Copy link
Copy Markdown
Contributor Author

Done. Added test coverage in 9e1ffa7 for previously uncovered code paths:

  • ReachedIgnitionEndpoint early return (capi.go:177): new test case exercises AutoRepair=true with ReachedIgnitionEndpoint absent, covering the early return path that preserves accumulated conditions.
  • MachineSet ReadyCondition propagation (capi.go:1067-1074): new TestCAPIReconcile_machineset_readyCondition uses a two-pass reconciliation to reach the ReadyCondition propagation path.
  • Condition type validation: existing test assertions now validate specific condition types (UpdatingPlatformMachineTemplate, AutorepairEnabled) in CAPIResult rather than just NotBeEmpty().

Note: the nodepool_controller.go lines (435-440) are in the main reconcile() loop which lacks unit test infrastructure — those are covered by e2e tests.


AI-assisted response via Claude Code

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
hypershift-operator/controllers/nodepool/capi_test.go (1)

2038-2046: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider asserting the actual condition Status, not just presence.

This check only confirms NodePoolUpdatingPlatformMachineTemplateConditionType exists in capiResult.Conditions, unlike the sibling Autorepair checks in the same block which assert .Status explicitly. Strengthening this to also verify the expected True/False value (based on whether the template actually changed) would make the test meaningfully stronger against regressions in that branch's logic.

🤖 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 `@hypershift-operator/controllers/nodepool/capi_test.go` around lines 2038 -
2046, The CAPIResult test only checks for the UpdatingPlatformMachineTemplate
condition’s presence. In the assertion around foundUpdatingCondition, locate the
matching condition and assert its Status matches the expected True/False value
for whether the platform machine template changed, following the sibling
Autorepair checks while preserving the existing presence validation.
🤖 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.

Inline comments:
In `@hypershift-operator/controllers/nodepool/capi_test.go`:
- Around line 2071-2086: Update the MHC lookup in the autorepair-disabled
assertion to use the existing controlpaneNamespace variable instead of the
hardcoded "test-cp-namespace" value. Keep the name and IsNotFound validation
unchanged so the test verifies deletion in the actual control-plane namespace.

---

Nitpick comments:
In `@hypershift-operator/controllers/nodepool/capi_test.go`:
- Around line 2038-2046: The CAPIResult test only checks for the
UpdatingPlatformMachineTemplate condition’s presence. In the assertion around
foundUpdatingCondition, locate the matching condition and assert its Status
matches the expected True/False value for whether the platform machine template
changed, following the sibling Autorepair checks while preserving the existing
presence validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 7fe1bbcf-57f6-4c26-97b0-64f3fade88b3

📥 Commits

Reviewing files that changed from the base of the PR and between 159b233 and 9e1ffa7.

📒 Files selected for processing (1)
  • hypershift-operator/controllers/nodepool/capi_test.go

Comment on lines 2071 to 2086
} else {
mhc := &capiv1.MachineHealthCheck{}
err = capi.Client.Get(t.Context(), client.ObjectKey{Namespace: "test-cp-namespace", Name: tt.nodePool.GetName()}, mhc)
g.Expect(apierrors.IsNotFound(err)).To(BeTrue())

// Validate autorepair disabled condition is present.
foundAutorepair := false
for _, cond := range capiResult.Conditions {
if cond.Type == hyperv1.NodePoolAutorepairEnabledConditionType {
g.Expect(cond.Status).To(Equal(corev1.ConditionFalse))
foundAutorepair = true
break
}
}
g.Expect(foundAutorepair).To(BeTrue(), "expected AutorepairEnabled=False condition in CAPIResult")
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Hardcoded namespace makes this assertion vacuous.

Line 2073 checks MHC absence in the literal namespace "test-cp-namespace" instead of controlpaneNamespace (used consistently elsewhere, e.g. lines 2052, 2069). Since no object is ever created under that literal string in this fake client, IsNotFound is trivially true regardless of whether the AutoRepair=false MHC-deletion logic actually works against the real control-plane namespace — a regression here wouldn't be caught.

🐛 Proposed fix
 			} else {
 				mhc := &capiv1.MachineHealthCheck{}
-				err = capi.Client.Get(t.Context(), client.ObjectKey{Namespace: "test-cp-namespace", Name: tt.nodePool.GetName()}, mhc)
+				err = capi.Client.Get(t.Context(), client.ObjectKey{Namespace: controlpaneNamespace, Name: tt.nodePool.GetName()}, mhc)
 				g.Expect(apierrors.IsNotFound(err)).To(BeTrue())
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
} else {
mhc := &capiv1.MachineHealthCheck{}
err = capi.Client.Get(t.Context(), client.ObjectKey{Namespace: "test-cp-namespace", Name: tt.nodePool.GetName()}, mhc)
g.Expect(apierrors.IsNotFound(err)).To(BeTrue())
// Validate autorepair disabled condition is present.
foundAutorepair := false
for _, cond := range capiResult.Conditions {
if cond.Type == hyperv1.NodePoolAutorepairEnabledConditionType {
g.Expect(cond.Status).To(Equal(corev1.ConditionFalse))
foundAutorepair = true
break
}
}
g.Expect(foundAutorepair).To(BeTrue(), "expected AutorepairEnabled=False condition in CAPIResult")
}
} else {
mhc := &capiv1.MachineHealthCheck{}
err = capi.Client.Get(t.Context(), client.ObjectKey{Namespace: controlpaneNamespace, Name: tt.nodePool.GetName()}, mhc)
g.Expect(apierrors.IsNotFound(err)).To(BeTrue())
// Validate autorepair disabled condition is present.
foundAutorepair := false
for _, cond := range capiResult.Conditions {
if cond.Type == hyperv1.NodePoolAutorepairEnabledConditionType {
g.Expect(cond.Status).To(Equal(corev1.ConditionFalse))
foundAutorepair = true
break
}
}
g.Expect(foundAutorepair).To(BeTrue(), "expected AutorepairEnabled=False condition in CAPIResult")
}
🤖 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 `@hypershift-operator/controllers/nodepool/capi_test.go` around lines 2071 -
2086, Update the MHC lookup in the autorepair-disabled assertion to use the
existing controlpaneNamespace variable instead of the hardcoded
"test-cp-namespace" value. Keep the name and IsNotFound validation unchanged so
the test verifies deletion in the actual control-plane namespace.

@bryan-cox

Copy link
Copy Markdown
Member

/test address-review-comments

@hypershift-jira-solve-ci

Copy link
Copy Markdown
Contributor Author

Review agent triggered. View job

@openshift-ci

openshift-ci Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

@hypershift-jira-solve-ci[bot]: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

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

Labels

area/hypershift-operator Indicates the PR includes changes for the hypershift operator and API - outside an OCP release jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants