Skip to content

Commit bef2044

Browse files
authored
feat(seer): Seer Code Review Overview section (#111593)
Bring in the Seer Code-Review overview section behind the `seer-overview` feature flag. <img width="991" height="321" alt="SCR-20260325-pahy" src="https://github.com/user-attachments/assets/f0378e08-86ce-4a13-b1a1-4c57fb921350" /> And some stories to show the different states, mostly counts of things <img width="1664" height="10924" alt="1282-hayes-qd dev getsentry net_7999_stories_product_views_settings_seer_overview_codereviewoverviewsection_" src="https://github.com/user-attachments/assets/27bad47b-ba9c-4a08-b79a-22f36fdcff3e" />
1 parent 42d6756 commit bef2044

File tree

12 files changed

+552
-81
lines changed

12 files changed

+552
-81
lines changed

.github/CODEOWNERS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -866,6 +866,10 @@ tests/sentry/api/endpoints/test_organization_attribute_mappings.py @get
866866
/tests/sentry/scm/ @getsentry/scm
867867
## End of SCM
868868

869+
## SCM Frontend
870+
/static/app/components/repositories @getsentry/coding-workflows-sentry-frontend @getsentry/scm
871+
## End of SCM Frontend
872+
869873
# End of Coding Workflows
870874

871875
# Conduit

static/gsApp/views/seerAutomation/onboarding/hooks/useBulkUpdateRepositorySettings.tsx renamed to static/app/components/repositories/useBulkUpdateRepositorySettings.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import {getRepositoryWithSettingsQueryKey} from 'sentry/components/repositories/useRepositoryWithSettings';
12
import type {RepositoryWithSettings} from 'sentry/types/integrations';
23
import {
34
fetchMutation,
@@ -7,8 +8,6 @@ import {
78
} from 'sentry/utils/queryClient';
89
import {useOrganization} from 'sentry/utils/useOrganization';
910

10-
import {getRepositoryWithSettingsQueryKey} from 'getsentry/views/seerAutomation/onboarding/hooks/useRepositoryWithSettings';
11-
1211
export type RepositorySettings =
1312
| {
1413
enabledCodeReview: boolean;

static/gsApp/views/seerAutomation/onboarding/hooks/useRepositoryWithSettings.tsx renamed to static/app/components/repositories/useRepositoryWithSettings.tsx

File renamed without changes.
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
import {Fragment, type ComponentProps} from 'react';
2+
3+
import * as Storybook from 'sentry/stories';
4+
import {RepositoryStatus} from 'sentry/types/integrations';
5+
import type {RepositoryWithSettings} from 'sentry/types/integrations';
6+
import type {Organization} from 'sentry/types/organization';
7+
import {CodeReviewOverviewSection} from 'sentry/views/settings/seer/overview/codeReviewOverviewSection';
8+
9+
type Props = ComponentProps<typeof CodeReviewOverviewSection>;
10+
11+
function makeRepo(
12+
id: string,
13+
name: string,
14+
enabledCodeReview: boolean
15+
): RepositoryWithSettings {
16+
return {
17+
id,
18+
name,
19+
externalId: id,
20+
externalSlug: name,
21+
integrationId: '1',
22+
url: `https://github.com/${name}`,
23+
status: RepositoryStatus.ACTIVE,
24+
dateCreated: '',
25+
provider: {id: 'integrations:github', name: 'GitHub'},
26+
settings: {
27+
enabledCodeReview,
28+
codeReviewTriggers: ['on_ready_for_review', 'on_new_commit'],
29+
},
30+
};
31+
}
32+
33+
const ALL_REPOS: RepositoryWithSettings[] = [
34+
makeRepo('1', 'my-org/frontend', false),
35+
makeRepo('2', 'my-org/backend', false),
36+
makeRepo('3', 'my-org/infra', false),
37+
makeRepo('4', 'my-org/mobile', false),
38+
makeRepo('5', 'my-org/data-pipeline', false),
39+
];
40+
41+
const BASE_ORG = {
42+
slug: 'my-org',
43+
autoEnableCodeReview: true,
44+
defaultCodeReviewTriggers: ['on_ready_for_review', 'on_new_commit'],
45+
access: ['org:read', 'org:write', 'org:admin', 'org:integrations'],
46+
} as Organization;
47+
48+
const ORG = BASE_ORG;
49+
const ORG_AUTO_OFF: Organization = {...BASE_ORG, autoEnableCodeReview: false};
50+
const ORG_READONLY: Organization = {...BASE_ORG, access: ['org:read']};
51+
52+
function makeProps(
53+
seerRepos: RepositoryWithSettings[],
54+
reposWithCodeReview: RepositoryWithSettings[],
55+
orgOverride: Organization = ORG,
56+
isPending = false
57+
): Props {
58+
return {
59+
isPending,
60+
data: {queryKey: ['repositories'] as any, seerRepos, reposWithCodeReview},
61+
refetch: () => Promise.resolve({} as any),
62+
canWrite: true,
63+
organization: orgOverride,
64+
} as Props;
65+
}
66+
67+
export default Storybook.story('CodeReviewOverviewSection', story => {
68+
story('Overview', () => (
69+
<Fragment>
70+
<p>
71+
The <Storybook.JSXNode name="CodeReviewOverviewSection" /> is the code review
72+
panel in the Seer settings overview page. It lets users enable or disable code
73+
review across all existing repositories at once and configure the default triggers
74+
(on push vs. on ready-for-review).
75+
</p>
76+
<p>
77+
The component derives its display from two lists: <code>seerRepos</code> (all
78+
Seer-compatible repos) and <code>reposWithCodeReview</code> (the subset that have
79+
code review enabled). The ratio between them drives the counter text and the
80+
enable/disable bulk-action button state. The{' '}
81+
<strong>Enable Code Review by Default</strong> toggle reflects{' '}
82+
<code>organization.autoEnableCodeReview</code> and flips the direction of the bulk
83+
action (enable remaining vs. disable all).
84+
</p>
85+
</Fragment>
86+
));
87+
88+
story('Loading', () => <CodeReviewOverviewSection {...makeProps([], [], ORG, true)} />);
89+
90+
story('0 repos', () => <CodeReviewOverviewSection {...makeProps([], [])} />);
91+
92+
story('1 repo / 0 enabled', () => (
93+
<CodeReviewOverviewSection {...makeProps(ALL_REPOS.slice(0, 1), [])} />
94+
));
95+
96+
story('1 repo / 1 enabled (all)', () => (
97+
<CodeReviewOverviewSection
98+
{...makeProps(ALL_REPOS.slice(0, 1), ALL_REPOS.slice(0, 1))}
99+
/>
100+
));
101+
102+
story('N repos / 0 enabled', () => (
103+
<CodeReviewOverviewSection {...makeProps(ALL_REPOS, [])} />
104+
));
105+
106+
story('N repos / 1 enabled', () => (
107+
<CodeReviewOverviewSection {...makeProps(ALL_REPOS, ALL_REPOS.slice(0, 1))} />
108+
));
109+
110+
story('N repos / many enabled (not all)', () => (
111+
<CodeReviewOverviewSection {...makeProps(ALL_REPOS, ALL_REPOS.slice(0, 3))} />
112+
));
113+
114+
story('N repos / all enabled', () => (
115+
<CodeReviewOverviewSection {...makeProps(ALL_REPOS, ALL_REPOS)} />
116+
));
117+
118+
story('Auto-enable off / 0 enabled', () => (
119+
<CodeReviewOverviewSection {...makeProps(ALL_REPOS, [], ORG_AUTO_OFF)} />
120+
));
121+
122+
story('Auto-enable off / some enabled', () => (
123+
<CodeReviewOverviewSection
124+
{...makeProps(ALL_REPOS, ALL_REPOS.slice(0, 2), ORG_AUTO_OFF)}
125+
/>
126+
));
127+
128+
story('Auto-enable off / all enabled', () => (
129+
<CodeReviewOverviewSection {...makeProps(ALL_REPOS, ALL_REPOS, ORG_AUTO_OFF)} />
130+
));
131+
132+
story('Read-only (no org:write)', () => (
133+
<CodeReviewOverviewSection
134+
{...makeProps(ALL_REPOS, ALL_REPOS.slice(0, 2), ORG_READONLY)}
135+
/>
136+
));
137+
});

0 commit comments

Comments
 (0)