Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
181 changes: 126 additions & 55 deletions static/app/components/events/interfaces/sourceMapsDebuggerModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@
<Fragment>
<WizardInstructionParagraph>
{tct(
'Firstly, have you already run the Sentry Wizard with [code:sourcemaps] in your projects terminal? Its the easiest way to get source maps set up:',
"Firstly, have you already run the Sentry Wizard with [code:sourcemaps] in your project's terminal? It's the easiest way to get source maps set up:",
{
code: <code />,
}
Expand Down Expand Up @@ -482,10 +482,23 @@
<Body>
<p>
{t(
"It looks like the original source code for this stack frame couldn't be determined when this error was captured. To get the original code for this stack frame, Sentry needs source maps to be configured."
"It looks like the original source code for this stack frame couldn't be determined when this error was captured. To get the original code for this stack frame, Sentry needs source maps to be uploaded."
)}
</p>
{metaFrameworksWithSentryWizardInOnboarding.includes(platform) ? (
{isReactNativeSDK({
sdkName: sourceResolutionResults.sdkName,
}) ? (
<WizardInstructionParagraph>
{tct(
"For React Native projects, source maps should be generated and uploaded automatically during the build process. If your source maps aren't showing up, consult our [link:React Native source maps documentation].",
{
link: (
<ExternalLinkWithIcon href="https://docs.sentry.io/platforms/react-native/sourcemaps/" />
),
}
)}
</WizardInstructionParagraph>
) : metaFrameworksWithSentryWizardInOnboarding.includes(platform) ? (
<MetaFrameworkConfigInfo
framework={platform}
orgSlug={orgSlug}
Expand All @@ -499,9 +512,13 @@
/>
)}
<p>
{t(
"Secondly, let's go through a checklist to help you troubleshoot why source maps aren't showing up. There are a few ways to configure them:"
)}
{isReactNativeSDK({sdkName: sourceResolutionResults.sdkName})
? t(
"Let's go through a checklist to help you troubleshoot why source maps aren't showing up. There are a few ways to configure them:"
)
: t(
"Secondly, let's go through a checklist to help you troubleshoot why source maps aren't showing up. There are a few ways to configure them:"
)}
</p>
<Tabs<'debug-ids' | 'release' | 'fetching'>
value={activeTab}
Expand Down Expand Up @@ -595,12 +612,14 @@
<UploadedSourceFileWithCorrectDebugIdChecklistItem
shouldValidate={sourceResolutionResults.stackFrameDebugId !== null}
sourceResolutionResults={sourceResolutionResults}
projectSlug={project?.slug}
/>
<UploadedSourceMapWithCorrectDebugIdChecklistItem
shouldValidate={
sourceResolutionResults.uploadedSourceFileWithCorrectDebugId
}
sourceResolutionResults={sourceResolutionResults}
projectSlug={project?.slug}
/>
</CheckList>
{sourceResolutionResults.debugIdProgressPercent === 1 ? (
Expand All @@ -625,17 +644,19 @@
sourceResolutionResults={sourceResolutionResults}
/>
<ReleaseHasUploadedArtifactsChecklistItem
shouldValidate={sourceResolutionResults.release !== null}
shouldValidate={sourceResolutionResults.releaseHasSomeArtifact}
sourceResolutionResults={sourceResolutionResults}
/>
<ReleaseSourceFileMatchingChecklistItem
shouldValidate={sourceResolutionResults.releaseHasSomeArtifact}
shouldValidate={
sourceResolutionResults.sourceFileReleaseNameFetchingResult ===
'found'
}
sourceResolutionResults={sourceResolutionResults}
/>
<ReleaseSourceMapMatchingChecklistItem
shouldValidate={
sourceResolutionResults.sourceFileReleaseNameFetchingResult ===
'found'
sourceResolutionResults.sourceMapReleaseNameFetchingResult === 'found'
}
sourceResolutionResults={sourceResolutionResults}
/>
Expand Down Expand Up @@ -1026,14 +1047,9 @@
"It seems you already uploaded artifacts with Debug IDs, however, this event doesn't contain any Debug IDs yet. Generally this means that your application doesn't include the same files you uploaded to Sentry."
)}
</p>
<p>
{t(
'For Sentry to be able to show your original source code, it is required that you build the application with the exact same files that you uploaded to Sentry.'
)}
</p>
<p>
{tct(
'The [bundlerPluginRepoLink:Sentry Metro Plugin] needs to be active when building your production app. You cannot do two separate builds, for example, one for uploading to Sentry with the plugin being active and one for deploying without the plugin. The plugin needs to be active for every build.',
'The [bundlerPluginRepoLink:Sentry Metro Plugin] needs to be active when building your production app. You cannot do two separate builds, for example, one for uploading to Sentry with the plugin being active and one for deploying without the plugin.',
{
bundlerPluginRepoLink: (
<ExternalLinkWithIcon
Expand Down Expand Up @@ -1067,14 +1083,6 @@
toolUsedToUploadSourceMaps={toolUsedToUploadSourceMaps}
/>
)}
<p>
{tct(
'Read the [link:Sentry Source Maps Documentation] to learn how to inject Debug IDs into your build artifacts and how to upload them to Sentry.',
{
link: <ExternalLinkWithIcon href={sourceMapsDocLinks.sourcemaps} />,
}
)}
</p>
</CheckListInstruction>
</CheckListItem>
);
Expand All @@ -1100,14 +1108,16 @@
function UploadedSourceFileWithCorrectDebugIdChecklistItem({
sourceResolutionResults,
shouldValidate,
projectSlug,
}: {
shouldValidate: boolean;
sourceResolutionResults: FrameSourceMapDebuggerData;
projectSlug?: string;
}) {
const platform = getPlatform(sourceResolutionResults);
const sourceMapsDocLinks = getSourceMapsDocLinks(platform);
const successMessage = t('Source file with a matching Debug ID was uploaded');
const errorMessage = t('Missing source file with a matching Debug ID');
const errorMessage = t('Missing a source file with a matching Debug ID');

if (!shouldValidate) {
return <CheckListItem status="none" title={successMessage} />;
Expand All @@ -1118,26 +1128,32 @@
}

if (sourceResolutionResults.uploadedSomeArtifactWithDebugId) {
const debugId = sourceResolutionResults.stackFrameDebugId;

return (
<CheckListItem status="alert" title={errorMessage}>
<CheckListInstruction type="muted">
<h6>{t('No Source File With Matching Debug ID')}</h6>
<p>
{tct('We cannot find a source file with this Debug ID: [debugId].', {
debugId: <MonoBlock>{debugId}</MonoBlock>,
})}
</p>
<p>
{tct(
"You already uploaded artifacts with Debug IDs but none of the uploaded source files had a Debug ID matching this stack frame's Debug ID: [debugId]",
'Check your [link:source maps uploads] to verify if the bundle with this Debug ID was uploaded properly.',
{
debugId: (
<MonoBlock>{sourceResolutionResults.stackFrameDebugId}</MonoBlock>
link: (
<LinkWithIcon
to={
projectSlug
? `/settings/projects/${projectSlug}/source-maps/?query=${debugId}`
: `/settings/projects/:projectId/source-maps/?query=${debugId}`
Copy link
Member

Choose a reason for hiding this comment

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

does this work? I have never written a link this way

}
/>
),
}
)}
</p>
<p>
{t(
'Make sure to inject Debug IDs into all of your source files and to upload all of them to Sentry.'
)}
</p>
{/* TODO: Link to Uploaded Artifacts */}
</CheckListInstruction>
</CheckListItem>
);
Expand All @@ -1146,15 +1162,32 @@
return (
<CheckListItem status="alert" title={errorMessage}>
<CheckListInstruction type="muted">
<h6>{t('No Artifacts With Debug IDs Uploaded')}</h6>
<p>

Check failure on line 1165 in static/app/components/events/interfaces/sourceMapsDebuggerModal.tsx

View workflow job for this annotation

GitHub Actions / self-hosted

Type 'string | undefined' is not assignable to type 'string'.

Check failure on line 1165 in static/app/components/events/interfaces/sourceMapsDebuggerModal.tsx

View workflow job for this annotation

GitHub Actions / typescript

Type 'string | undefined' is not assignable to type 'string'.
{tct(
"You didn't upload any artifacts with debug IDs yet. Read the [link:Sentry Source Maps Documentation] to learn how to inject Debug IDs into your build artifacts and how to upload them to Sentry.",
{
link: <ExternalLinkWithIcon href={sourceMapsDocLinks.sourcemaps} />,
}
)}
{tct('You did not upload any artifacts with [link:Debug IDs] yet.', {
link: <ExternalLinkWithIcon href={sourceMapsDocLinks.debugIds} />,
})}
</p>
{isReactNativeSDK({sdkName: sourceResolutionResults.sdkName}) && (
<p>
{tct(
'Check the [link:source maps uploads] for the missing source maps for debug ID: [debugId]. You should have source maps for both Android and iOS builds.',
{
link: (
<LinkWithIcon
to={
projectSlug
? `/settings/projects/${projectSlug}/source-maps/?query=${sourceResolutionResults.stackFrameDebugId}`
: `/settings/projects/:projectId/source-maps/?query=${sourceResolutionResults.stackFrameDebugId}`
}
/>
),
debugId: (
<MonoBlock>{sourceResolutionResults.stackFrameDebugId}</MonoBlock>
),
}
)}
</p>
)}
{/* TODO: Link to Uploaded Artifacts */}
</CheckListInstruction>
</CheckListItem>
Expand All @@ -1164,14 +1197,16 @@
function UploadedSourceMapWithCorrectDebugIdChecklistItem({
sourceResolutionResults,
shouldValidate,
projectSlug,
}: {
shouldValidate: boolean;
sourceResolutionResults: FrameSourceMapDebuggerData;
projectSlug?: string;
}) {
const platform = getPlatform(sourceResolutionResults);
const sourceMapsDocLinks = getSourceMapsDocLinks(platform);
const successMessage = t('Uploaded source map with a matching Debug ID');
const errorMessage = t('Missing source map with a matching Debug ID');
const errorMessage = t('Missing a source map with a matching Debug ID');

if (!shouldValidate) {
return <CheckListItem status="none" title={successMessage} />;
Expand All @@ -1182,6 +1217,8 @@
}

if (sourceResolutionResults.uploadedSomeArtifactWithDebugId) {
const debugId = sourceResolutionResults.stackFrameDebugId;

return (
<CheckListItem status="alert" title={errorMessage}>
<CheckListInstruction type="muted">
Expand All @@ -1190,15 +1227,24 @@
{tct(
"You already uploaded artifacts with Debug IDs but none of the uploaded source maps had a Debug ID matching this stack frame's Debug ID: [debugId]",
{
debugId: (
<MonoBlock>{sourceResolutionResults.stackFrameDebugId}</MonoBlock>
),
debugId: <MonoBlock>{debugId}</MonoBlock>,
}
)}
</p>
<p>
{t(
'Make sure to inject Debug IDs into all of your source files and to upload all of them to Sentry.'
{tct(
'Check your [link:source maps uploads] to verify if the bundle with this Debug ID was uploaded properly.',
{
link: (
<LinkWithIcon
to={
projectSlug
? `/settings/projects/${projectSlug}/source-maps/?query=${debugId}`
: `/settings/projects/:projectId/source-maps/?query=${debugId}`
}
/>
),
}
)}
</p>
{/* TODO: Link to Uploaded Artifacts */}
Expand All @@ -1213,13 +1259,31 @@
<CheckListInstruction type="muted">
<h6>{t('No Artifacts Uploaded')}</h6>
<p>
{tct(
"You didn't upload any artifacts with debug IDs yet. Read the [link:Sentry Source Maps Documentation] to learn how to inject Debug IDs into your build artifacts and how to upload them to Sentry.",
{
link: <ExternalLinkWithIcon href={sourceMapsDocLinks.sourcemaps} />,
}
)}
{tct('You did not upload any artifacts with debug IDs yet.', {
link: <ExternalLinkWithIcon href={sourceMapsDocLinks.sourcemaps} />,
})}
Comment on lines +1262 to +1264
Copy link
Member

Choose a reason for hiding this comment

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

same here. Also if we are going to repeat this multiple times, maybe it is worth creating a reusable component

</p>
{isReactNativeSDK({sdkName: sourceResolutionResults.sdkName}) && (
<p>
{tct(
'Check your [link:source maps uploads] for the missing source maps for debug ID: [debugId]. You should have source maps for both Android and iOS builds.',
Copy link
Member

Choose a reason for hiding this comment

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

should we always have Debug IDs capitalized?

{
link: (
<LinkWithIcon
to={
projectSlug
? `/settings/projects/${projectSlug}/source-maps/?query=${sourceResolutionResults.stackFrameDebugId}`
: `/settings/projects/:projectId/source-maps/?query=${sourceResolutionResults.stackFrameDebugId}`
}
/>
),
debugId: (
<MonoBlock>{sourceResolutionResults.stackFrameDebugId}</MonoBlock>
),
}
)}
</p>
)}
{/* TODO: Link to Uploaded Artifacts */}
</CheckListInstruction>
<SourceMapStepNotRequiredNote />
Expand Down Expand Up @@ -1465,7 +1529,6 @@
return (
<CheckListItem status="alert" title={errorMessage}>
<CheckListInstruction type="muted">
<h6>{t('Missing Source Map Reference')}</h6>
<p>
{tct(
'The source file for this stack frame is missing a source map reference. A source map reference is usually represented by a [sourceMappingUrl] comment at the bottom of your source file.',
Expand Down Expand Up @@ -1704,6 +1767,14 @@
);
}

function LinkWithIcon({to, children}: PropsWithChildren<{to: string}>) {
return (
<Link to={to}>
{children} <IconOpen size="xs" />
</Link>
);
}

function DistCodeSnippet() {
return (
<InstructionCodeSnippet language="javascript" dark hideCopyButton>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,41 @@ describe('ProjectSourceMaps', function () {
organization,
});

expect(await screen.findByText('No source map uploads found')).toBeInTheDocument();
expect(await screen.findByText('No Source Maps Uploaded')).toBeInTheDocument();
});

it('renders empty search results message', async function () {
const {organization, project, routerProps, router} = initializeOrg({
router: {
location: {
query: {query: 'nonexistent-source-map'},
pathname: `/settings/${initializeOrg().organization.slug}/projects/${
initializeOrg().project.slug
}/source-maps/`,
},
},
});

renderReleaseBundlesMockRequests({
orgSlug: organization.slug,
projectSlug: project.slug,
empty: true,
});

renderDebugIdBundlesMockRequests({
orgSlug: organization.slug,
projectSlug: project.slug,
empty: true,
});

render(<SourceMapsList project={project} {...routerProps} />, {
router,
organization,
});

expect(
await screen.findByText('No source map uploads found matching your search')
).toBeInTheDocument();
});
});
});
Loading
Loading