diff --git a/static/app/views/preprod/buildDetails/sidebar/buildDetailsSidebarAppInfo.tsx b/static/app/views/preprod/buildDetails/sidebar/buildDetailsSidebarAppInfo.tsx
index 443dfcbf3a1a2b..a283124529b813 100644
--- a/static/app/views/preprod/buildDetails/sidebar/buildDetailsSidebarAppInfo.tsx
+++ b/static/app/views/preprod/buildDetails/sidebar/buildDetailsSidebarAppInfo.tsx
@@ -129,19 +129,15 @@ export function BuildDetailsSidebarAppInfo(props: BuildDetailsSidebarAppInfoProp
- {props.projectId && props.appInfo.is_installable ? (
+ {props.projectId ? (
{
openInstallModal(props.projectId!, props.artifactId);
}}
>
- Installable
+ Install
- ) : (
-
- Not Installable
-
- )}
+ ) : null}
diff --git a/static/app/views/preprod/components/installModal.tsx b/static/app/views/preprod/components/installModal.tsx
index 0eb362e2b286ae..32e32d0908bb9e 100644
--- a/static/app/views/preprod/components/installModal.tsx
+++ b/static/app/views/preprod/components/installModal.tsx
@@ -11,6 +11,7 @@ import LoadingIndicator from 'sentry/components/loadingIndicator';
import {IconClose} from 'sentry/icons/iconClose';
import {t, tn} from 'sentry/locale';
import {space} from 'sentry/styles/space';
+import {MarkedText} from 'sentry/utils/marked/markedText';
import {useApiQuery} from 'sentry/utils/queryClient';
import useOrganization from 'sentry/utils/useOrganization';
import type {InstallDetailsApiResponse} from 'sentry/views/preprod/types/installDetailsTypes';
@@ -39,33 +40,71 @@ function InstallModal({projectId, artifactId, closeModal}: InstallModalProps) {
}
);
+ const header = (
+
+ {t('Install App')}
+
+ }
+ size="sm"
+ aria-label={t('Close')}
+ />
+
+
+ );
+
if (isPending) {
return (
-
+
+ {header}
{t('Loading install details...')}
);
}
- if (isError) {
+ if (isError || !installDetails) {
return (
-
+
+ {header}
{t('Error: %s', error?.message || 'Failed to fetch install details')}
-
);
}
- if (!installDetails?.install_url) {
- const message = installDetails
- ? t('No install download link available')
- : t('No install details available');
+ if (!installDetails.install_url) {
+ if (!installDetails.is_code_signature_valid) {
+ let errors = null;
+ if (
+ installDetails.code_signature_errors &&
+ installDetails.code_signature_errors.length > 0
+ ) {
+ errors = (
+
+ {installDetails.code_signature_errors.map(e => (
+ {e}
+ ))}
+
+ );
+ }
+ return (
+
+ {header}
+ {'Code signature is invalid'}
+ {errors}
+
+ );
+ }
return (
-
- {message}
-
+
+ {header}
+ {t('No install download link available')}
);
}
@@ -89,21 +128,7 @@ function InstallModal({projectId, artifactId, closeModal}: InstallModalProps) {
return (
-
- {t('Install App')}
-
- }
- size="sm"
- aria-label={t('Close')}
- />
-
-
+ {header}
@@ -152,6 +177,14 @@ function InstallModal({projectId, artifactId, closeModal}: InstallModalProps) {
{t('The install link will expire in 12 hours')}
+ {installDetails.release_notes && (
+
+ {t('Release Notes')}
+
+
+
+
+ )}
@@ -168,6 +201,9 @@ export const CodeSignatureInfo = styled('div')`
background: ${p => p.theme.backgroundSecondary};
border-radius: ${space(1)};
border: 1px solid ${p => p.theme.border};
+ max-width: 100%;
+ word-break: break-word;
+ overflow-wrap: break-word;
`;
const Divider = styled(Flex)`
@@ -195,6 +231,19 @@ const Divider = styled(Flex)`
}
`;
+const ReleaseNotesSection = styled(Flex)`
+ width: 100%;
+ margin-top: ${p => p.theme.space.xl};
+`;
+
+const ReleaseNotesContent = styled('div')`
+ width: 100%;
+ padding: ${p => p.theme.space.xl};
+ background: ${p => p.theme.backgroundSecondary};
+ border-radius: ${p => p.theme.space.md};
+ border: 1px solid ${p => p.theme.border};
+`;
+
export function openInstallModal(projectId: string, artifactId: string) {
openModal(
({closeModal}) => (
diff --git a/static/app/views/preprod/types/installDetailsTypes.ts b/static/app/views/preprod/types/installDetailsTypes.ts
index 7e39abcce0e11c..36d402b9bac23a 100644
--- a/static/app/views/preprod/types/installDetailsTypes.ts
+++ b/static/app/views/preprod/types/installDetailsTypes.ts
@@ -8,4 +8,5 @@ export interface InstallDetailsApiResponse {
install_url?: string;
is_code_signature_valid?: boolean;
profile_name?: string;
+ release_notes?: string;
}