From 5fd61e0f04de9957c4c8b9f4f0600f2ff244ee44 Mon Sep 17 00:00:00 2001 From: Nico Hinderling Date: Thu, 16 Apr 2026 08:46:52 -0700 Subject: [PATCH] ref(preprod): Move Snapshots tab to standalone settings subpage Extract the Snapshots tab from the Mobile Builds settings page into its own project settings subpage at /settings/:orgId/projects/:projectId/snapshots/. The new page is feature-gated behind organizations:preprod-snapshots and shows an alpha badge in the sidebar navigation. Co-Authored-By: Claude --- static/app/router/routes.tsx | 5 ++ .../project/navigationConfiguration.tsx | 7 +++ .../views/settings/project/preprod/index.tsx | 26 ++-------- .../settings/project/preprod/snapshots.tsx | 52 +++++++++++++++++++ 4 files changed, 67 insertions(+), 23 deletions(-) create mode 100644 static/app/views/settings/project/preprod/snapshots.tsx diff --git a/static/app/router/routes.tsx b/static/app/router/routes.tsx index 19b8680cc4e7..31cf95f2655e 100644 --- a/static/app/router/routes.tsx +++ b/static/app/router/routes.tsx @@ -672,6 +672,11 @@ function buildRoutes(): RouteObject[] { name: t('Mobile Builds'), component: make(() => import('sentry/views/settings/project/preprod')), }, + { + path: 'snapshots/', + name: t('Snapshots'), + component: make(() => import('sentry/views/settings/project/preprod/snapshots')), + }, { path: 'keys/', name: t('Client Keys'), diff --git a/static/app/views/settings/project/navigationConfiguration.tsx b/static/app/views/settings/project/navigationConfiguration.tsx index 5e38c7baf81c..49c43dda494e 100644 --- a/static/app/views/settings/project/navigationConfiguration.tsx +++ b/static/app/views/settings/project/navigationConfiguration.tsx @@ -134,6 +134,13 @@ export function getNavigationConfiguration({ badge: () => 'new', description: t('Size analysis and build distribution configuration.'), }, + { + path: `${pathPrefix}/snapshots/`, + title: t('Snapshots'), + badge: () => 'alpha', + show: () => !!organization?.features?.includes('preprod-snapshots'), + description: t('Configure snapshot status checks and PR comments.'), + }, ], }, { diff --git a/static/app/views/settings/project/preprod/index.tsx b/static/app/views/settings/project/preprod/index.tsx index 6b4b3c3a931a..73106c388046 100644 --- a/static/app/views/settings/project/preprod/index.tsx +++ b/static/app/views/settings/project/preprod/index.tsx @@ -11,7 +11,6 @@ import {t} from 'sentry/locale'; import {decodeScalar} from 'sentry/utils/queryString'; import {useLocation} from 'sentry/utils/useLocation'; import {useNavigate} from 'sentry/utils/useNavigate'; -import {useOrganization} from 'sentry/utils/useOrganization'; import {TopBar} from 'sentry/views/navigation/topBar'; import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature'; import {PreprodQuotaAlert} from 'sentry/views/preprod/components/preprodQuotaAlert'; @@ -19,11 +18,9 @@ import {SettingsPageHeader} from 'sentry/views/settings/components/settingsPageH import {FeatureFilter} from './featureFilter'; import {PrCommentsToggle} from './prCommentsToggle'; -import {SnapshotPrCommentsToggle} from './snapshotPrCommentsToggle'; -import {SnapshotStatusChecks} from './snapshotStatusChecks'; import {StatusCheckRules} from './statusCheckRules'; -type PreprodTab = 'size' | 'distribution' | 'snapshots'; +type PreprodTab = 'size' | 'distribution'; const SIZE_ENABLED_READ_KEY = 'sentry:preprod_size_enabled_by_customer'; const SIZE_ENABLED_WRITE_KEY = 'preprodSizeEnabledByCustomer'; @@ -35,21 +32,15 @@ const DISTRIBUTION_ENABLED_WRITE_KEY = 'preprodDistributionEnabledByCustomer'; const DISTRIBUTION_ENABLED_QUERY_READ_KEY = 'sentry:preprod_distribution_enabled_query'; const DISTRIBUTION_ENABLED_QUERY_WRITE_KEY = 'preprodDistributionEnabledQuery'; -const VALID_TABS: PreprodTab[] = ['size', 'distribution', 'snapshots']; +const VALID_TABS: PreprodTab[] = ['size', 'distribution']; export default function PreprodSettings() { const location = useLocation(); const navigate = useNavigate(); - const organization = useOrganization(); const hasPageFrameFeature = useHasPageFrameFeature(); - const hasSnapshots = organization.features.includes('preprod-snapshots'); - - const availableTabs = hasSnapshots - ? VALID_TABS - : VALID_TABS.filter(tab => tab !== 'snapshots'); const queryTab = decodeScalar(location?.query?.tab); - const tab = availableTabs.includes(queryTab as PreprodTab) + const tab = VALID_TABS.includes(queryTab as PreprodTab) ? (queryTab as PreprodTab) : 'size'; @@ -84,9 +75,6 @@ export default function PreprodSettings() { {t('Size Analysis')} {t('Build Distribution')} - @@ -121,14 +109,6 @@ export default function PreprodSettings() { )} - {tab === 'snapshots' && ( - - - - - - - )} ); diff --git a/static/app/views/settings/project/preprod/snapshots.tsx b/static/app/views/settings/project/preprod/snapshots.tsx new file mode 100644 index 000000000000..e4d25cbaa6e8 --- /dev/null +++ b/static/app/views/settings/project/preprod/snapshots.tsx @@ -0,0 +1,52 @@ +import {Fragment} from 'react'; + +import {Grid, Stack} from '@sentry/scraps/layout'; + +import Feature from 'sentry/components/acl/feature'; +import {NotFound} from 'sentry/components/errors/notFound'; +import {FeedbackButton} from 'sentry/components/feedbackButton/feedbackButton'; +import {SentryDocumentTitle} from 'sentry/components/sentryDocumentTitle'; +import {t} from 'sentry/locale'; +import {useOrganization} from 'sentry/utils/useOrganization'; +import {TopBar} from 'sentry/views/navigation/topBar'; +import {useHasPageFrameFeature} from 'sentry/views/navigation/useHasPageFrameFeature'; +import {SettingsPageHeader} from 'sentry/views/settings/components/settingsPageHeader'; + +import {SnapshotPrCommentsToggle} from './snapshotPrCommentsToggle'; +import {SnapshotStatusChecks} from './snapshotStatusChecks'; + +export default function SnapshotSettings() { + const organization = useOrganization(); + const hasPageFrameFeature = useHasPageFrameFeature(); + + if (!organization.features.includes('preprod-snapshots')) { + return ; + } + + return ( + + + + {hasPageFrameFeature ? ( + + {null} + + ) : ( + + )} + + } + /> + + + + + + + + ); +}