Skip to content

Conversation

@haoqing0110
Copy link
Member

@haoqing0110 haoqing0110 commented Nov 5, 2025

🤖 Generated with Claude Code

Summary

Related issue(s)

#1237

Fixes #

Summary by CodeRabbit

  • Chores

    • Updated module file: removed unused indirect requirements and applied a module replacement to streamline builds.
    • Switched configuration loading to a builder-based loader (behavior unchanged).
  • Refactor

    • Rollout status logic now requires an "Applied" condition with a matching generation before reporting Progressing or Degraded, avoiding stale status.
  • Tests

    • Tests updated to set an initial "Applied" condition in scenarios to match the new status evaluation.

@haoqing0110
Copy link
Member Author

/hold

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Nov 5, 2025

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: haoqing0110
Once this PR has been reviewed and has the lgtm label, please assign qiujian16 for approval. For more information see the Code Review Process.

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

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

@coderabbitai
Copy link

coderabbitai bot commented Nov 5, 2025

Walkthrough

Adds Applied-condition + ObservedGeneration gating to ManifestWork rollout status evaluation and updates related tests; swaps cloudevents config loader usage to the builder variant in several components; updates go.mod with a replace directive and removes multiple indirect requires.

Changes

Cohort / File(s) Summary
Dependency Management
go.mod
Added replace open-cluster-management.io/sdk-go => github.com/haoqing0110/sdk-go v0.0.0-20251105081906-aab7c4782f40; removed several indirect require entries (moby/docker-image-spec, moby/go-archive, docker, containerd errdefs, confluent kafka, go-winio, hcsshim, etc.).
Rollout status gating
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go
Added retrieval and gating on WorkApplied condition and its ObservedGeneration; require Applied with matching ObservedGeneration before evaluating Progressing/Degraded; reordered checks and added explanatory comments; same gating applied for hub-driven flow.
Unit & integration tests
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go, test/integration/work/manifestworkreplicaset_test.go
Inserted initial WorkApplied condition (Status=True, Reason, ObservedGeneration, LastTransitionTime) into multiple test cases before existing Progressing/Degraded/Available status injections to reflect Applied-first gating.
Cloudevents config loader
pkg/registration/register/grpc/spoke_driver.go, pkg/work/hub/manager.go, pkg/work/spoke/spokeagent.go
Replaced import open-cluster-management.io/sdk-go/pkg/cloudevents/generic with .../generic/options/builder and switched calls from generic.NewConfigLoader(...).LoadConfig() to builder.NewConfigLoader(...).LoadConfig(); call sites and error handling unchanged.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • Extra attention:
    • manifestworkreplicaset_deploy_reconcile.go: confirm Applied-first ordering and ObservedGeneration comparisons don't introduce regressions or race conditions.
    • Tests: ensure injected Applied conditions in unit/integration tests correctly model real-world timing/ObservedGeneration semantics.
    • go.mod: verify the replace target is intentional and that removing the listed indirect deps is safe.
    • Cloudevents loader swaps: validate builder loader preserves prior config behavior and error paths.

Possibly related PRs

Suggested reviewers

  • elgnay
  • zhiweiyin318

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is incomplete. The Summary section is empty, leaving the core purpose unexplained. The Fixes # line is not completed, and no implementation details are provided. Add a substantive summary explaining the bug being fixed, why the Applied condition check is needed, and complete the Fixes # reference to the related issue.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The PR title accurately reflects the main change: checking the Applied condition before evaluating rollout status, which is the core logic modification across multiple files.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 82c57fa and 65130d6.

⛔ Files ignored due to path filters (86)
  • go.sum is excluded by !**/*.sum
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/LICENSE is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/message.go is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/option.go is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/protocol.go is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/write_producer_message.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/LICENSE is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/.gitignore is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/00version.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/README.md is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/adminapi.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/adminoptions.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/api.html is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_darwin_amd64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_darwin_arm64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_dynamic.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_glibc_linux_amd64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_glibc_linux_arm64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_musl_linux_amd64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_musl_linux_arm64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_windows.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/config.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/consumer.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/context.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/error.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/error_gen.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/event.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/generated_errors.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/glue_rdkafka.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/handle.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/header.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/kafka.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/.gitignore is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/LICENSES.txt is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/README.md is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/bundle-import.sh is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/import.sh is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_darwin_amd64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_darwin_arm64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_glibc_linux_amd64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_glibc_linux_arm64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_musl_linux_amd64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_musl_linux_arm64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_windows.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/rdkafka.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/rdkafka_mock.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/log.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/message.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/metadata.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/misc.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/mockcluster.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/offset.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/producer.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/select_rdkafka.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/testconf-example.json is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/time.go is excluded by !vendor/**
  • vendor/modules.txt is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/apis/cluster/v1alpha1/rollout.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/addon/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/cluster/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/csr/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/event/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/lease/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/options/generic.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/agent/client/manifestwork.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/source/client/manifestwork.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/constants/constants.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/clients/agentclient.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/clients/baseclient.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/clients/sourceclient.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/metrics/metrics_collector.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/builder/optionsbuilder.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/agentoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/sourceoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/agentoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/options_noop.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/sourceoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/agentoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/sourceoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/ratelimiter.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/utils/ratelimiter.go is excluded by !vendor/**
📒 Files selected for processing (7)
  • go.mod (1 hunks)
  • pkg/registration/register/grpc/spoke_driver.go (3 hunks)
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go (1 hunks)
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go (8 hunks)
  • pkg/work/hub/manager.go (2 hunks)
  • pkg/work/spoke/spokeagent.go (2 hunks)
  • test/integration/work/manifestworkreplicaset_test.go (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/registration/register/grpc/spoke_driver.go
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-07-23T10:10:42.066Z
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1086
File: test/integration/util/grpc.go:146-146
Timestamp: 2025-07-23T10:10:42.066Z
Learning: In OCM codebase, there are two different GRPCServerOptions types: the local one in pkg/server/grpc/options.go (which only has GRPCServerConfig field) and the SDK one from open-cluster-management.io/sdk-go/pkg/cloudevents/server/grpc/options (which has ServerBindPort and other fields with default values). Test code uses the SDK version via grpcoptions import alias.

Applied to files:

  • pkg/work/hub/manager.go
  • pkg/work/spoke/spokeagent.go
  • go.mod
📚 Learning: 2025-10-28T02:55:13.893Z
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1224
File: pkg/registration/register/grpc/spoke_driver.go:89-98
Timestamp: 2025-10-28T02:55:13.893Z
Learning: In pkg/registration/register/grpc/spoke_driver.go (Go), when calling cloudeventscsr.NewAgentClientHolder with GenericClientOptions, the watcher store does not need to be explicitly provided via WithClientWatcherStore. The GenericClientOptions.AgentClient() method automatically creates a default AgentInformerWatcherStore if none is provided, which satisfies the NewAgentClientHolder requirements.

Applied to files:

  • pkg/work/hub/manager.go
  • pkg/work/spoke/spokeagent.go
📚 Learning: 2025-09-08T06:10:32.388Z
Learnt from: qiujian16
Repo: open-cluster-management-io/ocm PR: 1164
File: test/integration/work/deleteoption_test.go:42-42
Timestamp: 2025-09-08T06:10:32.388Z
Learning: The startWorkAgent function in the OCM test suite uses variadic parameters for decorators (...agentOptionsDecorator), allowing it to be called with just ctx and clusterName without requiring an explicit nil decorator parameter.

Applied to files:

  • pkg/work/spoke/spokeagent.go
📚 Learning: 2025-07-01T02:27:10.927Z
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1053
File: vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/agent/client/manifestwork.go:237-237
Timestamp: 2025-07-01T02:27:10.927Z
Learning: In OCM ManifestWork agent client, when a work is being deleted (DeletionTimestamp set and finalizers removed), the agent publishes a status update event (types.UpdateRequestAction) with ResourceDeleted condition set to True to inform the hub that deletion is complete, rather than publishing a delete request event.

Applied to files:

  • test/integration/work/manifestworkreplicaset_test.go
📚 Learning: 2025-09-03T08:43:34.751Z
Learnt from: qiujian16
Repo: open-cluster-management-io/ocm PR: 1158
File: test/integration/work/completedmanifestwork_test.go:216-256
Timestamp: 2025-09-03T08:43:34.751Z
Learning: In TTL=0 ManifestWork deletion tests, avoid waiting for WorkComplete condition because the controller deletes the resource immediately upon completion, creating a race condition where the test tries to check completion status on an already-deleted resource.

Applied to files:

  • test/integration/work/manifestworkreplicaset_test.go
🧬 Code graph analysis (4)
pkg/work/hub/manager.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/builder/optionsbuilder.go (1)
  • NewConfigLoader (24-29)
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go (1)
vendor/open-cluster-management.io/api/work/v1/types.go (1)
  • WorkApplied (500-500)
pkg/work/spoke/spokeagent.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/builder/optionsbuilder.go (1)
  • NewConfigLoader (24-29)
test/integration/work/manifestworkreplicaset_test.go (1)
vendor/open-cluster-management.io/api/work/v1/types.go (1)
  • WorkApplied (500-500)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: cloudevents-integration
  • GitHub Check: integration
  • GitHub Check: unit
  • GitHub Check: verify
  • GitHub Check: e2e-singleton
  • GitHub Check: e2e-hosted
  • GitHub Check: e2e
🔇 Additional comments (8)
test/integration/work/manifestworkreplicaset_test.go (5)

389-394: LGTM! Applied condition properly added before Progressing check.

The test now correctly sets the WorkApplied condition with matching ObservedGeneration before the WorkProgressing condition, aligning with the production gating logic in clusterRolloutStatusFunc.


413-418: LGTM! Consistent Applied condition setup.

The second batch of work status updates correctly includes the WorkApplied condition, maintaining consistency throughout the progressive rollout test.


456-461: LGTM! Applied condition correctly gates failure scenario.

The WorkApplied condition is properly set before Progressing and Degraded conditions in the max failure test scenario, ensuring the rollout status evaluation logic can proceed correctly.


518-525: LGTM! Applied condition added for min success time validation.

The WorkApplied condition is correctly positioned before the WorkProgressing condition, allowing the test to properly validate the minimum success time rollout behavior.


593-600: LGTM! Applied condition enables proper deadline validation.

The WorkApplied condition is correctly added before evaluating Progressing and Degraded states in the progress deadline test, ensuring accurate rollout timeout behavior.

pkg/work/hub/manager.go (1)

21-21: LGTM! Migration to builder-based config loader.

The change from generic.NewConfigLoader to builder.NewConfigLoader is consistent with the migration pattern across the codebase (also applied in spoke_driver.go and spokeagent.go). The functional behavior remains unchanged.

Also applies to: 80-80

pkg/work/spoke/spokeagent.go (1)

25-25: LGTM! Consistent migration to builder config loader.

The change aligns with the builder-based config loader migration pattern applied throughout the PR, maintaining consistency across hub and spoke components.

Also applies to: 229-230

pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go (1)

221-240: LGTM! Correctly implements Applied condition gating.

This change properly implements the PR objective by requiring the Applied condition to exist and have matching ObservedGeneration before evaluating agent-side Progressing and Degraded conditions. Key improvements:

  1. Prevents stale timestamp usage: Checking Applied first ensures the work has been properly applied by the hub controller before using agent-side condition timestamps
  2. Clear documentation: The inline comments effectively explain the order and rationale for the checks
  3. Generation matching: The ObservedGeneration check for Applied ensures the condition reflects the current manifest generation

The gating logic correctly returns ToApply status when Applied is missing or stale, preventing premature rollout decisions based on outdated condition states.


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.

@haoqing0110 haoqing0110 force-pushed the fix-rollout-applied-condition-check branch from af4dc06 to 31d8a33 Compare November 5, 2025 09:13
Copy link

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between af4dc06 and 31d8a33.

⛔ Files ignored due to path filters (86)
  • go.sum is excluded by !**/*.sum
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/LICENSE is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/message.go is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/option.go is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/protocol.go is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/write_producer_message.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/LICENSE is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/.gitignore is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/00version.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/README.md is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/adminapi.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/adminoptions.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/api.html is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_darwin_amd64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_darwin_arm64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_dynamic.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_glibc_linux_amd64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_glibc_linux_arm64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_musl_linux_amd64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_musl_linux_arm64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_windows.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/config.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/consumer.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/context.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/error.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/error_gen.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/event.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/generated_errors.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/glue_rdkafka.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/handle.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/header.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/kafka.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/.gitignore is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/LICENSES.txt is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/README.md is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/bundle-import.sh is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/import.sh is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_darwin_amd64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_darwin_arm64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_glibc_linux_amd64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_glibc_linux_arm64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_musl_linux_amd64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_musl_linux_arm64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_windows.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/rdkafka.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/rdkafka_mock.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/log.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/message.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/metadata.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/misc.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/mockcluster.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/offset.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/producer.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/select_rdkafka.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/testconf-example.json is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/time.go is excluded by !vendor/**
  • vendor/modules.txt is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/apis/cluster/v1alpha1/rollout.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/addon/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/cluster/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/csr/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/event/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/lease/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/options/generic.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/agent/client/manifestwork.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/source/client/manifestwork.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/constants/constants.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/clients/agentclient.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/clients/baseclient.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/clients/sourceclient.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/metrics/metrics_collector.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/builder/optionsbuilder.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/agentoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/sourceoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/agentoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/options_noop.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/sourceoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/agentoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/sourceoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/ratelimiter.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/utils/ratelimiter.go is excluded by !vendor/**
📒 Files selected for processing (2)
  • go.mod (1 hunks)
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-07-23T10:10:42.066Z
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1086
File: test/integration/util/grpc.go:146-146
Timestamp: 2025-07-23T10:10:42.066Z
Learning: In OCM codebase, there are two different GRPCServerOptions types: the local one in pkg/server/grpc/options.go (which only has GRPCServerConfig field) and the SDK one from open-cluster-management.io/sdk-go/pkg/cloudevents/server/grpc/options (which has ServerBindPort and other fields with default values). Test code uses the SDK version via grpcoptions import alias.

Applied to files:

  • go.mod
🧬 Code graph analysis (1)
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go (1)
vendor/open-cluster-management.io/api/work/v1/types.go (1)
  • WorkApplied (500-500)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: integration
  • GitHub Check: verify
  • GitHub Check: e2e-hosted
  • GitHub Check: unit
  • GitHub Check: e2e-singleton
  • GitHub Check: build
  • GitHub Check: e2e
🔇 Additional comments (2)
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go (2)

221-221: Good addition of Applied condition check.

Retrieving the Applied condition aligns with the PR objective to check hub-side application status before evaluating agent-side conditions.


224-240: No backward compatibility issue—code correctly handles ManifestWorks without Applied condition.

The Applied condition is set by the spoke-side controller (pkg/work/spoke/controllers/manifestcontroller/manifestwork_reconciler.go:108) during normal manifest reconciliation. ManifestWorks created without the Applied condition is expected behavior, explicitly documented in appliedmanifestwork_reconciler.go:42–47 with graceful handling for missing conditions. The lines 224–240 correctly gate rollout evaluation until the condition exists and observes the current generation—this is proper design, not a bug. Old ManifestWorks will eventually have the condition set as the spoke applies them.

Likely an incorrect or invalid review comment.

Comment on lines +5 to +6
replace open-cluster-management.io/sdk-go => github.com/haoqing0110/sdk-go v0.0.0-20251105081906-aab7c4782f40

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Replace personal fork with official upstream release.

The replace directive points to a personal fork (github.com/haoqing0110/sdk-go) with a pseudo-version, which introduces supply chain risk and makes the build non-reproducible. Personal forks should not be used in production code.

Please take one of the following actions:

  1. Preferred: Upstream your changes to the official open-cluster-management.io/sdk-go repository and wait for an official release
  2. Temporary workaround (if urgent): Document why this temporary fork is necessary, link to the upstream PR, and create an issue to track replacing it with the official release

Once the changes are available in the official repository, update to use a proper semantic version:

-replace open-cluster-management.io/sdk-go => github.com/haoqing0110/sdk-go v0.0.0-20251105081906-aab7c4782f40
+// Remove replace directive once sdk-go releases version with required changes

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In go.mod around lines 5-6, the replace directive points to a personal fork
(github.com/haoqing0110/sdk-go) with a pseudo-version; replace it by using the
official upstream module and a proper semantic version once available: remove
the replace directive and set the require to open-cluster-management.io/sdk-go
at the released semver; if an immediate release isn’t available and you must
keep the fork temporarily, add a comment in the repository documenting why the
fork is used, link the upstream PR, and open a tracked issue to revert to
upstream when a release is made (then update go.mod to the official semver and
remove the replace).

@haoqing0110 haoqing0110 force-pushed the fix-rollout-applied-condition-check branch 2 times, most recently from f0f9234 to 82c57fa Compare November 5, 2025 16:54
@codecov
Copy link

codecov bot commented Nov 5, 2025

Codecov Report

❌ Patch coverage is 75.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.16%. Comparing base (d80ec55) to head (65130d6).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
pkg/work/hub/manager.go 0.00% 1 Missing ⚠️
pkg/work/spoke/spokeagent.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main    #1243   +/-   ##
=======================================
  Coverage   62.15%   62.16%           
=======================================
  Files         209      209           
  Lines       16968    16971    +3     
=======================================
+ Hits        10547    10550    +3     
  Misses       5304     5304           
  Partials     1117     1117           
Flag Coverage Δ
unit 62.16% <75.00%> (+<0.01%) ⬆️

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

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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

Copy link

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

Actionable comments posted: 0

🧹 Nitpick comments (1)
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go (1)

902-1135: Comprehensive test coverage, but consider adding one more scenario.

The test cases thoroughly cover various combinations of Progressing and Degraded conditions, and correctly inject the Applied condition in all scenarios that should progress past ToApply status.

However, consider adding a test case for:

  • Applied condition exists but Applied.ObservedGeneration != ManifestWork.Generation (should return ToApply)

This scenario is explicitly checked in the reconcile logic (lines 234-235 of manifestworkreplicaset_deploy_reconcile.go) but not directly tested here.

Add this test case to verify the Applied ObservedGeneration gating:

{
    name: "applied condition with unobserved generation - should return ToApply",
    manifestWork: &workapiv1.ManifestWork{
        ObjectMeta: metav1.ObjectMeta{
            Name:              "test-mw",
            Namespace:         "cls1",
            Generation:        2,
            CreationTimestamp: creationTime,
        },
        Status: workapiv1.ManifestWorkStatus{
            Conditions: []metav1.Condition{
                {
                    Type:               workapiv1.WorkApplied,
                    Status:             metav1.ConditionTrue,
                    ObservedGeneration: 1, // Stale generation
                    LastTransitionTime: now,
                    Reason:             "Applied",
                },
                {
                    Type:               workapiv1.WorkProgressing,
                    Status:             metav1.ConditionFalse,
                    ObservedGeneration: 2,
                    LastTransitionTime: now,
                    Reason:             "Completed",
                },
            },
        },
    },
    expectedStatus:         clustersdkv1alpha1.ToApply,
    expectedLastTransition: nil,
},
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0f9234 and 82c57fa.

⛔ Files ignored due to path filters (86)
  • go.sum is excluded by !**/*.sum
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/LICENSE is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/message.go is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/option.go is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/protocol.go is excluded by !vendor/**
  • vendor/github.com/cloudevents/sdk-go/protocol/kafka_confluent/v2/write_producer_message.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/LICENSE is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/.gitignore is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/00version.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/README.md is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/adminapi.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/adminoptions.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/api.html is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_darwin_amd64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_darwin_arm64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_dynamic.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_glibc_linux_amd64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_glibc_linux_arm64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_musl_linux_amd64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_musl_linux_arm64.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/build_windows.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/config.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/consumer.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/context.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/error.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/error_gen.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/event.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/generated_errors.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/glue_rdkafka.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/handle.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/header.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/kafka.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/.gitignore is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/LICENSES.txt is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/README.md is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/bundle-import.sh is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/import.sh is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_darwin_amd64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_darwin_arm64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_glibc_linux_amd64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_glibc_linux_arm64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_musl_linux_amd64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_musl_linux_arm64.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/librdkafka_windows.a is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/rdkafka.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/librdkafka_vendor/rdkafka_mock.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/log.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/message.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/metadata.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/misc.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/mockcluster.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/offset.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/producer.go is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/select_rdkafka.h is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/testconf-example.json is excluded by !vendor/**
  • vendor/github.com/confluentinc/confluent-kafka-go/v2/kafka/time.go is excluded by !vendor/**
  • vendor/modules.txt is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/apis/cluster/v1alpha1/rollout.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/addon/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/cluster/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/csr/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/event/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/lease/client.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/options/generic.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/agent/client/manifestwork.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/source/client/manifestwork.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/constants/constants.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/clients/agentclient.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/clients/baseclient.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/clients/sourceclient.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/metrics/metrics_collector.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/builder/optionsbuilder.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/agentoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/grpc/sourceoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/agentoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/options_noop.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/kafka/sourceoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/agentoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/mqtt/sourceoptions.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/options.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/ratelimiter.go is excluded by !vendor/**
  • vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/utils/ratelimiter.go is excluded by !vendor/**
📒 Files selected for processing (6)
  • go.mod (1 hunks)
  • pkg/registration/register/grpc/spoke_driver.go (3 hunks)
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go (1 hunks)
  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go (8 hunks)
  • pkg/work/hub/manager.go (2 hunks)
  • pkg/work/spoke/spokeagent.go (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • go.mod
  • pkg/registration/register/grpc/spoke_driver.go
🧰 Additional context used
🧠 Learnings (5)
📚 Learning: 2025-07-23T10:10:42.066Z
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1086
File: test/integration/util/grpc.go:146-146
Timestamp: 2025-07-23T10:10:42.066Z
Learning: In OCM codebase, there are two different GRPCServerOptions types: the local one in pkg/server/grpc/options.go (which only has GRPCServerConfig field) and the SDK one from open-cluster-management.io/sdk-go/pkg/cloudevents/server/grpc/options (which has ServerBindPort and other fields with default values). Test code uses the SDK version via grpcoptions import alias.

Applied to files:

  • pkg/work/hub/manager.go
  • pkg/work/spoke/spokeagent.go
📚 Learning: 2025-10-28T02:55:13.893Z
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1224
File: pkg/registration/register/grpc/spoke_driver.go:89-98
Timestamp: 2025-10-28T02:55:13.893Z
Learning: In pkg/registration/register/grpc/spoke_driver.go (Go), when calling cloudeventscsr.NewAgentClientHolder with GenericClientOptions, the watcher store does not need to be explicitly provided via WithClientWatcherStore. The GenericClientOptions.AgentClient() method automatically creates a default AgentInformerWatcherStore if none is provided, which satisfies the NewAgentClientHolder requirements.

Applied to files:

  • pkg/work/hub/manager.go
  • pkg/work/spoke/spokeagent.go
📚 Learning: 2025-09-03T08:43:34.751Z
Learnt from: qiujian16
Repo: open-cluster-management-io/ocm PR: 1158
File: test/integration/work/completedmanifestwork_test.go:216-256
Timestamp: 2025-09-03T08:43:34.751Z
Learning: In TTL=0 ManifestWork deletion tests, avoid waiting for WorkComplete condition because the controller deletes the resource immediately upon completion, creating a race condition where the test tries to check completion status on an already-deleted resource.

Applied to files:

  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go
📚 Learning: 2025-07-01T02:27:10.927Z
Learnt from: skeeey
Repo: open-cluster-management-io/ocm PR: 1053
File: vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/clients/work/agent/client/manifestwork.go:237-237
Timestamp: 2025-07-01T02:27:10.927Z
Learning: In OCM ManifestWork agent client, when a work is being deleted (DeletionTimestamp set and finalizers removed), the agent publishes a status update event (types.UpdateRequestAction) with ResourceDeleted condition set to True to inform the hub that deletion is complete, rather than publishing a delete request event.

Applied to files:

  • pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go
📚 Learning: 2025-09-08T06:10:32.388Z
Learnt from: qiujian16
Repo: open-cluster-management-io/ocm PR: 1164
File: test/integration/work/deleteoption_test.go:42-42
Timestamp: 2025-09-08T06:10:32.388Z
Learning: The startWorkAgent function in the OCM test suite uses variadic parameters for decorators (...agentOptionsDecorator), allowing it to be called with just ctx and clusterName without requiring an explicit nil decorator parameter.

Applied to files:

  • pkg/work/spoke/spokeagent.go
🧬 Code graph analysis (4)
pkg/work/hub/manager.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/builder/optionsbuilder.go (1)
  • NewConfigLoader (24-29)
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go (1)
vendor/open-cluster-management.io/api/work/v1/types.go (1)
  • WorkApplied (500-500)
pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go (1)
vendor/open-cluster-management.io/api/work/v1/types.go (1)
  • WorkApplied (500-500)
pkg/work/spoke/spokeagent.go (1)
vendor/open-cluster-management.io/sdk-go/pkg/cloudevents/generic/options/builder/optionsbuilder.go (1)
  • NewConfigLoader (24-29)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: integration
  • GitHub Check: unit
  • GitHub Check: verify
  • GitHub Check: e2e-singleton
  • GitHub Check: cloudevents-integration
  • GitHub Check: e2e-hosted
  • GitHub Check: e2e
🔇 Additional comments (5)
pkg/work/hub/manager.go (1)

21-21: LGTM! Clean refactoring to builder-based config loading.

The migration from generic.NewConfigLoader to builder.NewConfigLoader is straightforward and maintains the same API surface. Error handling and control flow remain unchanged.

Also applies to: 80-80

pkg/work/spoke/spokeagent.go (1)

25-25: LGTM! Consistent builder-based config loading.

The change aligns with the builder pattern migration seen in pkg/work/hub/manager.go. The multi-line formatting of the config loader call improves readability.

Also applies to: 229-230

pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go (2)

231-233: Excellent documentation of the ordering requirement.

The comment clearly explains why Applied must be checked before Progressing/Degraded to prevent using stale timestamps from previous generations. This is critical for correct rollout timeout calculations.


221-240: Fix misleading comment about which controller sets WorkApplied condition.

Line 224 comment incorrectly states Applied condition is set by "hub controller" when it's actually set by the spoke/agent controller during manifest reconciliation. Update the comment to accurately reflect that Applied represents the spoke controller's view of work application state. The logic itself is correct—returning ToApply for works without an Applied condition is the intended safe behavior, not a breaking change. Existing ManifestWorks will naturally receive the Applied condition as the spoke controller reconciles them.

Likely an incorrect or invalid review comment.

pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go (1)

594-601: Good test setup aligning with the new Applied condition requirement.

The test correctly sets the Applied condition with matching ObservedGeneration before simulating the Progressing/Degraded states. This ensures the gating logic allows evaluation of rollout status.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <[email protected]>
Signed-off-by: Qing Hao <[email protected]>
@haoqing0110 haoqing0110 force-pushed the fix-rollout-applied-condition-check branch from 82c57fa to 65130d6 Compare November 6, 2025 04:13
@haoqing0110
Copy link
Member Author

/assign @qiujian16 @youngbupark

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Nov 6, 2025

@haoqing0110: GitHub didn't allow me to assign the following users: youngbupark.

Note that only open-cluster-management-io members with read permissions, repo collaborators and people who have commented on this issue/PR can be assigned. Additionally, issues/PRs can only have 10 assignees at the same time.
For more information please see the contributor guide

In response to this:

/assign @qiujian16 @youngbupark

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.

// IMPORTANT: Check Applied condition FIRST to ensure the work has been properly applied
// before checking agent-side conditions. This prevents using stale timestamps from
// previous generations when conditions update their ObservedGeneration without changing Status.
if appliedCond == nil ||

Choose a reason for hiding this comment

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

Is this the only change made to fix this issue?

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.

3 participants