Skip to content

Conversation

@mtopo27
Copy link
Contributor

@mtopo27 mtopo27 commented Dec 4, 2025

context: https://www.notion.so/sentry/Integrating-with-releases-short-term-fix-2b08b10e4b5d80cbb28ccbdefe46f7f8#2b58b10e4b5d80acb810f8af7c651bac

When mobile project selected:
Screenshot 2025-12-10 at 2 09 50 PM
Screenshot 2025-12-10 at 2 09 44 PM

When non-mobile project is selected (also tested to confirm default releases page is handled when switching from mobile back to non-mobile):
Screenshot 2025-12-10 at 2 09 57 PM

@github-actions github-actions bot added the Scope: Frontend Automatically applied to PRs that change frontend components label Dec 4, 2025
@codecov
Copy link

codecov bot commented Dec 4, 2025

❌ 1 Tests Failed:

Tests completed Failed Passed Skipped
12840 1 12839 10
View the top 1 failed test(s) by shortest run time
ReleasesList allows searching within the mobile-builds tab
Stack Traces | 1.6s run time
Error: expect(jest.fn()).toHaveBeenLastCalledWith(...expected)

Expected: ".../mobile-project-2/preprodartifacts/list-builds/", ObjectContaining {"query": ObjectContaining {"per_page": 25, "query": "branch:main", "statsPeriod": "14d"}}
Received
       3: ".../mobile-project-2/preprodartifacts/list-builds/", {"data": undefined, "error": [Function error], "headers": undefined, "host": undefined, "method": "GET", "query": {"per_page": 25, "statsPeriod": "14d", "tab": "mobile-builds"}, "success": [Function success]}
->     4: ".../mobile-project-2/preprodartifacts/list-builds/", {"data": undefined, "error": [Function error], "headers": undefined, "host": undefined, "method": "GET", "query": {"per_page": 25, "query": "b", "statsPeriod": "14d", "tab": "mobile-builds"}, "success": [Function success]}

Number of calls: 4

Ignored nodes: comments, script, style
...
    at toHaveBeenLastCalledWith (.../releases/list/index.spec.tsx:633:26)
    at runWithExpensiveErrorDiagnosticsDisabled (.../sentry/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@.../dom/dist/config.js:47:12)
    at checkCallback (.../sentry/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@.../dom/dist/wait-for.js:124:77)
    at checkRealTimersCallback (.../sentry/node_modules/.pnpm/@testing-library+dom@10.4.0/node_modules/@.../dom/dist/wait-for.js:118:16)
    at Timeout.task [as _onTimeout] (.../sentry/node_modules/.pnpm/jsdom@26.1..../jsdom/browser/Window.js:579:19)
    at listOnTimeout (node:internal/timers:588:17)
    at processTimers (node:internal/timers:523:7)

To view more test analytics, go to the Test Analytics Dashboard
📋 Got 3 mins? Take this short survey to help us improve Test Analytics.

Copy link
Member

rbro112 commented Dec 10, 2025

This stack of pull requests is managed by Graphite. Learn more about stacking.

numberOfMobileBuilds === 0 ? (
<BadgeWrapper>
<FeatureBadge type="new" />
<FeatureBadge type="beta" />
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unifying on "Beta" per Max and I's discussion

selection={selection}
/>
<ReleasesPageFilterBar condensed>
<Layout.Header noActionWrap>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inlines the header now and moves the project selector into it. This is intentional to give us the divider under the tabs.

Image

)}

{selectedTab === 'releases' && (
<Fragment>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All content here is the same, just gated behind the selectedTab being 'releases'

const ReleasesPageFilterBar = styled(PageFilterBar)`
margin-bottom: ${space(2)};
const ReleasesPageFilterBar = styled(PageFilterBar)<{shouldShowMobileBuildsTab: boolean}>`
${p => !p.shouldShowMobileBuildsTab && `margin-bottom: ${p.theme.space.xl};`}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conditional logic to add bottom padding before the divider when tabs are not present

Image

@rbro112 rbro112 changed the title (WIP) Mtopo27/add mobile tab to releases v1 feat(releases): Add mobile tab to releases Dec 10, 2025
@rbro112 rbro112 marked this pull request as ready for review December 10, 2025 22:42
@rbro112 rbro112 requested a review from a team as a code owner December 10, 2025 22:42
([...mobile, ...desktop] as string[]).includes(releaseProjectPlatform);
export const isMobileRelease = (
releaseProjectPlatform: PlatformKey,
includeDesktop = true
Copy link
Member

@ryan953 ryan953 Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a funny prop

isMobile .... or sometimes desktop. lol

Copy link
Member

@rbro112 rbro112 Dec 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree but I admittedly don't have context here. Appears this change is just styling but will follow up and remove this weird includeDesktop behavior if I get the greenlight to from @mtopo27

Copy link
Member

@ryan953 ryan953 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

works for me. some nits if that's your thing.

:shipit: when you're ready!

if (!shouldShowMobileBuildsTab) {
return 'releases';
}
return (decodeScalar(location.query.tab) as ReleaseTab | undefined) || 'releases';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bug: The tab URL query parameter is not validated at runtime. An invalid value causes the component to render a blank page instead of defaulting to the 'releases' view.
Severity: HIGH | Confidence: High

🔍 Detailed Analysis

The selectedTab variable is derived from the tab URL query parameter using decodeScalar. This value is then type-cast to ReleaseTab | undefined without any runtime validation. If a user provides an invalid tab value in the URL, such as ?tab=invalid, selectedTab will hold this invalid string. Consequently, the conditional rendering for both the 'releases' and 'mobile-builds' tabs will fail, resulting in the page rendering an empty content area instead of defaulting to a valid view.

💡 Suggested Fix

Add runtime validation to ensure the value from decodeScalar(location.query.tab) is one of the expected values ('releases' or 'mobile-builds'). If it's not, default to 'releases'. For example: const tabValue = decodeScalar(location.query.tab); return (tabValue === 'mobile-builds' || tabValue === 'releases') ? tabValue : 'releases';.

🤖 Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.

Location: static/app/views/releases/list/index.tsx#L230

Potential issue: The `selectedTab` variable is derived from the `tab` URL query
parameter using `decodeScalar`. This value is then type-cast to `ReleaseTab | undefined`
without any runtime validation. If a user provides an invalid tab value in the URL, such
as `?tab=invalid`, `selectedTab` will hold this invalid string. Consequently, the
conditional rendering for both the 'releases' and 'mobile-builds' tabs will fail,
resulting in the page rendering an empty content area instead of defaulting to a valid
view.

Did we get this right? 👍 / 👎 to inform future reviews.
Reference ID: 6962494

@rbro112 rbro112 merged commit a1510a0 into master Dec 11, 2025
48 checks passed
@rbro112 rbro112 deleted the mtopo27/add-mobile-tab-to-releases-v1 branch December 11, 2025 00:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Scope: Frontend Automatically applied to PRs that change frontend components

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants