Skip to content

Conversation

@bastilian
Copy link
Member

@bastilian bastilian commented Nov 6, 2025

This updates the "remediation section" on the CVE details page.

Before:

Screenshot 2025-11-10 at 15 54 46

After:

Screenshot 2025-11-10 at 15 53 59

How to test:

  1. Open the CVE details for example of CVE-2022-0847
  2. Verify the new remediation section appears correctly

Summary by Sourcery

Update the remediation section in CsawRuleBox by introducing a dedicated component for remediation plan availability and streamlining the reboot requirement display

Enhancements:

  • Add RemediationPlanSplitItem component to display remediation plan availability
  • Integrate the new remediation plan indicator into CsawRuleBox and remove the previous playbook-based UI
  • Simplify the reboot requirement section to a single icon-based yes/no label

Summary by Sourcery

Update the remediation section in CsawRuleBox by extracting remediation plan availability into its own component and simplifying the reboot requirement display

New Features:

  • Introduce a dedicated RemediationPlanSplitItem component to display remediation plan availability

Enhancements:

  • Replace the previous playbook-based remediation UI with the new remediation plan indicator in CsawRuleBox
  • Streamline the reboot requirement display to a single icon-based yes/no label

Tests:

  • Update CsawRuleBox tests to assert the new remediation plan status and simplified reboot requirement

@sourcery-ai
Copy link

sourcery-ai bot commented Nov 6, 2025

Reviewer's Guide

This PR refactors the remediation section in CsawRuleBox by extracting display logic into a new RemediationPlanSplitItem component, integrating it into the main component, simplifying the reboot requirement to an icon-based yes/no label, and updating tests to match the new UI structure.

Class diagram for CsawRuleBox and RemediationPlanSplitItem refactor

classDiagram
    class CsawRuleBox {
        +rules
        +synopsis
        +intl
        +setHeaderFilters
        +headerFilters
        +render()
    }
    class RemediationPlanSplitItem {
        +rule
        +render()
    }
    CsawRuleBox --> RemediationPlanSplitItem: uses
Loading

File-Level Changes

Change Details Files
Extract and integrate RemediationPlanSplitItem component for remediation plan
  • Created RemediationPlanSplitItem to render playbook availability with icons and tooltips
  • Imported and inserted RemediationPlanSplitItem into CsawRuleBox, replacing the previous playbook-based UI
  • Defined PropTypes and added data-testid attributes for the new component
src/Components/PresentationalComponents/CsawRuleBox/components/RemediationPlanSplitItem.js
src/Components/PresentationalComponents/CsawRuleBox/CsawRuleBox.js
Simplify reboot requirement section to use icon-based yes/no label
  • Replaced the complex reboot_required fragment with a single Text element showing Yes or No
  • Moved PowerOffIcon inside Text under data-testid="reboot-required"
src/Components/PresentationalComponents/CsawRuleBox/CsawRuleBox.js
Update unit tests to reflect UI refactoring
  • Replaced power-off-icon presence checks with assertions on 'reboot-required' text
  • Added assertions on remediation-plan text ('Available'/'Not available') under data-testid="remediation-plan"
src/Components/PresentationalComponents/CsawRuleBox/CsawRuleBox.test.js

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@bastilian bastilian force-pushed the RHINENG-19856 branch 4 times, most recently from 94f90a7 to 7a02634 Compare November 10, 2025 14:55
@bastilian bastilian marked this pull request as ready for review November 10, 2025 14:57
@bastilian bastilian requested a review from a team as a code owner November 10, 2025 14:57
Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey there - I've reviewed your changes - here's some feedback:

  • Use intl.formatMessage and message definitions for all new user-facing text (e.g. “Remediation plan”, “Available”, “Not available” and tooltip content) to maintain localization support.
  • Add aria-labels or accessible text to the icon elements in RemediationPlanSplitItem so screen readers can convey their purpose.
  • Consider extracting the reboot-required UI into its own small component to mirror RemediationPlanSplitItem and keep CsawRuleBox concerns separated.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Use intl.formatMessage and message definitions for all new user-facing text (e.g. “Remediation plan”, “Available”, “Not available” and tooltip content) to maintain localization support.
- Add aria-labels or accessible text to the icon elements in RemediationPlanSplitItem so screen readers can convey their purpose.
- Consider extracting the reboot-required UI into its own small component to mirror RemediationPlanSplitItem and keep CsawRuleBox concerns separated.

## Individual Comments

### Comment 1
<location> `src/Components/PresentationalComponents/CsawRuleBox/CsawRuleBox.js:141` </location>
<code_context>
                                                     <SplitItem>
                                                         <Label className="label pf-v5-u-mb-xs">
-                                                            {intl.formatMessage(messages.remediationLabel)}
+                                                            Remediation requires reboot
                                                         </Label>
                                                         <Split>
</code_context>

<issue_to_address>
**suggestion:** The label 'Remediation requires reboot' may be misleading if reboot is not always required.

If reboot is only needed in certain cases, update the label to indicate when a reboot is actually required.

Suggested implementation:

```javascript
                                                        <Label className="label pf-v5-u-mb-xs">
                                                            {rule.requires_reboot
                                                                ? 'Remediation requires reboot'
                                                                : 'Remediation does not require reboot'}
                                                        </Label>

```

If the `rule` object does not have a `requires_reboot` property, you will need to add or derive this property based on your application's logic.
</issue_to_address>

### Comment 2
<location> `src/Components/PresentationalComponents/CsawRuleBox/components/RemediationPlanSplitItem.js:22` </location>
<code_context>
+        </Label>
+        <Split>
+            <SplitItem data-testid="remediation-plan">
+                {rule?.playbook_count === 0
+                    ? (
+                        <>
</code_context>

<issue_to_address>
**issue (complexity):** Consider refactoring the repeated status rendering logic into a reusable StatusIndicator component with a lookup map.

You can collapse all of that nested JSX and duplicated fragments into a small, self-contained `StatusIndicator` component and a simple lookup map. For example:

```jsx
// StatusIndicator.js
import React from 'react';
import PropTypes from 'prop-types';
import { Tooltip, Icon } from '@patternfly/react-core';
import { CheckCircleIcon, TimesIcon } from '@patternfly/react-icons';

const STATUS_MAP = {
  available: {
    IconComponent: CheckCircleIcon,
    tooltip: 'You can create an Ansible playbook to remediate your systems.',
    label: 'Available',
    iconClass: 'pf-v5-u-mr-xs',
  },
  unavailable: {
    IconComponent: TimesIcon,
    tooltip: 'No Ansible playbooks are available, manual remediation is required for patching.',
    label: 'Not available',
    iconClass: 'pf-v5-u-mr-xs',
  },
};

const StatusIndicator = ({ status }) => {
  const { IconComponent, tooltip, label, iconClass } = STATUS_MAP[status];
  return (
    <>
      <Tooltip content={tooltip}>
        <Icon>
          <IconComponent className={iconClass} />
        </Icon>
      </Tooltip>
      {label}
    </>
  );
};

StatusIndicator.propTypes = {
  status: PropTypes.oneOf(['available', 'unavailable']).isRequired,
};

export default StatusIndicator;
```

Then simplify your main component to:

```jsx
import React from 'react';
import PropTypes from 'prop-types';
import { Split, SplitItem } from '@patternfly/react-core';
import Label from '../../Snippets/Label';
import StatusIndicator from './StatusIndicator';

const RemediationPlanSplitItem = ({ rule }) => {
  const status = rule?.playbook_count > 0 ? 'available' : 'unavailable';

  return (
    <SplitItem>
      <Label className="label pf-v5-u-mb-xs">Remediation plan</Label>
      <Split>
        <SplitItem data-testid="remediation-plan">
          <StatusIndicator status={status} />
        </SplitItem>
      </Split>
    </SplitItem>
  );
};

RemediationPlanSplitItem.propTypes = {
  rule: PropTypes.shape({
    playbook_count: PropTypes.number,
  }),
};

export default RemediationPlanSplitItem;
```

This removes the inline fragments, duplicate tooltips/icons, and makes it trivial to extend or tweak in the future.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

</Label>
<Split>
<SplitItem data-testid="remediation-plan">
{rule?.playbook_count === 0
Copy link

Choose a reason for hiding this comment

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

issue (complexity): Consider refactoring the repeated status rendering logic into a reusable StatusIndicator component with a lookup map.

You can collapse all of that nested JSX and duplicated fragments into a small, self-contained StatusIndicator component and a simple lookup map. For example:

// StatusIndicator.js
import React from 'react';
import PropTypes from 'prop-types';
import { Tooltip, Icon } from '@patternfly/react-core';
import { CheckCircleIcon, TimesIcon } from '@patternfly/react-icons';

const STATUS_MAP = {
  available: {
    IconComponent: CheckCircleIcon,
    tooltip: 'You can create an Ansible playbook to remediate your systems.',
    label: 'Available',
    iconClass: 'pf-v5-u-mr-xs',
  },
  unavailable: {
    IconComponent: TimesIcon,
    tooltip: 'No Ansible playbooks are available, manual remediation is required for patching.',
    label: 'Not available',
    iconClass: 'pf-v5-u-mr-xs',
  },
};

const StatusIndicator = ({ status }) => {
  const { IconComponent, tooltip, label, iconClass } = STATUS_MAP[status];
  return (
    <>
      <Tooltip content={tooltip}>
        <Icon>
          <IconComponent className={iconClass} />
        </Icon>
      </Tooltip>
      {label}
    </>
  );
};

StatusIndicator.propTypes = {
  status: PropTypes.oneOf(['available', 'unavailable']).isRequired,
};

export default StatusIndicator;

Then simplify your main component to:

import React from 'react';
import PropTypes from 'prop-types';
import { Split, SplitItem } from '@patternfly/react-core';
import Label from '../../Snippets/Label';
import StatusIndicator from './StatusIndicator';

const RemediationPlanSplitItem = ({ rule }) => {
  const status = rule?.playbook_count > 0 ? 'available' : 'unavailable';

  return (
    <SplitItem>
      <Label className="label pf-v5-u-mb-xs">Remediation plan</Label>
      <Split>
        <SplitItem data-testid="remediation-plan">
          <StatusIndicator status={status} />
        </SplitItem>
      </Split>
    </SplitItem>
  );
};

RemediationPlanSplitItem.propTypes = {
  rule: PropTypes.shape({
    playbook_count: PropTypes.number,
  }),
};

export default RemediationPlanSplitItem;

This removes the inline fragments, duplicate tooltips/icons, and makes it trivial to extend or tweak in the future.

@adonispuente
Copy link
Contributor

adonispuente commented Nov 10, 2025

In your PR the text is still the normal redhat font/color.
Screenshot 2025-11-10 at 10 04 20 AM

In the mocks its lighter/ the 'disabled' font :
Screenshot 2025-11-10 at 10 05 23 AM

To the CheckCircleIcon you may need to add status="success" in order to make it green.

@bastilian
Copy link
Member Author

@adonispuente I think the font weight difference may just be a rendering thing or just accidental, at least I think there is no reason that this would have a different weight.

The lack of colour when it's "Not available"/"No" is mentioned in the mocks as somewhat intentional only the "Availbal"/"Yes" states have "color":

Screenshot 2025-11-25 at 15 41 14

Copy link
Contributor

@LightOfHeaven1994 LightOfHeaven1994 left a comment

Choose a reason for hiding this comment

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

LGTM, good work!

@jira-linking
Copy link

jira-linking bot commented Dec 4, 2025

Referenced Jiras:
https://issues.redhat.com/browse/RHINENG-19856

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants