Skip to content

Commit 9522a99

Browse files
committed
feat(autofix): Autotrigger root cause if legacy autofix ran
If legacy autofix has run, we should at least auto trigger explorer autofix to run root cause.
1 parent d4c27af commit 9522a99

File tree

4 files changed

+101
-0
lines changed

4 files changed

+101
-0
lines changed
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import {GroupFixture} from 'sentry-fixture/group';
2+
3+
import {renderHook} from 'sentry-test/reactTestingLibrary';
4+
5+
import type {useExplorerAutofix} from 'sentry/components/events/autofix/useExplorerAutofix';
6+
import {useAutotriggerAutofix} from 'sentry/components/events/autofix/v3/useAutotriggerAutofix';
7+
8+
function makeAutofix(
9+
overrides: Partial<ReturnType<typeof useExplorerAutofix>> = {}
10+
): ReturnType<typeof useExplorerAutofix> {
11+
return {
12+
runState: null,
13+
startStep: jest.fn(),
14+
createPR: jest.fn(),
15+
reset: jest.fn(),
16+
triggerCodingAgentHandoff: jest.fn(),
17+
isLoading: false,
18+
isPolling: false,
19+
...overrides,
20+
} as ReturnType<typeof useExplorerAutofix>;
21+
}
22+
23+
describe('useAutotriggerAutofix', () => {
24+
it('starts root_cause when seerAutofixLastTriggered is set but seerExplorerAutofixLastTriggered is not', () => {
25+
const autofix = makeAutofix();
26+
const group = GroupFixture({
27+
seerAutofixLastTriggered: '2024-01-01T00:00:00Z',
28+
seerExplorerAutofixLastTriggered: null,
29+
});
30+
31+
renderHook(() => useAutotriggerAutofix({autofix, group}));
32+
33+
expect(autofix.startStep).toHaveBeenCalledWith('root_cause');
34+
expect(autofix.startStep).toHaveBeenCalledTimes(1);
35+
});
36+
37+
it('does not start root_cause when seerExplorerAutofixLastTriggered is set', () => {
38+
const autofix = makeAutofix();
39+
const group = GroupFixture({
40+
seerAutofixLastTriggered: '2024-01-01T00:00:00Z',
41+
seerExplorerAutofixLastTriggered: '2024-01-02T00:00:00Z',
42+
});
43+
44+
renderHook(() => useAutotriggerAutofix({autofix, group}));
45+
46+
expect(autofix.startStep).not.toHaveBeenCalled();
47+
});
48+
49+
it('does not trigger root_cause more than once on re-render', () => {
50+
const autofix = makeAutofix();
51+
const group = GroupFixture({
52+
seerAutofixLastTriggered: '2024-01-01T00:00:00Z',
53+
seerExplorerAutofixLastTriggered: null,
54+
});
55+
56+
const {rerender} = renderHook(() => useAutotriggerAutofix({autofix, group}));
57+
58+
rerender();
59+
rerender();
60+
61+
expect(autofix.startStep).toHaveBeenCalledTimes(1);
62+
});
63+
});
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import {useEffect, useRef} from 'react';
2+
3+
import {useExplorerAutofix} from 'sentry/components/events/autofix/useExplorerAutofix';
4+
import type {Group} from 'sentry/types/group';
5+
6+
interface UseAutotriggerAutofixOptions {
7+
autofix: ReturnType<typeof useExplorerAutofix>;
8+
group: Group;
9+
}
10+
11+
export function useAutotriggerAutofix({autofix, group}: UseAutotriggerAutofixOptions) {
12+
const alreadyTriggered = useRef(false);
13+
14+
// extract startStep first here so we can depend on it directly as `autofix` itself is unstable.
15+
const startStep = autofix.startStep;
16+
17+
useEffect(() => {
18+
if (alreadyTriggered.current) {
19+
return;
20+
}
21+
22+
// In order to have a smooth transition from legacy to explorer autofix, we want to automatically
23+
// trigger autofix when users view an issue that had legacy but not explorer autofix.
24+
const shouldAutotriggerAutofix =
25+
!!group.seerAutofixLastTriggered && !group.seerExplorerAutofixLastTriggered;
26+
27+
if (!shouldAutotriggerAutofix) {
28+
return;
29+
}
30+
31+
alreadyTriggered.current = true;
32+
startStep('root_cause');
33+
}, [group, startStep]);
34+
}

static/app/types/group.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1019,6 +1019,7 @@ export interface BaseGroup {
10191019
latestEventHasAttachments?: boolean;
10201020
owners?: SuggestedOwner[] | null;
10211021
seerAutofixLastTriggered?: string | null;
1022+
seerExplorerAutofixLastTriggered?: string | null;
10221023
seerFixabilityScore?: number | null;
10231024
sentryAppIssues?: PlatformExternalIssue[];
10241025
substatus?: GroupSubstatus | null;

static/app/views/issueDetails/streamline/sidebar/autofixSection.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
RootCausePreview,
3030
SolutionPreview,
3131
} from 'sentry/components/events/autofix/v3/autofixPreviews';
32+
import {useAutotriggerAutofix} from 'sentry/components/events/autofix/v3/useAutotriggerAutofix';
3233
import {useGroupSummaryData} from 'sentry/components/group/groupSummary';
3334
import {HookOrDefault} from 'sentry/components/hookOrDefault';
3435
import {Placeholder} from 'sentry/components/placeholder';
@@ -125,6 +126,8 @@ export function AutofixContent({aiConfig, group, project, event}: AutofixContent
125126
const autofix = useExplorerAutofix(group.id);
126127
const {data: setupCheck, isPending} = useSeerOnboardingCheck();
127128

129+
useAutotriggerAutofix({autofix, group});
130+
128131
if (
129132
// waiting on the onboarding checks to load
130133
isPending ||

0 commit comments

Comments
 (0)