Skip to content

Comments

CONSOLE-5055: AsyncComponent type improvements#16002

Merged
openshift-merge-bot[bot] merged 2 commits intoopenshift:mainfrom
logonoff:CONSOLE-5055-async
Feb 13, 2026
Merged

CONSOLE-5055: AsyncComponent type improvements#16002
openshift-merge-bot[bot] merged 2 commits intoopenshift:mainfrom
logonoff:CONSOLE-5055-async

Conversation

@logonoff
Copy link
Member

@logonoff logonoff commented Feb 5, 2026

  • Updated AsyncComponent to be a functional component that uses React.lazy
  • Retry duration is now capped to 30s instead of exponentially increasing (previously we would backoff for over a month)
    • To be honest we probably don't need to have any retry behaivour here. But I kept it incase just in case
  • Components consuming AsyncComponent now have proper type checking based on the props of the loader

Summary by CodeRabbit

  • Bug Fixes

    • Improved reliability of component loading with automatic retry and exponential backoff for better error recovery.
  • New Features

    • Added localization support for edit mode in YAML creation workflows.
  • Tests

    • Enhanced test coverage for async component error handling and retry behavior with backoff timing verification.

@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 5, 2026
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Feb 5, 2026

@logonoff: This pull request references CONSOLE-5055 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:

  • Updated AsyncComponent to be a functional component that uses React.lazy
  • Retry duration is now capped to 30s instead of exponentially increasing (previously we would backoff for over a month)
  • Component consuming AsyncComponent now have proper type checking based on the props of the loader

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 requested review from cajieh and rawagner February 5, 2026 19:57
@openshift-ci openshift-ci bot added component/core Related to console core functionality component/dashboard Related to dashboard approved Indicates a PR has been approved by an approver from all required OWNERS files. component/dev-console Related to dev-console component/olm Related to OLM component/shared Related to console-shared kind/i18n Indicates issue or PR relates to internationalization or has content that needs to be translated labels Feb 5, 2026
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Feb 5, 2026

@logonoff: This pull request references CONSOLE-5055 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:

  • Updated AsyncComponent to be a functional component that uses React.lazy
  • Retry duration is now capped to 30s instead of exponentially increasing (previously we would backoff for over a month)
  • To be honest we probably don't need to have any retry behaivour here. But I kept it incase just in case
  • Component consuming AsyncComponent now have proper type checking based on the props of the loader

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-robot
Copy link
Contributor

openshift-ci-robot commented Feb 5, 2026

@logonoff: This pull request references CONSOLE-5055 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:

  • Updated AsyncComponent to be a functional component that uses React.lazy
  • Retry duration is now capped to 30s instead of exponentially increasing (previously we would backoff for over a month)
  • To be honest we probably don't need to have any retry behaivour here. But I kept it incase just in case
  • Components consuming AsyncComponent now have proper type checking based on the props of the loader

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-robot
Copy link
Contributor

openshift-ci-robot commented Feb 5, 2026

@logonoff: This pull request references CONSOLE-5055 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:

  • Updated AsyncComponent to be a functional component that uses React.lazy
  • Retry duration is now capped to 30s instead of exponentially increasing (previously we would backoff for over a month)
  • To be honest we probably don't need to have any retry behaivour here. But I kept it incase just in case
  • Components consuming AsyncComponent now have proper type checking based on the props of the loader

Summary by CodeRabbit

  • Bug Fixes

  • Improved reliability of component loading with automatic retry and exponential backoff for better error recovery.

  • New Features

  • Added localization support for edit mode in YAML creation workflows.

  • Tests

  • Enhanced test coverage for async component error handling and retry behavior with backoff timing verification.

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.

@logonoff
Copy link
Member Author

logonoff commented Feb 5, 2026

/label px-approved
/label docs-approved

@openshift-ci openshift-ci bot added px-approved Signifies that Product Support has signed off on this PR docs-approved Signifies that Docs has signed off on this PR labels Feb 5, 2026
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 5, 2026

📝 Walkthrough

Walkthrough

This pull request refactors the AsyncComponent lazy-loading system from class-based to functional component using hooks and Suspense, introducing exponential backoff retry logic with a configurable retry cap. Type signatures across lazy loaders are updated to expect ComponentType instead of raw props, with corresponding type adjustments in dependent components. Error boundaries are selectively removed from certain lazy-loaded resources. Props are refined to make create and clearFileUpload optional in EditYAMLProps. Test coverage expands for async error and retry scenarios. Data-test attributes are added to buttons for improved testing visibility. Minor type imports are consolidated and React type references are simplified throughout.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title directly reflects the main change: converting AsyncComponent to use better type checking and functional approach with retry improvements.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

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

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: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/public/components/import-yaml.tsx (1)

16-25: ⚠️ Potential issue | 🟡 Minor

Fix type safety: initialResource={undefined} violates the required prop definition.

ResourceYAMLEditorProps defines initialResource: K8sResourceKind as required (not optional). Passing undefined conflicts with this contract. In create-yaml.tsx, the pattern correctly uses an empty object {} instead:

const initialResource = useMemo(() => {
  if (!kindObj) {
    return {};  // Always pass an object
  }
  // ...
}, []);

Either mark initialResource as optional in ResourceYAMLEditorProps if undefined should be supported, or pass {} here to align with the type definition and existing usage patterns.

🧹 Nitpick comments (3)
frontend/packages/console-shared/src/components/formik-fields/field-types.ts (1)

166-173: Minor inconsistency between RadioButtonFieldProps and RadioGroupFieldProps value types.

RadioButtonFieldProps.value accepts string | number (line 167), while RadioGroupOption.value is constrained to string only (line 185). If a RadioButtonField is used standalone with a numeric value but the same field is later wrapped in a RadioGroupField, the types won't align.

Consider whether both should consistently use string or string | number. If numeric values are genuinely needed for radio buttons, RadioGroupOption.value should also support number.

frontend/public/components/utils/async.tsx (1)

18-22: sameLoader comparison is fragile — document limitations and consider alternatives.

Comparing functions via name and toString() can produce false positives (different inline functions with identical bodies) or false negatives (minified code where function bodies differ). The current approach handles inline loaders better than referential equality alone, but:

  1. Arrow functions typically have empty name properties
  2. Minifiers may alter function bodies unpredictably

The comment acknowledges this ("not the best solution"), but consider adding a more robust equality check or documenting that consumers should define loaders outside render cycles when possible.

frontend/public/components/utils/__tests__/async.spec.tsx (1)

98-109: Minor: Missing await after advanceTimersByTime may cause timing issues.

For consistency with other tests in this file, consider wrapping the timer advancement in act or awaiting promise resolution:

await act(async () => {
  jest.advanceTimersByTime(1000);
});

This ensures all pending promise resolutions are flushed before the assertion on line 107.

♻️ Suggested improvement
   await waitFor(() => expect(loader).toHaveBeenCalledTimes(1));

-  jest.advanceTimersByTime(1000);
+  await act(async () => {
+    jest.advanceTimersByTime(1000);
+  });

   expect(loader).toHaveBeenCalledTimes(1);

@logonoff logonoff force-pushed the CONSOLE-5055-async branch 4 times, most recently from be35005 to 9cf3f71 Compare February 6, 2026 17:32
@TheRealJon
Copy link
Member

/woof

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 10, 2026

@TheRealJon: dog image

Details

In response to this:

/woof

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.

Copy link
Member

@TheRealJon TheRealJon left a comment

Choose a reason for hiding this comment

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

Just a couple of questions about the kind props being removed.

path="/k8s/ns/:ns/secrets/~new/:type"
element={
<AsyncComponent
kind="Secret"
Copy link
Member

Choose a reason for hiding this comment

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

Is this safe?

Copy link
Member Author

Choose a reason for hiding this comment

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

m.CreateSecret takes no props

export const CreateSecret = () => {
  const params = useParams();
  const formType = params.type as SecretFormType;
  return (
    <SecretFormWrapper
      fixed={{ metadata: { namespace: params.ns } }}
      formType={formType}
      isCreate={true}
    />
  );
};

loader={() => import('./droppable-edit-yaml').then((c) => c.DroppableEditYAML)}
initialResource={initialResource}
create={isCreate}
kind={kindObj.kind}
Copy link
Member

Choose a reason for hiding this comment

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

Is this safe?

Copy link
Member Author

Choose a reason for hiding this comment

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

kind is not a prop in either DroppableEditYAML nor EditYAML. props.kind is not accessed in either component either

Comment on lines -89 to +90
forwardRef={editorRef}
ref={editorRef}
Copy link
Member Author

Choose a reason for hiding this comment

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

CodeEditor never accepted forwardRef, the way to pass a ref to a component is via the ref prop

Comment on lines -165 to +167
<ErrorBoundaryPage>
<AsyncComponent
loader={createResourceExtension.properties.component}
namespace={params.ns}
/>
</ErrorBoundaryPage>
<AsyncComponent
loader={createResourceExtension.properties.component}
namespace={params.ns}
/>
Copy link
Member Author

Choose a reason for hiding this comment

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

AsyncComponent now wraps an ErrorBoundary

path="/k8s/ns/:ns/secrets/~new/:type"
element={
<AsyncComponent
kind="Secret"
Copy link
Member Author

Choose a reason for hiding this comment

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

m.CreateSecret takes no props

export const CreateSecret = () => {
  const params = useParams();
  const formType = params.type as SecretFormType;
  return (
    <SecretFormWrapper
      fixed={{ metadata: { namespace: params.ns } }}
      formType={formType}
      isCreate={true}
    />
  );
};

path="/k8s/ns/:ns/configmaps/~new/form"
element={
<AsyncComponent
kind="ConfigMap"
Copy link
Member Author

Choose a reason for hiding this comment

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

ConfigMapPage accepts no props

export const ConfigMapPage: FC = () => {
  const { t } = useTranslation();
  const { ns: namespace, name } = useParams();
  const isCreateFlow: boolean = !name;

  const [watchedConf

loader={() =>
import('./RBAC' /* webpackChunkName: "rbac" */).then((m) => m.CreateRoleBinding)
}
kind="RoleBinding"
Copy link
Member Author

Choose a reason for hiding this comment

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

CreateRoleBinding accepts no props

export const CreateRoleBinding: FC = () => {
  const params = useParams();
  const location = useLocation();
  const searchParams = new URLSearchParams(location.search);
  const roleKind = searchParams.get('rolekind');
  const roleName = searchParams.get('rolename');
  const subjectName = searchParams.get('subjectName'

path="/k8s/ns/:ns/persistentvolumeclaims/~new/form"
element={
<AsyncComponent
kind="PersistentVolumeClaim"
Copy link
Member Author

Choose a reason for hiding this comment

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

accepts no props

export const CreatePVC = () => {
  const params = useParams();
  const namespace = params.ns || 'default';
  return <CreatePVC

path="/k8s/ns/:ns/:resourceRef/form"
element={
<AsyncComponent
kind="PodDisruptionBudgets"
Copy link
Member Author

Choose a reason for hiding this comment

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

accepts no props

export const PDBFormPage: FC = () => {
  const { t } = useTranslation();
  const params = us

loader={() => import('./droppable-edit-yaml').then((c) => c.DroppableEditYAML)}
initialResource={initialResource}
create={isCreate}
kind={kindObj.kind}
Copy link
Member Author

Choose a reason for hiding this comment

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

kind is not a prop in either DroppableEditYAML nor EditYAML. props.kind is not accessed in either component either

Copy link
Member

@TheRealJon TheRealJon 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 Feb 10, 2026
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 10, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: logonoff, TheRealJon

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

@logonoff
Copy link
Member Author

/assign @yapei

@yapei
Copy link
Contributor

yapei commented Feb 12, 2026

performed some regression testing on following

  • Deployment & Pod Environment handling, Add/Remove/Update/Reorder environment variables
  • Import YAML page, drag and drop files
  • Enable console-demo-plugin and check Sample Error Boundary Page
  • Resource creation form, including workloads creation form and operand creation form
  • Pod debug terminal
  • Secret, ConfigMap, RoleBinding, ClusterRoleBinding,PDB and PVC creation form
  • Attach Storage form

No obvious regression issues found
/verified by @yapei and CI

@openshift-ci-robot openshift-ci-robot added the verified Signifies that the PR passed pre-merge verification criteria label Feb 12, 2026
@openshift-ci-robot
Copy link
Contributor

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

Details

In response to this:

performed some regression testing on following

  • Deployment & Pod Environment handling, Add/Remove/Update/Reorder environment variables
  • Import YAML page, drag and drop files
  • Enable console-demo-plugin and check Sample Error Boundary Page
  • Resource creation form, including workloads creation form and operand creation form
  • Pod debug terminal
  • Secret, ConfigMap, RoleBinding, ClusterRoleBinding,PDB and PVC creation form
  • Attach Storage form

No obvious regression issues found
/verified by @yapei and CI

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
Copy link
Contributor

openshift-ci bot commented Feb 13, 2026

@logonoff: all tests passed!

Full PR test history. Your PR dashboard.

Details

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

@openshift-merge-bot openshift-merge-bot bot merged commit 51671f2 into openshift:main Feb 13, 2026
8 checks passed
@logonoff logonoff deleted the CONSOLE-5055-async branch February 13, 2026 06:48
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/dashboard Related to dashboard component/dev-console Related to dev-console component/olm Related to OLM 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. px-approved Signifies that Product Support has signed off on this PR verified Signifies that the PR passed pre-merge verification criteria

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants