Skip to content

Commit ef55497

Browse files
feat(codecov): Add TA onboarding expandable dropdowns (#96989)
Closes https://linear.app/getsentry/issue/CCMRG-1441/steps-expand-dropdown - Adds the dropdown component - Adds four instances of the dropdown for the TA onboarding steps - Fixes a bug with steps responsiveness that was introduced by the combination of the Steps 4/5/6 and Responsiveness PRs that have gone in recently Testing reminder: needs `/new` at the end of the url to show onboarding steps (https://sentry-4lwy6t2cv.sentry.dev/codecov/tests/new)
1 parent 4df639d commit ef55497

17 files changed

+391
-267
lines changed

static/app/views/prevent/tests/onboarding.tsx

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {useCallback, useState} from 'react';
22
import {useSearchParams} from 'react-router-dom';
33
import styled from '@emotion/styled';
44

5+
import {Flex} from 'sentry/components/core/layout';
56
import {Link} from 'sentry/components/core/link';
67
import RadioGroup from 'sentry/components/forms/controls/radioGroup';
78
import {t, tct} from 'sentry/locale';
@@ -63,7 +64,7 @@ export default function TestsOnboardingPage() {
6364
['cli', t("Use Sentry Prevent's CLI to upload testing reports")],
6465
]}
6566
/>
66-
<StepsContainer>
67+
<Flex direction="column" gap="2xl" maxWidth="1000px" padding="2xl 0 0 3xl">
6768
<OutputCoverageFileStep step="1" />
6869
{/* TODO coming soon: we will conditionally render this based on CLI vs GHAction and OIDC vs Token for CLI */}
6970
<ChooseUploadPermissionStep
@@ -87,7 +88,7 @@ export default function TestsOnboardingPage() {
8788
),
8889
})}
8990
</div>
90-
</StepsContainer>
91+
</Flex>
9192
</OnboardingContent>
9293
</OnboardingContainer>
9394
</LayoutGap>
@@ -131,9 +132,3 @@ const SelectOptionHeader = styled('h5')`
131132
color: ${p => p.theme.tokens.content.primary};
132133
margin-top: ${p => p.theme.space['2xl']};
133134
`;
134-
135-
const StepsContainer = styled('div')`
136-
padding-top: ${p => p.theme.space['2xl']};
137-
padding-left: ${p => p.theme.space['3xl']};
138-
max-width: 1000px;
139-
`;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import testAnalyticsGHAWorkflowExample from 'sentry-images/features/test-analytics-gha-workflow-ex.png';
2+
3+
import {Text} from 'sentry/components/core/text';
4+
import {t, tct} from 'sentry/locale';
5+
import {OnboardingStep} from 'sentry/views/prevent/tests/onboardingSteps/onboardingStep';
6+
7+
export function GHAWorkflowExpandable() {
8+
return (
9+
<OnboardingStep.ExpandableDropdown
10+
triggerContent={
11+
<div>
12+
{tct(
13+
'A GitHub Actions workflow for a repository using [pytest] might look something like this:',
14+
{
15+
pytest: <Text variant="promotion">{t('pytest')}</Text>,
16+
}
17+
)}
18+
</div>
19+
}
20+
>
21+
<img src={testAnalyticsGHAWorkflowExample} />
22+
</OnboardingStep.ExpandableDropdown>
23+
);
24+
}

static/app/views/prevent/tests/onboardingSteps/addScriptToYamlStep.tsx

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ import styled from '@emotion/styled';
22

33
import {CodeSnippet} from 'sentry/components/codeSnippet';
44
import {t, tct} from 'sentry/locale';
5-
import {space} from 'sentry/styles/space';
65
import {InlineCodeSnippet} from 'sentry/views/prevent/styles';
6+
import {GHAWorkflowExpandable} from 'sentry/views/prevent/tests/onboardingSteps/GHAWorkflowExpandable';
77
import {OnboardingStep} from 'sentry/views/prevent/tests/onboardingSteps/onboardingStep';
88

99
interface AddScriptToYamlStepProps {
@@ -28,29 +28,31 @@ export function AddScriptToYamlStep({step}: AddScriptToYamlStepProps) {
2828

2929
return (
3030
<OnboardingStep.Container>
31-
<OnboardingStep.Header>{headerText}</OnboardingStep.Header>
32-
<OnboardingStep.Content>
33-
<AddScriptsParagraph>
34-
{t('In your CI YAML file, add below scripts to the end of your test run.')}
35-
</AddScriptsParagraph>
36-
<CodeSnippet dark language="yaml">
37-
{SNIPPET}
38-
</CodeSnippet>
39-
<SnippetFollowupParagraph>
40-
{t(
41-
'This action will download the Sentry Prevent CLI, and upload the junit.xml file generated in the previous step to Sentry.'
42-
)}
43-
</SnippetFollowupParagraph>
44-
{/* TODO: add dropdown expansion */}
45-
</OnboardingStep.Content>
31+
<OnboardingStep.Body>
32+
<OnboardingStep.Header>{headerText}</OnboardingStep.Header>
33+
<OnboardingStep.Content>
34+
<AddScriptsParagraph>
35+
{t('In your CI YAML file, add below scripts to the end of your test run.')}
36+
</AddScriptsParagraph>
37+
<CodeSnippet dark language="yaml">
38+
{SNIPPET}
39+
</CodeSnippet>
40+
<SnippetFollowupParagraph>
41+
{t(
42+
'This action will download the Sentry Prevent CLI, and upload the junit.xml file generated in the previous step to Sentry.'
43+
)}
44+
</SnippetFollowupParagraph>
45+
</OnboardingStep.Content>
46+
</OnboardingStep.Body>
47+
<GHAWorkflowExpandable />
4648
</OnboardingStep.Container>
4749
);
4850
}
4951

5052
const AddScriptsParagraph = styled('div')`
51-
margin-bottom: ${space(1)};
53+
margin-bottom: ${p => p.theme.space.md};
5254
`;
5355

5456
const SnippetFollowupParagraph = styled('div')`
55-
margin-top: ${space(1.5)};
57+
margin-top: ${p => p.theme.space.lg};
5658
`;
Lines changed: 65 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
import {Fragment, useState} from 'react';
2+
import {useTheme} from '@emotion/react';
3+
4+
import testAnalyticsRepoSecretDark from 'sentry-images/features/test-analytics-repo-secret-dark.png';
5+
import testAnalyticsRepoSecretLight from 'sentry-images/features/test-analytics-repo-secret-light.png';
26

37
import {CodeSnippet} from 'sentry/components/codeSnippet';
48
import {Alert} from 'sentry/components/core/alert';
@@ -22,6 +26,10 @@ export function AddUploadTokenStep({step}: AddUploadTokenStepProps) {
2226
// this value is only used when showing token details
2327
const [showFullToken, setShowFullToken] = useState(true);
2428
const [showWarning, setShowWarning] = useState(true);
29+
30+
const theme = useTheme();
31+
const isDarkMode = theme.type === 'dark';
32+
2533
const headerText = tct(`Step [step]: Add token as [repositorySecret]`, {
2634
step,
2735
// TODO: replace with actual link
@@ -46,59 +54,70 @@ export function AddUploadTokenStep({step}: AddUploadTokenStepProps) {
4654

4755
return (
4856
<OnboardingStep.Container>
49-
<OnboardingStep.Header>{headerText}</OnboardingStep.Header>
50-
<OnboardingStep.Content>
51-
<p>
52-
{tct(
53-
'Sentry requires a token to authenticate uploading your coverage reports. GitHub [repoAdmin] is required to access organization settings > secrets and variables > actions',
54-
{
55-
repoAdmin: <b>{t('Repository admin')}</b>,
56-
}
57-
)}
58-
</p>
59-
{showTokenDetails ? (
60-
showFullToken ? (
61-
<Fragment>
62-
{showWarning && (
63-
<Alert.Container>
64-
<Alert
65-
type="warning"
66-
data-test-id="page-error-alert"
67-
trailingItems={<IconClose size="sm" onClick={handleDismiss} />}
68-
>
69-
{t(
70-
"Please copy this token to a safe place - it won't be shown again."
71-
)}
72-
</Alert>
73-
</Alert.Container>
74-
)}
57+
<OnboardingStep.Body>
58+
<OnboardingStep.Header>{headerText}</OnboardingStep.Header>
59+
<OnboardingStep.Content>
60+
<p>
61+
{tct(
62+
'Sentry requires a token to authenticate uploading your coverage reports. GitHub [repoAdmin] is required to access organization settings > secrets and variables > actions',
63+
{
64+
repoAdmin: <b>{t('Repository admin')}</b>,
65+
}
66+
)}
67+
</p>
68+
{showTokenDetails ? (
69+
showFullToken ? (
70+
<Fragment>
71+
{showWarning && (
72+
<Alert.Container>
73+
<Alert
74+
type="warning"
75+
data-test-id="page-error-alert"
76+
trailingItems={<IconClose size="sm" onClick={handleDismiss} />}
77+
>
78+
{t(
79+
"Please copy this token to a safe place - it won't be shown again."
80+
)}
81+
</Alert>
82+
</Alert.Container>
83+
)}
84+
<Flex justify="between" gap="md">
85+
<Flex justify="between" gap="md">
86+
<CodeSnippet dark>SENTRY_PREVENT_TOKEN</CodeSnippet>
87+
<CodeSnippet dark>{FULL_TOKEN}</CodeSnippet>
88+
</Flex>
89+
<Button priority="primary" onClick={handleDoneClick}>
90+
{t('Done')}
91+
</Button>
92+
</Flex>
93+
</Fragment>
94+
) : (
7595
<Flex justify="between" gap="md">
7696
<Flex justify="between" gap="md">
7797
<CodeSnippet dark>SENTRY_PREVENT_TOKEN</CodeSnippet>
78-
<CodeSnippet dark>{FULL_TOKEN}</CodeSnippet>
98+
<CodeSnippet dark>{TRUNCATED_TOKEN}</CodeSnippet>
7999
</Flex>
80-
<Button priority="primary" onClick={handleDoneClick}>
81-
{t('Done')}
100+
<Button priority="default" onClick={handleGenerateClick}>
101+
{t('Regenerate')}
82102
</Button>
83103
</Flex>
84-
</Fragment>
104+
)
85105
) : (
86-
<Flex justify="between" gap="md">
87-
<Flex justify="between" gap="md">
88-
<CodeSnippet dark>SENTRY_PREVENT_TOKEN</CodeSnippet>
89-
<CodeSnippet dark>{TRUNCATED_TOKEN}</CodeSnippet>
90-
</Flex>
91-
<Button priority="default" onClick={handleGenerateClick}>
92-
{t('Regenerate')}
93-
</Button>
94-
</Flex>
95-
)
96-
) : (
97-
<Button priority="primary" onClick={handleGenerateClick}>
98-
{t('Generate Repository Token')}
99-
</Button>
100-
)}
101-
</OnboardingStep.Content>
106+
<Button priority="primary" onClick={handleGenerateClick}>
107+
{t('Generate Repository Token')}
108+
</Button>
109+
)}
110+
</OnboardingStep.Content>
111+
</OnboardingStep.Body>
112+
<OnboardingStep.ExpandableDropdown
113+
triggerContent={
114+
<div>{t('Your repository secret in GitHub should look like this:')}</div>
115+
}
116+
>
117+
<img
118+
src={isDarkMode ? testAnalyticsRepoSecretDark : testAnalyticsRepoSecretLight}
119+
/>
120+
</OnboardingStep.ExpandableDropdown>
102121
</OnboardingStep.Container>
103122
);
104123
}

static/app/views/prevent/tests/onboardingSteps/chooseUploadPermissionStep.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,17 @@ export function ChooseUploadPermissionStep({
5050

5151
return (
5252
<OnboardingStep.Container>
53-
<OnboardingStep.Header>{headerText}</OnboardingStep.Header>
54-
<OnboardingStep.Content>
55-
<RadioGroup
56-
label="Choose an upload permission"
57-
value={selectedUploadPermission}
58-
onChange={handleRadioChange}
59-
choices={CHOICE_OPTIONS}
60-
/>
61-
</OnboardingStep.Content>
53+
<OnboardingStep.Body>
54+
<OnboardingStep.Header>{headerText}</OnboardingStep.Header>
55+
<OnboardingStep.Content>
56+
<RadioGroup
57+
label="Choose an upload permission"
58+
value={selectedUploadPermission}
59+
onChange={handleRadioChange}
60+
choices={CHOICE_OPTIONS}
61+
/>
62+
</OnboardingStep.Content>
63+
</OnboardingStep.Body>
6264
</OnboardingStep.Container>
6365
);
6466
}

static/app/views/prevent/tests/onboardingSteps/editGHAWorkflowStep.tsx

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import styled from '@emotion/styled';
33
import {CodeSnippet} from 'sentry/components/codeSnippet';
44
import {Link} from 'sentry/components/core/link';
55
import {t, tct} from 'sentry/locale';
6-
import {space} from 'sentry/styles/space';
76
import {InlineCodeSnippet} from 'sentry/views/prevent/styles';
7+
import {GHAWorkflowExpandable} from 'sentry/views/prevent/tests/onboardingSteps/GHAWorkflowExpandable';
88
import {OnboardingStep} from 'sentry/views/prevent/tests/onboardingSteps/onboardingStep';
99

1010
interface EditGHAWorkflowStepProps {
@@ -27,47 +27,49 @@ export function EditGHAWorkflowStep({step}: EditGHAWorkflowStepProps) {
2727

2828
return (
2929
<OnboardingStep.Container>
30-
<OnboardingStep.Header>{headerText}</OnboardingStep.Header>
31-
<OnboardingStep.Content>
32-
<TopParagraph>
30+
<OnboardingStep.Body>
31+
<OnboardingStep.Header>{headerText}</OnboardingStep.Header>
32+
<OnboardingStep.Content>
33+
<TopParagraph>
34+
<SubHeader>
35+
{tct(
36+
'Add [permissions] block at the top level in your CI YAML file to run Sentry Prevent',
37+
{
38+
permissions: <InlineCodeSnippet>permissions</InlineCodeSnippet>,
39+
}
40+
)}
41+
</SubHeader>
42+
<CodeSnippet dark language="yaml">
43+
{PERMISSIONS_SNIPPET}
44+
</CodeSnippet>
45+
<Paragraph>
46+
{tct(
47+
'Set this permission at the workflow or job level. For better security, define it at the job level as it limits access to only the job that needs the OIDC token. Learn more about [permissionsSettings].',
48+
{
49+
permissionsSettings: <Link to="">{t('permissions settings')}</Link>,
50+
}
51+
)}
52+
</Paragraph>
53+
</TopParagraph>
3354
<SubHeader>
34-
{tct(
35-
'Add [permissions] block at the top level in your CI YAML file to run Sentry Prevent',
36-
{
37-
permissions: <InlineCodeSnippet>permissions</InlineCodeSnippet>,
38-
}
39-
)}
55+
{tct('Add the script [actionName] to your CI YAML file', {
56+
actionName: <InlineCodeSnippet>getsentry/prevent-action</InlineCodeSnippet>,
57+
})}
4058
</SubHeader>
59+
<Paragraph>
60+
{t('In your CI YAML file, add below scripts to the end of your test run.')}
61+
</Paragraph>
4162
<CodeSnippet dark language="yaml">
42-
{PERMISSIONS_SNIPPET}
63+
{ACTION_SNIPPET}
4364
</CodeSnippet>
4465
<Paragraph>
45-
{tct(
46-
'Set this permission at the workflow or job level. For better security, define it at the job level as it limits access to only the job that needs the OIDC token. Learn more about [permissionsSettings].',
47-
{
48-
permissionsSettings: <Link to="">{t('permissions settings')}</Link>,
49-
}
66+
{t(
67+
'This action will download the Sentry Prevent CLI, and upload the junit.xml file generated in the previous step to Sentry.'
5068
)}
5169
</Paragraph>
52-
</TopParagraph>
53-
<SubHeader>
54-
{tct('Add the script [actionName] to your CI YAML file', {
55-
actionName: <InlineCodeSnippet>getsentry/prevent-action</InlineCodeSnippet>,
56-
})}
57-
</SubHeader>
58-
<Paragraph>
59-
{t('In your CI YAML file, add below scripts to the end of your test run.')}
60-
</Paragraph>
61-
<CodeSnippet dark language="yaml">
62-
{ACTION_SNIPPET}
63-
</CodeSnippet>
64-
<Paragraph>
65-
{t(
66-
'This action will download the Sentry Prevent CLI, and upload the junit.xml file generated in the previous step to Sentry.'
67-
)}
68-
</Paragraph>
69-
{/* TODO: add dropdown expansion */}
70-
</OnboardingStep.Content>
70+
</OnboardingStep.Content>
71+
</OnboardingStep.Body>
72+
<GHAWorkflowExpandable />
7173
</OnboardingStep.Container>
7274
);
7375
}
@@ -81,9 +83,9 @@ const SubHeader = styled('div')`
8183
`;
8284

8385
const TopParagraph = styled('div')`
84-
margin-bottom: ${space(3)};
86+
margin-bottom: ${p => p.theme.space['2xl']};
8587
`;
8688

8789
const Paragraph = styled('div')`
88-
margin: ${space(1)} 0;
90+
margin: ${p => p.theme.space.md} 0;
8991
`;

0 commit comments

Comments
 (0)