Skip to content

Commit 9906334

Browse files
committed
fix(onboarding): Skip duplicate project creation in SCM steps
When a user goes back from setup-docs after the project has already received its first event, the project is not deleted. Without this guard, clicking Continue/Create again would attempt to create a duplicate. Check the projects store first and reuse the existing project, mirroring the useConfigureSdk logic. Also use useExperiment for the SCM back-action check to stay consistent with how onboarding.tsx reads the experiment flag. Refs VDY-82
1 parent 1e517d0 commit 9906334

File tree

3 files changed

+33
-6
lines changed

3 files changed

+33
-6
lines changed

static/app/views/onboarding/scmPlatformFeatures.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import type {PlatformIntegration, PlatformKey} from 'sentry/types/project';
2727
import {trackAnalytics} from 'sentry/utils/analytics';
2828
import {isDisabledGamingPlatform} from 'sentry/utils/platform';
2929
import {useOrganization} from 'sentry/utils/useOrganization';
30+
import {useProjects} from 'sentry/utils/useProjects';
3031
import {useTeams} from 'sentry/utils/useTeams';
3132
import {ScmFeatureSelectionCards} from 'sentry/views/onboarding/components/scmFeatureSelectionCards';
3233
import {ScmPlatformCard} from 'sentry/views/onboarding/components/scmPlatformCard';
@@ -93,6 +94,7 @@ export function ScmPlatformFeatures({onComplete}: StepProps) {
9394
} = useOnboardingContext();
9495

9596
const {teams} = useTeams();
97+
const {projects} = useProjects();
9698
const createProject = useCreateProject();
9799
const hasProjectDetailsStep = organization.features.includes(
98100
'onboarding-scm-project-details'
@@ -338,6 +340,16 @@ export function ScmPlatformFeatures({onComplete}: StepProps) {
338340
return;
339341
}
340342

343+
// If a project for this platform already exists (e.g. the user went
344+
// back after the project had already received its first event), skip
345+
// creation and reuse it — mirrors useConfigureSdk logic.
346+
const existingProject = projects.find(p => p.slug === platform.key);
347+
if (existingProject) {
348+
setCreatedProjectSlug(existingProject.slug);
349+
onComplete(undefined, {product: currentFeatures});
350+
return;
351+
}
352+
341353
const firstAdminTeam = teams.find((team: Team) =>
342354
team.access.includes('team:admin')
343355
);

static/app/views/onboarding/scmProjectDetails.tsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type {Team} from 'sentry/types/organization';
1616
import {trackAnalytics} from 'sentry/utils/analytics';
1717
import {slugify} from 'sentry/utils/slugify';
1818
import {useOrganization} from 'sentry/utils/useOrganization';
19+
import {useProjects} from 'sentry/utils/useProjects';
1920
import {useTeams} from 'sentry/utils/useTeams';
2021
import {
2122
DEFAULT_ISSUE_ALERT_OPTIONS_VALUES,
@@ -36,6 +37,7 @@ export function ScmProjectDetails({onComplete}: StepProps) {
3637
const {selectedPlatform, selectedFeatures, setCreatedProjectSlug} =
3738
useOnboardingContext();
3839
const {teams} = useTeams();
40+
const {projects} = useProjects();
3941
const createProjectAndRules = useCreateProjectAndRules();
4042
useEffect(() => {
4143
trackAnalytics('onboarding.scm_project_details_step_viewed', {organization});
@@ -101,6 +103,16 @@ export function ScmProjectDetails({onComplete}: StepProps) {
101103
return;
102104
}
103105

106+
// If a project for this name already exists (e.g. the user went back
107+
// after the project had already received its first event), skip
108+
// creation and reuse it — mirrors useConfigureSdk logic.
109+
const existingProject = projects.find(p => p.slug === projectNameResolved);
110+
if (existingProject) {
111+
setCreatedProjectSlug(existingProject.slug);
112+
onComplete(undefined, selectedFeatures ? {product: selectedFeatures} : undefined);
113+
return;
114+
}
115+
104116
trackAnalytics('onboarding.scm_project_details_create_clicked', {organization});
105117

106118
try {

static/app/views/onboarding/useBackActions.tsx

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {handleXhrErrorResponse} from 'sentry/utils/handleXhrErrorResponse';
1010
import type {RequestError} from 'sentry/utils/requestError/requestError';
1111
import {normalizeUrl} from 'sentry/utils/url/normalizeUrl';
1212
import {useApi} from 'sentry/utils/useApi';
13+
import {useExperiment} from 'sentry/utils/useExperiment';
1314
import {useOrganization} from 'sentry/utils/useOrganization';
1415
import type {StepDescriptor} from 'sentry/views/onboarding/types';
1516

@@ -33,6 +34,9 @@ export function useBackActions({
3334
const api = useApi();
3435
const organization = useOrganization();
3536
const onboardingContext = useOnboardingContext();
37+
const {inExperiment: hasScmOnboarding} = useExperiment({
38+
feature: 'onboarding-scm-experiment',
39+
});
3640
const currentStep = onboardingSteps[stepIndex];
3741

3842
const deleteRecentCreatedProject = useCallback(
@@ -118,23 +122,22 @@ export function useBackActions({
118122
// store data and skip project creation.
119123
// In the SCM flow, preserve context so the user keeps their SCM
120124
// connection, repo selection, and feature choices.
121-
await deleteRecentCreatedProject(
122-
organization.features.includes('onboarding-scm-experiment')
123-
);
125+
await deleteRecentCreatedProject(hasScmOnboarding);
124126
}
125127

126128
if (!browserBackButton) {
127129
goToStep(prevStep);
128130
}
129131
},
130132
[
131-
goToStep,
133+
currentStep,
132134
organization,
133-
onboardingContext,
134135
isRecentCreatedProjectActive,
135136
recentCreatedProject,
136-
currentStep,
137+
onboardingContext,
138+
goToStep,
137139
deleteRecentCreatedProject,
140+
hasScmOnboarding,
138141
]
139142
);
140143

0 commit comments

Comments
 (0)