Skip to content

Commit 183a444

Browse files
ref(autofix): Remove feature flag gating and add retry to RootCauseCard
Retry buttons are now always visible on all completed step cards including Root Cause. The feature flag check has been removed since this is intended as a standard feature, not gated functionality. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent d2fea10 commit 183a444

File tree

2 files changed

+33
-84
lines changed

2 files changed

+33
-84
lines changed

static/app/components/events/autofix/v3/autofixCards.spec.tsx

Lines changed: 19 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import {OrganizationFixture} from 'sentry-fixture/organization';
2-
31
import {render, screen, userEvent} from 'sentry-test/reactTestingLibrary';
42

53
import {CodingAgentProvider} from 'sentry/components/events/autofix/types';
@@ -629,7 +627,7 @@ describe('Retry button', () => {
629627
isPolling: false,
630628
};
631629

632-
it('does not show retry button on SolutionCard without feature flag', () => {
630+
it('shows retry button on completed SolutionCard', () => {
633631
const artifact = makeSolutionArtifact({
634632
one_line_summary: 'Fix the bug',
635633
steps: [{title: 'Step 1', description: 'Do something'}],
@@ -642,28 +640,25 @@ describe('Retry button', () => {
642640
/>
643641
);
644642

645-
expect(screen.queryByRole('button', {name: 'Retry'})).not.toBeInTheDocument();
643+
expect(screen.getByRole('button', {name: 'Retry'})).toBeInTheDocument();
646644
});
647645

648-
it('shows retry button on SolutionCard with feature flag', () => {
649-
const artifact = makeSolutionArtifact({
650-
one_line_summary: 'Fix the bug',
651-
steps: [{title: 'Step 1', description: 'Do something'}],
646+
it('calls startStep with root_cause, runId, and blockIndex on RootCauseCard retry click', async () => {
647+
const startStep = jest.fn();
648+
const artifact = makeRootCauseArtifact({
649+
one_line_description: 'Null pointer',
650+
five_whys: ['why1'],
652651
});
653652

654653
render(
655-
<SolutionCard
656-
autofix={autofixWithRun}
657-
section={makeSection('solution', 'completed', [artifact])}
658-
/>,
659-
{
660-
organization: OrganizationFixture({
661-
features: ['autofix-retry-from-step'],
662-
}),
663-
}
654+
<RootCauseCard
655+
autofix={{...autofixWithRun, startStep}}
656+
section={makeSection('root_cause', 'completed', [artifact], 0)}
657+
/>
664658
);
665659

666-
expect(screen.getByRole('button', {name: 'Retry'})).toBeInTheDocument();
660+
await userEvent.click(screen.getByRole('button', {name: 'Retry'}));
661+
expect(startStep).toHaveBeenCalledWith('root_cause', 42, undefined, 0);
667662
});
668663

669664
it('calls startStep with solution, runId, and blockIndex on SolutionCard retry click', async () => {
@@ -677,12 +672,7 @@ describe('Retry button', () => {
677672
<SolutionCard
678673
autofix={{...autofixWithRun, startStep}}
679674
section={makeSection('solution', 'completed', [artifact], 3)}
680-
/>,
681-
{
682-
organization: OrganizationFixture({
683-
features: ['autofix-retry-from-step'],
684-
}),
685-
}
675+
/>
686676
);
687677

688678
await userEvent.click(screen.getByRole('button', {name: 'Retry'}));
@@ -701,12 +691,7 @@ describe('Retry button', () => {
701691
[[makePatch('org/repo', 'src/app.py')]],
702692
5
703693
)}
704-
/>,
705-
{
706-
organization: OrganizationFixture({
707-
features: ['autofix-retry-from-step'],
708-
}),
709-
}
694+
/>
710695
);
711696

712697
await userEvent.click(screen.getByRole('button', {name: 'Retry'}));
@@ -720,12 +705,7 @@ describe('Retry button', () => {
720705
<PullRequestsCard
721706
autofix={{...autofixWithRun, createPR}}
722707
section={makeSection('pull_request', 'completed', [[makePR()]])}
723-
/>,
724-
{
725-
organization: OrganizationFixture({
726-
features: ['autofix-retry-from-step'],
727-
}),
728-
}
708+
/>
729709
);
730710

731711
await userEvent.click(screen.getByRole('button', {name: 'Retry'}));
@@ -742,12 +722,7 @@ describe('Retry button', () => {
742722
<SolutionCard
743723
autofix={autofixWithRun}
744724
section={makeSection('solution', 'processing', [artifact])}
745-
/>,
746-
{
747-
organization: OrganizationFixture({
748-
features: ['autofix-retry-from-step'],
749-
}),
750-
}
725+
/>
751726
);
752727

753728
expect(screen.queryByRole('button', {name: 'Retry'})).not.toBeInTheDocument();
@@ -760,12 +735,7 @@ describe('Retry button', () => {
760735
<SolutionCard
761736
autofix={autofixWithRun}
762737
section={makeSection('solution', 'completed', [artifact])}
763-
/>,
764-
{
765-
organization: OrganizationFixture({
766-
features: ['autofix-retry-from-step'],
767-
}),
768-
}
738+
/>
769739
);
770740

771741
expect(screen.queryByRole('button', {name: 'Retry'})).not.toBeInTheDocument();
@@ -781,35 +751,9 @@ describe('Retry button', () => {
781751
<SolutionCard
782752
autofix={{...autofixWithRun, isPolling: true}}
783753
section={makeSection('solution', 'completed', [artifact])}
784-
/>,
785-
{
786-
organization: OrganizationFixture({
787-
features: ['autofix-retry-from-step'],
788-
}),
789-
}
754+
/>
790755
);
791756

792757
expect(screen.getByRole('button', {name: 'Retry'})).toBeDisabled();
793758
});
794-
795-
it('does not show retry button on RootCauseCard even with feature flag', () => {
796-
const artifact = makeRootCauseArtifact({
797-
one_line_description: 'Null pointer',
798-
five_whys: ['why1'],
799-
});
800-
801-
render(
802-
<RootCauseCard
803-
autofix={autofixWithRun}
804-
section={makeSection('root_cause', 'completed', [artifact])}
805-
/>,
806-
{
807-
organization: OrganizationFixture({
808-
features: ['autofix-retry-from-step'],
809-
}),
810-
}
811-
);
812-
813-
expect(screen.queryByRole('button', {name: 'Retry'})).not.toBeInTheDocument();
814-
});
815759
});

static/app/components/events/autofix/v3/autofixCards.tsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ import {IconOpen} from 'sentry/icons/iconOpen';
3434
import {IconPullRequest} from 'sentry/icons/iconPullRequest';
3535
import {t, tct, tn} from 'sentry/locale';
3636
import {defined} from 'sentry/utils';
37-
import {useOrganization} from 'sentry/utils/useOrganization';
3837
import {FileDiffViewer} from 'sentry/views/seerExplorer/fileDiffViewer';
3938

4039
interface AutofixCardProps {
@@ -48,10 +47,22 @@ export function RootCauseCard({autofix, section}: AutofixCardProps) {
4847
return isRootCauseArtifact(sectionArtifact) ? sectionArtifact : null;
4948
}, [section]);
5049

51-
const {startStep} = autofix;
50+
const {startStep, runState, isPolling} = autofix;
51+
const runId = runState?.run_id;
5252

5353
return (
54-
<ArtifactCard icon={<IconBug />} title={t('Root Cause')}>
54+
<ArtifactCard
55+
icon={<IconBug />}
56+
title={t('Root Cause')}
57+
trailingItems={
58+
section.status === 'completed' && artifact?.data ? (
59+
<RetryButton
60+
onClick={() => startStep('root_cause', runId, undefined, section.blockIndex)}
61+
disabled={isPolling}
62+
/>
63+
) : undefined
64+
}
65+
>
5566
{section.status === 'processing' ? (
5667
<LoadingDetails
5768
messages={section.messages}
@@ -405,12 +416,6 @@ interface RetryButtonProps {
405416
}
406417

407418
function RetryButton({onClick, disabled}: RetryButtonProps) {
408-
const organization = useOrganization();
409-
410-
if (!organization.features.includes('autofix-retry-from-step')) {
411-
return null;
412-
}
413-
414419
return (
415420
<Button
416421
size="xs"

0 commit comments

Comments
 (0)