Skip to content

Commit 6f98d27

Browse files
feat(preprod): Check for actual build data when showing mobile builds tab (#112525)
Adjust the Mobile Builds tab visibility on the Releases page to also check for actual build data, not just whether the project has a mobile platform. Previously, the tab showed purely based on `isMobileRelease()` — a client-side platform check. Now we also probe the existing `/builds/` endpoint with `per_page=1` to see if any preprod builds exist for the selected projects and time range. The tab shows if either condition is true: 1. The builds endpoint returns at least one result 2. At least one selected project has a mobile platform (existing fallback) The probe query is gated behind the `preprod-frontend-routes` feature flag and uses a 60s stale time. Only date-related params are passed to avoid spurious refetches from unrelated URL query changes. Refs EME-706 --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 23b99b0 commit 6f98d27

File tree

2 files changed

+36
-10
lines changed

2 files changed

+36
-10
lines changed

static/app/views/releases/list/index.spec.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,10 @@ describe('ReleasesList', () => {
100100
method: 'POST',
101101
body: {attributes: {}},
102102
});
103+
MockApiClient.addMockResponse({
104+
url: `/organizations/${organization.slug}/builds/`,
105+
body: [],
106+
});
103107
});
104108

105109
afterEach(() => {

static/app/views/releases/list/index.tsx

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {Fragment, useCallback, useEffect, useMemo} from 'react';
22
import {forceCheck} from 'react-lazyload';
33
import styled from '@emotion/styled';
4+
import {keepPreviousData, useQuery} from '@tanstack/react-query';
45

56
import {FeatureBadge} from '@sentry/scraps/badge';
67
import {Flex, Stack} from '@sentry/scraps/layout';
@@ -41,6 +42,7 @@ import {useLocation} from 'sentry/utils/useLocation';
4142
import {useNavigate} from 'sentry/utils/useNavigate';
4243
import {useOrganization} from 'sentry/utils/useOrganization';
4344
import {useProjects} from 'sentry/utils/useProjects';
45+
import {buildDetailsApiOptions} from 'sentry/views/preprod/utils/buildDetailsApiOptions';
4446
import {ReleaseArchivedNotice} from 'sentry/views/releases/detail/overview/releaseArchivedNotice';
4547
import {MobileBuilds} from 'sentry/views/releases/list/mobileBuilds';
4648
import {ReleaseHealthCTA} from 'sentry/views/releases/list/releaseHealthCTA';
@@ -232,13 +234,29 @@ export default function ReleasesList() {
232234
: selectedIds.map(id => `${id}`);
233235
}, [selection.projects]);
234236

235-
const shouldShowMobileBuildsTab = useMemo(() => {
236-
if (!organization.features?.includes('preprod-frontend-routes')) {
237-
return false;
238-
}
239-
240-
// When "All Projects" is selected (represented by [-1]), check all accessible projects
241-
// When specific projects are selected, check only those projects
237+
const hasPreprodFeature = organization.features?.includes('preprod-frontend-routes');
238+
239+
const {statsPeriod, start, end, utc} = normalizeDateTimeParams(location.query);
240+
const buildsProbeQuery = useQuery({
241+
...buildDetailsApiOptions({
242+
organization,
243+
queryParams: {
244+
per_page: 1,
245+
project: selectedProjectIds,
246+
...(statsPeriod && {statsPeriod}),
247+
...(start && {start}),
248+
...(end && {end}),
249+
...(utc && {utc}),
250+
},
251+
}),
252+
staleTime: 60_000,
253+
enabled: !!hasPreprodFeature,
254+
placeholderData: keepPreviousData,
255+
});
256+
257+
// When "All Projects" is selected (represented by [-1]), check all accessible projects
258+
// When specific projects are selected, check only those projects
259+
const hasAnyStrictlyMobileProject = useMemo(() => {
242260
const isAllProjects =
243261
selectedProjectIds.length === 1 &&
244262
selectedProjectIds[0] === `${ALL_ACCESS_PROJECTS}`;
@@ -247,13 +265,17 @@ export default function ReleasesList() {
247265
: selectedProjectIds;
248266

249267
// Check if at least one project has a mobile platform
250-
const hasAnyStrictlyMobileProject = projectIdsToCheck
268+
return projectIdsToCheck
251269
.map(id => ProjectsStore.getById(id))
252270
.filter(Boolean)
253271
.some(project => project?.platform && isMobileRelease(project.platform, false));
272+
}, [selectedProjectIds, projects]);
273+
274+
const hasBuildsData =
275+
!buildsProbeQuery.isPending && (buildsProbeQuery.data?.length ?? 0) > 0;
254276

255-
return hasAnyStrictlyMobileProject;
256-
}, [organization.features, selectedProjectIds, projects]);
277+
const shouldShowMobileBuildsTab =
278+
hasPreprodFeature && (hasBuildsData || hasAnyStrictlyMobileProject);
257279

258280
const selectedTab = useMemo(() => {
259281
if (!shouldShowMobileBuildsTab) {

0 commit comments

Comments
 (0)