diff --git a/src/components/docs/versions/builds/build-row.tsx b/src/components/docs/versions/builds/build-row.tsx index 79bd02a2..738d422e 100644 --- a/src/components/docs/versions/builds/build-row.tsx +++ b/src/components/docs/versions/builds/build-row.tsx @@ -31,8 +31,11 @@ export default function BuildRow({ children, build }: Props) { switch (status) { case 'started': return ; - case 'failed': - return {icon}; + case 'failed': { + const failureCount = build.meta?.failureCount || 0; + const label = failureCount >= 15 ? `${icon} (${failureCount}/15)` : icon; + return {label}; + } case 'published': return icon; default: diff --git a/src/components/docs/versions/docker-image-link-or-retry-button.tsx b/src/components/docs/versions/docker-image-link-or-retry-button.tsx index 6e52f5e0..1171da91 100644 --- a/src/components/docs/versions/docker-image-link-or-retry-button.tsx +++ b/src/components/docs/versions/docker-image-link-or-retry-button.tsx @@ -1,5 +1,6 @@ import React, { useState } from 'react'; import { HiOutlineRefresh } from 'react-icons/hi'; +import { MdRestartAlt } from 'react-icons/md'; import { SimpleAuthCheck } from '@site/src/components/auth/safe-auth-check'; import DockerImageLink from '@site/src/components/docs/versions/docker-image-link'; import { useAuthenticatedEndpoint } from '@site/src/core/hooks/use-authenticated-endpoint'; @@ -21,6 +22,9 @@ type Record = { imageRepo: string; imageName: string; }; + meta?: { + failureCount?: number; + }; status: string; [key: string]: any; }; @@ -32,21 +36,23 @@ interface Props { export { Record }; const DockerImageLinkOrRetryButton = ({ record }: Props) => { - const { buildInfo, dockerInfo, buildId, relatedJobId, status } = record; + const { buildInfo, dockerInfo, buildId, relatedJobId, status, meta } = record; const { baseOs, editorVersion, targetPlatform, repoVersion } = buildInfo; const { imageRepo, imageName } = dockerInfo || {}; const imageTag = `${baseOs}-${editorVersion}-${targetPlatform}-${repoVersion}`; const [retryRequested, setRetryRequested] = useState(false); + const [resetRequested, setResetRequested] = useState(false); const notify = useNotification(); const retryBuild = useAuthenticatedEndpoint('retryBuild', { buildId, relatedJobId }); + const resetBuild = useAuthenticatedEndpoint('resetFailedBuilds', { buildId }); // Also show the retry button when the build has been sent to `failed` manually. if (dockerInfo && status !== 'failed') { return ; } - const onClick = async () => { + const onRetryClick = async () => { try { setRetryRequested(true); await notify.promise(retryBuild(), { @@ -59,17 +65,39 @@ const DockerImageLinkOrRetryButton = ({ record }: Props) => { } }; + const onResetClick = async () => { + try { + setResetRequested(true); + await notify.promise(resetBuild(), { + loading: , + success: (response) => response.message, + error: (error) => error.message, + }); + } catch { + setResetRequested(false); + } + }; + + const failureCount = meta?.failureCount || 0; + const isMaxedOut = failureCount >= 15; + const buttonStyle = { padding: 0, border: 0, outline: 0, cursor: 'pointer' }; + return ( } requiredClaims={{ admin: true }}> - + {isMaxedOut && ( + + + + )} ); };