Skip to content

CONSOLE-5087: Refactor console-shared-package from Firehose to useK8sWatchResource#16077

Open
cajieh wants to merge 1 commit intoopenshift:mainfrom
cajieh:refactor-console-shared-package-firehose-usek8swatchresource
Open

CONSOLE-5087: Refactor console-shared-package from Firehose to useK8sWatchResource#16077
cajieh wants to merge 1 commit intoopenshift:mainfrom
cajieh:refactor-console-shared-package-firehose-usek8swatchresource

Conversation

@cajieh
Copy link
Contributor

@cajieh cajieh commented Feb 27, 2026

Summary by CodeRabbit

  • New Features

    • Resource dropdowns (secrets, projects, service accounts, PVCs) now dynamically fetch real-time data from your Kubernetes cluster, automatically reflecting resource changes without requiring page refresh.
  • Refactor

    • Improved resource loading performance and responsiveness across dropdown components by switching to dynamic data fetching.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Feb 27, 2026
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Feb 27, 2026

@cajieh: This pull request references CONSOLE-5087 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 story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

NOT READY FOR REVIEW

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.

@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Feb 27, 2026
@openshift-ci openshift-ci bot requested review from Leo6Leo and sg00dwin February 27, 2026 15:57
@openshift-ci openshift-ci bot added component/dev-console Related to dev-console component/helm Related to helm-plugin approved Indicates a PR has been approved by an approver from all required OWNERS files. component/knative Related to knative-plugin component/shared Related to console-shared labels Feb 27, 2026
import type { FirehoseResource } from '@console/internal/components/utils/types';
import type { K8sResourceKind } from '@console/internal/module/k8s';
import { useField, useFormikContext, FormikValues } from 'formik';
import type { FirehoseResult } from '@console/internal/components/utils/types';
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This change would likely require creating a new type, as WatchK8sResultsObject does not support manually adding a kind property, which FirehoseResult does. This will be addressed in the 'Refactor Firehose Types' story.

  Create a new type in console-shared that represents the unified shape:

  // packages/console-shared/src/types/resource-watch.ts
  export type ResourceWatchResult<R = K8sResourceKind[]> = {
    data: R;
    loaded: boolean;
    loadError?: any;
    kind: string;
  };

  Then update ResourceDropdownField.tsx:

  import { ResourceWatchResult } from '../types/resource-watch';

  export interface ResourceDropdownFieldProps extends DropdownFieldProps {
    dataSelector: string[] | number[] | symbol[];
    resources: ResourceWatchResult[];  // Changed from FirehoseResult[]
    // ... rest
  }

@cajieh cajieh force-pushed the refactor-console-shared-package-firehose-usek8swatchresource branch 2 times, most recently from 80db95e to 56e5d1f Compare March 2, 2026 21:08
@openshift-ci openshift-ci bot added component/core Related to console core functionality kind/i18n Indicates issue or PR relates to internationalization or has content that needs to be translated labels Mar 2, 2026
@cajieh cajieh force-pushed the refactor-console-shared-package-firehose-usek8swatchresource branch 2 times, most recently from 7e0e541 to 2c965cf Compare March 2, 2026 22:56
cajieh added a commit to cajieh/console that referenced this pull request Mar 2, 2026
cajieh added a commit to cajieh/console that referenced this pull request Mar 2, 2026
@cajieh cajieh force-pushed the refactor-console-shared-package-firehose-usek8swatchresource branch 2 times, most recently from 1f56752 to 5770bf3 Compare March 3, 2026 15:55
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 3, 2026

@cajieh: This pull request references CONSOLE-5087 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 story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

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.

@cajieh cajieh changed the title [WIP] CONSOLE-5087: Refactor console-shared-package from Firehose to useK8sWatchResource CONSOLE-5087: Refactor console-shared-package from Firehose to useK8sWatchResource Mar 3, 2026
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Mar 3, 2026
@cajieh cajieh force-pushed the refactor-console-shared-package-firehose-usek8swatchresource branch from 5770bf3 to c857a49 Compare March 3, 2026 17:09
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 3, 2026

📝 Walkthrough

Walkthrough

This pull request systematically refactors resource data sourcing across multiple frontend packages, replacing static FirehoseResource declarations with dynamic Kubernetes watch hooks (useK8sWatchResources / useK8sWatchResource). The ResourceDropdownField component signature is updated to accept FirehoseResult[] instead of FirehoseResource[], with local loading state derived via useMemo. Affected components—including SecretsSection, TriggersSection, ImageStreamDropdown, WebhookSection, SinkResources, and others—now use watch-based data collection, construct memoized resource arrays from watched data, and employ referenceForModel for kind references. Test files are updated to mock the new watch hooks and adjust assertions accordingly. Supporting type imports and utilities are added for K8sResourceKind, WatchK8sResource, and related typing.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main refactoring effort: migrating from Firehose to useK8sWatchResource across the console-shared-package.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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

Copy link
Contributor

@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: 4

🧹 Nitpick comments (3)
frontend/packages/webterminal-plugin/src/components/cloud-shell/setup/NamespaceSection.tsx (1)

61-71: Consider memoizing handleOnLoad for consistency.

While onDropdownChange is correctly memoized with useCallback, handleOnLoad is not. Given that it closes over namespace.value, canCreate, and setFieldValue, memoizing it would require listing those as dependencies—so the benefit is marginal. However, for consistency with other callbacks in this component and to avoid potential unnecessary child re-renders if ResourceDropdownField uses callback identity in any effects, you might consider wrapping it.

This is a minor optimization and can be deferred if preferred.

♻️ Optional: Memoize handleOnLoad
-  const handleOnLoad = (projectList: { [key: string]: string }) => {
+  const handleOnLoad = useCallback((projectList: { [key: string]: string }) => {
     const noProjects = _.isEmpty(projectList);
     if (noProjects || !projectList[namespace.value]) {
       if (canCreate && namespace.value !== CREATE_NAMESPACE_KEY) {
         setFieldValue('namespace', CREATE_NAMESPACE_KEY);
       }
       if (!canCreate && namespace.value) {
         setFieldValue('namespace', undefined);
       }
     }
-  };
+  }, [namespace.value, canCreate, setFieldValue]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/webterminal-plugin/src/components/cloud-shell/setup/NamespaceSection.tsx`
around lines 61 - 71, The handleOnLoad function is not memoized while
onDropdownChange is; wrap handleOnLoad in useCallback with dependencies
[namespace.value, canCreate, setFieldValue] so it retains identity across
renders (helpful if ResourceDropdownField relies on callback identity) and
update its declaration accordingly; ensure you import useCallback from React if
not already imported and keep the existing logic inside the memoized
handleOnLoad.
frontend/packages/dev-console/src/components/buildconfig/sections/SecretsSection.tsx (1)

27-49: Consider extracting a shared useSecretDropdownResources(namespace) helper.

Line 27 through Line 49 duplicates the same watch-to-dropdown adapter now present in multiple components. Centralizing this mapping would reduce drift and make future resource-shape updates safer.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/dev-console/src/components/buildconfig/sections/SecretsSection.tsx`
around lines 27 - 49, Extract the duplicated watch-to-dropdown mapping into a
shared hook named useSecretDropdownResources(namespace): move the
useK8sWatchResources call and the useMemo adapter that produces the resources
array into this helper, have it accept namespace and return the resources array
shaped with data, loaded, loadError and kind (matching current output), and
replace the local watchedResources/resources logic in SecretsSection by calling
useSecretDropdownResources(namespace); ensure the hook references SecretModel
and SecretKind and lists watchedResources.secrets.data, .loaded, .loadError in
its useMemo dependency array so behavior and memoization remain identical.
frontend/packages/knative-plugin/src/components/add/event-sinks/form-fields/SourceResources.tsx (1)

73-77: Prefer fully-qualified refs in resourcesData.kind for consistency with watch keys.

Line 77 and Line 90 currently emit bare kind names. Since watch keys are already reference-based, using refs here avoids model ambiguity and keeps dropdown model mapping deterministic.

♻️ Proposed refactor
     if (watchedResources.brokers) {
       result.push({
         data: watchedResources.brokers.data,
         loaded: watchedResources.brokers.loaded,
         loadError: watchedResources.brokers.loadError,
-        kind: EventingBrokerModel.kind,
+        kind: referenceForModel(EventingBrokerModel),
       });
     }
@@
         if (watchedResources[ref]) {
           result.push({
             data: watchedResources[ref].data,
             loaded: watchedResources[ref].loaded,
             loadError: watchedResources[ref].loadError,
-            kind: model.kind,
+            kind: ref,
           });
         }

Also applies to: 84-91

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/components/add/event-sinks/form-fields/SourceResources.tsx`
around lines 73 - 77, Replace the bare kind values with fully-qualified model
refs in the objects pushed into the result array: instead of using
EventingBrokerModel.kind and CloudEventSourceModel.kind, call the utility that
produces reference-based kinds (e.g., referenceForModel) for those models so
resourcesData.kind matches the watch keys; update both the broker entry and the
cloud event source entry in SourceResources.tsx (the objects built where
watchedResources.brokers and watchedResources.cloudEventSources are used) to use
referenceForModel(EventingBrokerModel) and
referenceForModel(CloudEventSourceModel) respectively.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@frontend/packages/console-shared/src/components/formik-fields/ResourceDropdownField.tsx`:
- Around line 55-64: The aggregation in the useMemo for { loaded, loadError }
incorrectly treats optional resources as required and stringifies errors; update
it to only consider required resources when computing loaded/loadError (i.e.,
filter resources to those where optional !== true or required === true) so
optional watch failures don't block the UI, and return the first raw error
object (do not String(...) it) so callers keep the original error semantics;
adjust the useMemo in ResourceDropdownField that computes loaded/loadError from
resources accordingly and ensure the fallback when there are no required
resources remains { loaded: true, loadError: undefined }.

In
`@frontend/packages/knative-plugin/src/components/add/event-sinks/__tests__/KafkaSinkSection.spec.tsx`:
- Around line 39-42: The test for KafkaSinkSection currently only checks the
presence of the FormSection but claims to verify the title; update the test in
KafkaSinkSection.spec.tsx to assert the rendered title by using the title prop
(e.g., the title variable passed into <KafkaSinkSection title={title} ... />) —
locate the test block with the render call and add an assertion that the DOM
contains the expected title string (via getByText or
container.querySelector/textContent) so the spec actually verifies the
component’s displayed title.

In
`@frontend/packages/knative-plugin/src/components/add/event-sources/form-fields/SinkResources.tsx`:
- Around line 119-172: The resourcesData useMemo collects watchedResources
entries but passes their .data directly, which can be undefined during initial
load/error; update each push in resourcesData (for services, ksservices,
brokers, kafkasinks and the dynamic channel branch inside the channels.forEach)
to use a safe fallback for the data property (e.g., data:
watchedResources.X.data || []) so ResourceDropdownField always receives an
array; keep the existing loaded and loadError fields and use referenceForModel
and model.kind unchanged.

In
`@frontend/packages/knative-plugin/src/components/pub-sub/form-fields/PubSubSubscriber.tsx`:
- Around line 61-80: The resources array uses bare Model.kind strings which can
be ambiguous between core Service and Knative Service; update each resource
entry to use referenceForModel(Model) (the same helper used in watchSpec) so
ResourceDropdown resolves the exact apiVersion/group: replace occurrences where
resources list items set kind: ServiceModel.kind or similar with kind:
referenceForModel(ServiceModel) (and do the same for KnativeServiceModel,
KafkaSinkModel, etc.), ensuring watchSpec and the resources array consistently
use referenceForModel to avoid model resolution errors in ResourceDropdown.

---

Nitpick comments:
In
`@frontend/packages/dev-console/src/components/buildconfig/sections/SecretsSection.tsx`:
- Around line 27-49: Extract the duplicated watch-to-dropdown mapping into a
shared hook named useSecretDropdownResources(namespace): move the
useK8sWatchResources call and the useMemo adapter that produces the resources
array into this helper, have it accept namespace and return the resources array
shaped with data, loaded, loadError and kind (matching current output), and
replace the local watchedResources/resources logic in SecretsSection by calling
useSecretDropdownResources(namespace); ensure the hook references SecretModel
and SecretKind and lists watchedResources.secrets.data, .loaded, .loadError in
its useMemo dependency array so behavior and memoization remain identical.

In
`@frontend/packages/knative-plugin/src/components/add/event-sinks/form-fields/SourceResources.tsx`:
- Around line 73-77: Replace the bare kind values with fully-qualified model
refs in the objects pushed into the result array: instead of using
EventingBrokerModel.kind and CloudEventSourceModel.kind, call the utility that
produces reference-based kinds (e.g., referenceForModel) for those models so
resourcesData.kind matches the watch keys; update both the broker entry and the
cloud event source entry in SourceResources.tsx (the objects built where
watchedResources.brokers and watchedResources.cloudEventSources are used) to use
referenceForModel(EventingBrokerModel) and
referenceForModel(CloudEventSourceModel) respectively.

In
`@frontend/packages/webterminal-plugin/src/components/cloud-shell/setup/NamespaceSection.tsx`:
- Around line 61-71: The handleOnLoad function is not memoized while
onDropdownChange is; wrap handleOnLoad in useCallback with dependencies
[namespace.value, canCreate, setFieldValue] so it retains identity across
renders (helpful if ResourceDropdownField relies on callback identity) and
update its declaration accordingly; ensure you import useCallback from React if
not already imported and keep the existing logic inside the memoized
handleOnLoad.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between f913459 and c857a49.

📒 Files selected for processing (24)
  • frontend/packages/console-shared/src/components/formik-fields/ResourceDropdownField.tsx
  • frontend/packages/dev-console/src/components/buildconfig/sections/SecretsSection.tsx
  • frontend/packages/dev-console/src/components/buildconfig/sections/TriggersSection.tsx
  • frontend/packages/dev-console/src/components/buildconfig/sections/__tests__/TriggersSection.spec.tsx
  • frontend/packages/dev-console/src/components/deployments/images/AdvancedImageOptions.tsx
  • frontend/packages/dev-console/src/components/import/image-search/ImageStreamDropdown.tsx
  • frontend/packages/dev-console/src/components/import/image-search/ImageStreamNsDropdown.tsx
  • frontend/packages/dev-console/src/components/pipeline-section/pipeline/WebhookSection.tsx
  • frontend/packages/helm-plugin/src/components/forms/HelmChartRepository/CreateHelmChartRepositoryFormEditor.tsx
  • frontend/packages/knative-plugin/src/components/add/event-sinks/KafkaSinkSection.tsx
  • frontend/packages/knative-plugin/src/components/add/event-sinks/__tests__/KafkaSinkSection.spec.tsx
  • frontend/packages/knative-plugin/src/components/add/event-sinks/form-fields/SourceResources.tsx
  • frontend/packages/knative-plugin/src/components/add/event-sources/form-fields/SinkResources.tsx
  • frontend/packages/knative-plugin/src/components/add/event-sources/form-fields/__tests__/SinkResources.spec.tsx
  • frontend/packages/knative-plugin/src/components/dropdowns/ServiceAccountDropdown.tsx
  • frontend/packages/knative-plugin/src/components/pub-sub/form-fields/PubSubSubscriber.tsx
  • frontend/packages/knative-plugin/src/components/sink-pubsub/SinkPubsub.tsx
  • frontend/packages/knative-plugin/src/components/sink-pubsub/SinkPubsubModal.tsx
  • frontend/packages/knative-plugin/src/components/sink-pubsub/__tests__/SinkPubsub.spec.tsx
  • frontend/packages/knative-plugin/src/components/sink-pubsub/__tests__/SinkPubsubModal.spec.tsx
  • frontend/packages/shipwright-plugin/src/components/build-form/PVCDropdown.tsx
  • frontend/packages/shipwright-plugin/src/components/build-form/SecretDropdown.tsx
  • frontend/packages/webterminal-plugin/src/components/cloud-shell/setup/NamespaceSection.tsx
  • frontend/public/locales/en/public.json

Comment on lines +55 to +64
const { loaded, loadError } = useMemo(() => {
if (!resources || resources.length === 0) {
return { loaded: true, loadError: undefined };
}
const allLoaded = resources.every((r) => r.loaded);
const firstError = resources.find((r) => r.loadError)?.loadError;
return {
loaded: allLoaded,
loadError: firstError ? String(firstError) : undefined,
};
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Preserve optional-resource semantics when deriving loaded/loadError.

Line 59-63 now aggregates across all resources and stringifies errors. This diverges from prior Firehose behavior (required-resource filtering), and may surface optional watch errors as blocking UI errors.

Proposed fix
-  const { loaded, loadError } = useMemo(() => {
+  const { loaded, loadError } = useMemo(() => {
     if (!resources || resources.length === 0) {
       return { loaded: true, loadError: undefined };
     }
-    const allLoaded = resources.every((r) => r.loaded);
-    const firstError = resources.find((r) => r.loadError)?.loadError;
+    const required = (resources as Array<{ loaded: boolean; loadError?: unknown; optional?: boolean }>)
+      .filter((r) => !r.optional);
+    const target = required.length ? required : resources;
+    const allLoaded = target.every((r) => r.loaded);
+    const firstError = target.find((r) => r.loadError)?.loadError;
     return {
       loaded: allLoaded,
-      loadError: firstError ? String(firstError) : undefined,
+      loadError: firstError,
     };
   }, [resources]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/console-shared/src/components/formik-fields/ResourceDropdownField.tsx`
around lines 55 - 64, The aggregation in the useMemo for { loaded, loadError }
incorrectly treats optional resources as required and stringifies errors; update
it to only consider required resources when computing loaded/loadError (i.e.,
filter resources to those where optional !== true or required === true) so
optional watch failures don't block the UI, and return the first raw error
object (do not String(...) it) so callers keep the original error semantics;
adjust the useMemo in ResourceDropdownField that computes loaded/loadError from
resources accordingly and ensure the fallback when there are no required
resources remains { loaded: true, loadError: undefined }.

Comment on lines 39 to 42
it('should render KafkaSink FormSection with proper title', () => {
const { container } = render(<KafkaSinkSection title={title} namespace="my-app" />);
expect(container.querySelector('FormSection')).toBeInTheDocument();
});
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Test intent mismatch: title is not actually asserted.

Line 39 says “proper title,” but Line 41 only checks element presence. Add a title assertion so the test guards the described behavior.

✅ Proposed test fix
   it('should render KafkaSink FormSection with proper title', () => {
     const { container } = render(<KafkaSinkSection title={title} namespace="my-app" />);
-    expect(container.querySelector('FormSection')).toBeInTheDocument();
+    const formSection = container.querySelector('FormSection');
+    expect(formSection).toBeInTheDocument();
+    expect(formSection).toHaveAttribute('title', title);
   });
📝 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
it('should render KafkaSink FormSection with proper title', () => {
const { container } = render(<KafkaSinkSection title={title} namespace="my-app" />);
expect(container.querySelector('FormSection')).toBeInTheDocument();
});
it('should render KafkaSink FormSection with proper title', () => {
const { container } = render(<KafkaSinkSection title={title} namespace="my-app" />);
const formSection = container.querySelector('FormSection');
expect(formSection).toBeInTheDocument();
expect(formSection).toHaveAttribute('title', title);
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/components/add/event-sinks/__tests__/KafkaSinkSection.spec.tsx`
around lines 39 - 42, The test for KafkaSinkSection currently only checks the
presence of the FormSection but claims to verify the title; update the test in
KafkaSinkSection.spec.tsx to assert the rendered title by using the title prop
(e.g., the title variable passed into <KafkaSinkSection title={title} ... />) —
locate the test block with the render call and add an assertion that the DOM
contains the expected title string (via getByText or
container.querySelector/textContent) so the spec actually verifies the
component’s displayed title.

Comment on lines +119 to +172
const resourcesData = useMemo(() => {
const result = [];

// Add static resources
if (watchedResources.services) {
result.push({
data: watchedResources.services.data,
loaded: watchedResources.services.loaded,
loadError: watchedResources.services.loadError,
kind: 'Service',
});
}
if (watchedResources.ksservices) {
result.push({
data: watchedResources.ksservices.data,
loaded: watchedResources.ksservices.loaded,
loadError: watchedResources.ksservices.loadError,
kind: KnativeServiceModel.kind,
});
}
if (watchedResources.brokers) {
result.push({
data: watchedResources.brokers.data,
loaded: watchedResources.brokers.loaded,
loadError: watchedResources.brokers.loadError,
kind: EventingBrokerModel.kind,
});
}
if (watchedResources.kafkasinks) {
result.push({
data: watchedResources.kafkasinks.data,
loaded: watchedResources.kafkasinks.loaded,
loadError: watchedResources.kafkasinks.loadError,
kind: KafkaSinkModel.kind,
});
}

// Add dynamic channel resources
if (channelsLoaded && channels.length > 0) {
channels.forEach((model) => {
const ref = referenceForModel(model);
if (watchedResources[ref]) {
result.push({
data: watchedResources[ref].data,
loaded: watchedResources[ref].loaded,
loadError: watchedResources[ref].loadError,
kind: model.kind,
});
}
});
}

return result;
}, [watchedResources, channelsLoaded, channels]);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add fallback for data to handle initial/error states gracefully.

While the outer if (watchedResources.services) check exists, the inner .data property may be undefined before the watch completes or if there's an error state. Adding a fallback ensures ResourceDropdownField always receives an array:

data: watchedResources.services.data || []

This applies to all resource entries (lines 125, 133, 141, 149, 162). Without this, the downstream component might receive undefined during the loading phase, which could cause runtime issues depending on how ResourceDropdownField handles its resources prop.

🛡️ Proposed fix for defensive data handling
     if (watchedResources.services) {
       result.push({
-        data: watchedResources.services.data,
+        data: watchedResources.services.data || [],
         loaded: watchedResources.services.loaded,
         loadError: watchedResources.services.loadError,
         kind: 'Service',
       });
     }
     if (watchedResources.ksservices) {
       result.push({
-        data: watchedResources.ksservices.data,
+        data: watchedResources.ksservices.data || [],
         loaded: watchedResources.ksservices.loaded,
         loadError: watchedResources.ksservices.loadError,
         kind: KnativeServiceModel.kind,
       });
     }
     if (watchedResources.brokers) {
       result.push({
-        data: watchedResources.brokers.data,
+        data: watchedResources.brokers.data || [],
         loaded: watchedResources.brokers.loaded,
         loadError: watchedResources.brokers.loadError,
         kind: EventingBrokerModel.kind,
       });
     }
     if (watchedResources.kafkasinks) {
       result.push({
-        data: watchedResources.kafkasinks.data,
+        data: watchedResources.kafkasinks.data || [],
         loaded: watchedResources.kafkasinks.loaded,
         loadError: watchedResources.kafkasinks.loadError,
         kind: KafkaSinkModel.kind,
       });
     }

     // Add dynamic channel resources
     if (channelsLoaded && channels.length > 0) {
       channels.forEach((model) => {
         const ref = referenceForModel(model);
         if (watchedResources[ref]) {
           result.push({
-            data: watchedResources[ref].data,
+            data: watchedResources[ref].data || [],
             loaded: watchedResources[ref].loaded,
             loadError: watchedResources[ref].loadError,
             kind: model.kind,
           });
         }
       });
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/packages/knative-plugin/src/components/add/event-sources/form-fields/SinkResources.tsx`
around lines 119 - 172, The resourcesData useMemo collects watchedResources
entries but passes their .data directly, which can be undefined during initial
load/error; update each push in resourcesData (for services, ksservices,
brokers, kafkasinks and the dynamic channel branch inside the channels.forEach)
to use a safe fallback for the data property (e.g., data:
watchedResources.X.data || []) so ResourceDropdownField always receives an
array; keep the existing loaded and loadError fields and use referenceForModel
and model.kind unchanged.

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 3, 2026

@cajieh: This pull request references CONSOLE-5087 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 story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Summary by CodeRabbit

  • New Features

  • Resource dropdowns (secrets, projects, service accounts, PVCs) now dynamically fetch real-time data from your Kubernetes cluster, automatically reflecting resource changes without requiring page refresh.

  • Refactor

  • Improved resource loading performance and responsiveness across dropdown components by switching to dynamic data fetching.

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.

@cajieh cajieh force-pushed the refactor-console-shared-package-firehose-usek8swatchresource branch from c857a49 to 06f56ce Compare March 3, 2026 18:17
const spec: Record<string, WatchK8sResource> = {
services: {
isList: true,
kind: referenceForModel(ServiceModel),
Copy link
Contributor Author

@cajieh cajieh Mar 3, 2026

Choose a reason for hiding this comment

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

The deprecation warning for referenceForModel has been noted, but it is considered out of scope for this specific effort.

@openshift-ci-robot
Copy link
Contributor

@yapei: This PR has been marked as verified by @yapei.

Details

In response to this:

run regression testing about impacted pages, no regression issues found
Screenshot 2026-03-06 at 11 38 20 AM
Screenshot 2026-03-06 at 11 41 24 AM
Screenshot 2026-03-06 at 12 54 31 PM

/verified by @yapei

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.

@yapei
Copy link
Contributor

yapei commented Mar 6, 2026

/remove-label verified

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 6, 2026

@yapei: The label(s) /remove-label verified cannot be applied. These labels are supported: acknowledge-critical-fixes-only, platform/aws, platform/azure, platform/baremetal, platform/google, platform/libvirt, platform/openstack, ga, tide/merge-method-merge, tide/merge-method-rebase, tide/merge-method-squash, px-approved, docs-approved, qe-approved, ux-approved, no-qe, downstream-change-needed, rebase/manual, cluster-config-api-changed, run-integration-tests, approved, backport-risk-assessed, bugzilla/valid-bug, cherry-pick-approved, jira/valid-bug, ok-to-test, plugin-api-approved, plugin-api-changed, stability-fix-approved, staff-eng-approved. Is this label configured under labels -> additional_labels or labels -> restricted_labels in plugin.yaml?

Details

In response to this:

/remove-label verified

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.

@yapei
Copy link
Contributor

yapei commented Mar 6, 2026

  • The secret dropdown in Triggers and Secrets section on Create BuildConfig page automatically refresh and load newly created secret
buildconfig-triggers-secrets.mov
  • newly created ConfigMap and Secret are refreshed automatically on Create Helm Chart Repository page which is working as expected
helm-work.mov

/verified by @yapei

@jhadvig
Copy link
Member

jhadvig commented Mar 6, 2026

/retest

@cajieh
Copy link
Contributor Author

cajieh commented Mar 6, 2026

/test e2e-gcp-console

1 similar comment
@cajieh
Copy link
Contributor Author

cajieh commented Mar 7, 2026

/test e2e-gcp-console

@cajieh
Copy link
Contributor Author

cajieh commented Mar 7, 2026

/retest

4 similar comments
@cajieh
Copy link
Contributor Author

cajieh commented Mar 7, 2026

/retest

@cajieh
Copy link
Contributor Author

cajieh commented Mar 8, 2026

/retest

@cajieh
Copy link
Contributor Author

cajieh commented Mar 8, 2026

/retest

@logonoff
Copy link
Member

logonoff commented Mar 8, 2026

/retest

@cajieh
Copy link
Contributor Author

cajieh commented Mar 8, 2026

/test e2e-gcp-console

1 similar comment
@cajieh
Copy link
Contributor Author

cajieh commented Mar 8, 2026

/test e2e-gcp-console

@cajieh cajieh force-pushed the refactor-console-shared-package-firehose-usek8swatchresource branch from f778bf2 to 25ad7c3 Compare March 8, 2026 21:38
@openshift-ci-robot openshift-ci-robot removed the verified Signifies that the PR passed pre-merge verification criteria label Mar 8, 2026
@openshift-ci openshift-ci bot removed the lgtm Indicates that a PR is ready to be merged. label Mar 8, 2026
@cajieh
Copy link
Contributor Author

cajieh commented Mar 8, 2026

Adding the verified label since this was just a rebase.
/verified later @yapei

@openshift-ci-robot openshift-ci-robot added verified-later verified Signifies that the PR passed pre-merge verification criteria labels Mar 8, 2026
@openshift-ci-robot
Copy link
Contributor

@cajieh: This PR has been marked to be verified later by @yapei.

Details

In response to this:

Adding the verified label since this was just a rebase.
/verified later @yapei

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.

Copy link
Member

@jhadvig jhadvig left a comment

Choose a reason for hiding this comment

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

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Mar 9, 2026
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 9, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: cajieh, jhadvig

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

The pull request process is described 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

@cajieh
Copy link
Contributor Author

cajieh commented Mar 9, 2026

/test e2e-gcp-console

@cajieh
Copy link
Contributor Author

cajieh commented Mar 9, 2026

test e2e-gcp-console

@cajieh
Copy link
Contributor Author

cajieh commented Mar 9, 2026

/test e2e-gcp-console

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 10, 2026

@cajieh: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-gcp-console 25ad7c3 link true /test e2e-gcp-console

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.

@cajieh
Copy link
Contributor Author

cajieh commented Mar 10, 2026

/test e2e-gcp-console

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. component/core Related to console core functionality component/dev-console Related to dev-console component/helm Related to helm-plugin component/knative Related to knative-plugin component/shared Related to console-shared docs-approved Signifies that Docs has signed off on this PR jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. kind/i18n Indicates issue or PR relates to internationalization or has content that needs to be translated lgtm Indicates that a PR is ready to be merged. plugin-api-approved Indicates a PR with plugin API changes has been approved by an API reviewer px-approved Signifies that Product Support has signed off on this PR verified Signifies that the PR passed pre-merge verification criteria verified-later

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants