diff --git a/static/app/types/group.tsx b/static/app/types/group.tsx index bff087eb43d6..b57c184ca0df 100644 --- a/static/app/types/group.tsx +++ b/static/app/types/group.tsx @@ -673,6 +673,7 @@ export enum GroupActivityType { SEER_PR_READY_FOR_REVIEW = 'seer_pr_ready_for_review', SEER_ITERATION_STARTED = 'seer_iteration_started', SEER_ITERATION_COMPLETED = 'seer_iteration_completed', + SEER_STOPPED = 'seer_stopped', PULL_REQUEST_CLOSED = 'pull_request_closed', PULL_REQUEST_REOPENED = 'pull_request_reopened', PULL_REQUEST_MERGED = 'pull_request_merged', @@ -695,6 +696,7 @@ export const SEER_ACTIVITY_TYPES = new Set([ GroupActivityType.SEER_ITERATION_STARTED, GroupActivityType.SEER_ITERATION_COMPLETED, GroupActivityType.SEER_PR_READY_FOR_REVIEW, + GroupActivityType.SEER_STOPPED, GroupActivityType.TRIGGER_AUTOFIX, ]); @@ -1143,6 +1145,15 @@ interface GroupActivitySeerIterationCompleted extends GroupActivityBase { type: GroupActivityType.SEER_ITERATION_COMPLETED; } +interface GroupActivitySeerStopped extends GroupActivityBase { + data: { + reason?: string; + run_id?: number; + suggestion?: string; + }; + type: GroupActivityType.SEER_STOPPED; +} + interface GroupActivityUnlinkExternalIssue extends GroupActivityBase { data: {external_issue_key: string; provider: string}; type: GroupActivityType.UNLINK_EXTERNAL_ISSUE; @@ -1240,6 +1251,7 @@ export type GroupActivity = | GroupActivitySeerPrReadyForReview | GroupActivitySeerIterationStarted | GroupActivitySeerIterationCompleted + | GroupActivitySeerStopped | GroupActivityPullRequestClosed | GroupActivityPullRequestReopened | GroupActivityPullRequestMerged diff --git a/static/app/views/issueDetails/activitySection/activityLineItem/activityItem.tsx b/static/app/views/issueDetails/activitySection/activityLineItem/activityItem.tsx index 7c8f4d957d9a..524da9879036 100644 --- a/static/app/views/issueDetails/activitySection/activityLineItem/activityItem.tsx +++ b/static/app/views/issueDetails/activitySection/activityLineItem/activityItem.tsx @@ -627,6 +627,17 @@ function getActivityItemContent({ details, }; } + case GroupActivityType.SEER_STOPPED: + return { + title: t('Seer stopped early'), + details: ( + + {activity.data.reason} + {activity.data.suggestion && + ` ${t('Suggestion: %s', activity.data.suggestion)}`} + + ), + }; case GroupActivityType.TRIGGER_AUTOFIX: switch (activity.data.referrer) { case 'slack': diff --git a/static/app/views/issueDetails/activitySection/index.spec.tsx b/static/app/views/issueDetails/activitySection/index.spec.tsx index bbf88cb08f1c..54095ab4aaeb 100644 --- a/static/app/views/issueDetails/activitySection/index.spec.tsx +++ b/static/app/views/issueDetails/activitySection/index.spec.tsx @@ -2342,6 +2342,36 @@ describe('ActivitySection', () => { expect(screen.getByText('Autofix triggered from Slack')).toBeInTheDocument(); }); + it('renders a Seer early stop', async () => { + const seerGroup = GroupFixture({ + id: '1342', + activity: [ + { + type: GroupActivityType.SEER_STOPPED, + id: 'seer-stop-1', + dateCreated: '2020-01-01T00:00:00', + data: { + run_id: 123, + reason: 'The API key expired.', + suggestion: 'Rotate the key.', + }, + user: null, + }, + ], + project, + }); + + render( + + + + ); + expect(await screen.findByText('Seer stopped early')).toBeInTheDocument(); + expect( + screen.getByText('The API key expired. Suggestion: Rotate the key.') + ).toBeInTheDocument(); + }); + it('collapses Seer activity pairs across other activity', async () => { const seerGroup = GroupFixture({ id: '1343',