From 510afa3ccce32404a19921779f8eba59ee1d3f94 Mon Sep 17 00:00:00 2001 From: Gabriel Le Breton Date: Tue, 24 Oct 2023 12:58:34 -0400 Subject: [PATCH 1/5] Fix Versions page closes #410, credits to EliasVal <3 Original author: https://github.com/EliasVal See https://github.com/game-ci/documentation/pull/412 --- .../versions/builds/build-failure-details.tsx | 93 +++++++++++++++++++ .../docs/versions/builds/build-row.tsx | 88 ++++++++++++++++++ .../docs/versions/builds/builds.module.scss | 22 +++++ .../docs/versions/builds/builds.tsx | 62 +++++++++++++ src/components/docs/versions/date-time.tsx | 11 ++- .../docker-image-link-or-retry-button.tsx | 40 ++++---- .../docs/versions/docker-image-link.tsx | 26 +++--- .../docs/versions/image-versions.tsx | 20 ++-- .../docs/versions/major-editor-version.tsx | 36 +++++++ .../docs/versions/unity-version.module.scss | 46 +++++++++ .../docs/versions/unity-version.tsx | 71 +++++++++----- .../docs/versions/unity-versions.tsx | 47 ++++++---- .../molecules/tooltip/tooltip.module.scss | 20 ++++ src/components/molecules/tooltip/tooltip.tsx | 18 ++++ 14 files changed, 520 insertions(+), 80 deletions(-) create mode 100644 src/components/docs/versions/builds/build-failure-details.tsx create mode 100644 src/components/docs/versions/builds/build-row.tsx create mode 100644 src/components/docs/versions/builds/builds.module.scss create mode 100644 src/components/docs/versions/builds/builds.tsx create mode 100644 src/components/docs/versions/major-editor-version.tsx create mode 100644 src/components/molecules/tooltip/tooltip.module.scss create mode 100644 src/components/molecules/tooltip/tooltip.tsx diff --git a/src/components/docs/versions/builds/build-failure-details.tsx b/src/components/docs/versions/builds/build-failure-details.tsx new file mode 100644 index 00000000..860e7a78 --- /dev/null +++ b/src/components/docs/versions/builds/build-failure-details.tsx @@ -0,0 +1,93 @@ +import React, { useReducer } from 'react'; +import CodeBlock from '@theme/CodeBlock'; + +interface Props { + ciJob; + ciBuild; + repoVersionInfo; + editorVersionInfo; + style; +} + +const BuildFailureDetails = ({ + ciJob, + repoVersionInfo, + editorVersionInfo, + ciBuild, + ...rest +}: Props) => { + const { editorVersion, baseOs, targetPlatform } = ciBuild.buildInfo; + const { major, minor, patch } = repoVersionInfo; + + const reducer = (state, action) => { + const { tag, value } = action; + return { ...state, [tag]: value }; + }; + + const [tags /* , dispatch */] = useReducer(reducer, { + [`${baseOs}-${editorVersion}-${targetPlatform}-${major}`]: '❓', + [`${baseOs}-${editorVersion}-${targetPlatform}-${major}.${minor}`]: '❓', + [`${baseOs}-${editorVersion}-${targetPlatform}-${major}.${minor}.${patch}`]: '❓', + [`${editorVersion}-${targetPlatform}-${major}`]: '❓', + [`${editorVersion}-${targetPlatform}-${major}.${minor}`]: '❓', + [`${editorVersion}-${targetPlatform}-${major}.${minor}.${patch}`]: '❓', + }); + + // Todo - fetch docker info from dockerhub for all tags, or do it on the server + // useEffect(() => { + // (async () => { + // const repo = 'unityci/editor'; + // for (const tag of Object.keys(tags)) { + // const requestUrl = `https://index.docker.io/v1/repositories/${repo}/tags/${tag}`; + // try { + // const response = await fetch(requestUrl); + // dispatch({ tag, value: response.status === 0 }); + // } catch (error) { + // dispatch({ tag, value: false }); + // } + // } + // })(); + // }, []); + + const { changeSet } = editorVersionInfo; + const buildCommand = `#!/usr/bin/env bash +git clone git@github.com:game-ci/docker.git +cd docker + +editor_version=${editorVersion} +change_set=${changeSet} +base_os=${baseOs} +target_platform=${targetPlatform} +image_name=unityci-editor:$editor_version-$target_platform + +docker build . \\ + --file ./images/$base_os/editor/Dockerfile \\ + -t $image_name \\ + --build-arg=version=$editor_version \\ + --build-arg=changeSet=$change_set \\ + --build-arg=module=$target_platform +`; + + const pullCommand = `docker pull unityci/editor:${baseOs}-${editorVersion}-${targetPlatform}-${major}.${minor}.${patch}`; + + return ( +
+

CI Job identification

+ {JSON.stringify(ciJob, null, 2)} +
+

Commands

+

Build the docker image locally for debugging:

+ {buildCommand} +

Pull this docker image:

+ {pullCommand} +
+

Associated tags on docker hub

+ {JSON.stringify(tags, null, 2)} +
+

CI Build details

+ {JSON.stringify(ciBuild, null, 2)} +
+ ); +}; + +export default BuildFailureDetails; diff --git a/src/components/docs/versions/builds/build-row.tsx b/src/components/docs/versions/builds/build-row.tsx new file mode 100644 index 00000000..999f35e1 --- /dev/null +++ b/src/components/docs/versions/builds/build-row.tsx @@ -0,0 +1,88 @@ +import React, { useState } from 'react'; +import DockerImageLinkOrRetryButton, { + type Record, +} from '@site/src/components/docs/versions/docker-image-link-or-retry-button'; +import Spinner from '@site/src/components/molecules/spinner'; +import Tooltip from '@site/src/components/molecules/tooltip/tooltip'; +import styles from './builds.module.scss'; + +const mapBuildStatusToIcon = { + started: , + failed: '⚠', + published: '✅', +}; + +type Props = { + children: React.JSX.Element | React.JSX.Element[]; + build: Record; +}; + +const CopyToClipboard = (copyString: string) => { + navigator.clipboard.writeText(copyString); +}; + +export default function BuildRow({ children, build }: Props) { + const [expanded, setExpanded] = useState(false); + const [toolbarContent, setToolbarContent] = useState('Click to copy'); + + const MapBuildStatusToElement = (status: string) => { + const icon = mapBuildStatusToIcon[status]; + + switch (status) { + case 'started': + return ; + case 'failed': + return {icon}; + case 'published': + return icon; + default: + return status; + } + }; + + return ( + <> + + setExpanded(!expanded)} + className="text-center select-none cursor-pointer" + > + {expanded ? '➖' : '➕'} + + {MapBuildStatusToElement(build.status)} + + + {/* */} + + + + + {/* */} + + + + {build.imageType} + {build.buildInfo.baseOs} + {build.buildInfo.targetPlatform} + + {expanded && ( + + {children} + + )} + + ); +} diff --git a/src/components/docs/versions/builds/builds.module.scss b/src/components/docs/versions/builds/builds.module.scss new file mode 100644 index 00000000..9256dab7 --- /dev/null +++ b/src/components/docs/versions/builds/builds.module.scss @@ -0,0 +1,22 @@ +.stickyRow:global(.ant-table-row.ant-table-row-level-0) > :global(td) { + position: sticky; + top: 99px; /* height of the collapse-item-header + the parent tr > td sticky */ + background-color: rgb(255, 255, 255); + z-index: 2; + box-shadow: 0 0 25px rgba(255,255,255,1), 0 0 15px rgba(255,255,255,1), 0 0 20px rgba(255,255,255,1); + clip-path: inset(-25px 0 0 0); +} + +.stickyRow:global(.ant-table-row.ant-table-row-level-0) > :global(td:not(:last-child)) { + clip-path: inset(-25px -1px 0 0); /* fix for space from responsive vs fixed width on cells */ +} + +.expandedContentRow { + height: 0; + overflow: hidden; +} + + +.tableRow { + width: 100%; +} diff --git a/src/components/docs/versions/builds/builds.tsx b/src/components/docs/versions/builds/builds.tsx new file mode 100644 index 00000000..64e2f9ef --- /dev/null +++ b/src/components/docs/versions/builds/builds.tsx @@ -0,0 +1,62 @@ +import React from 'react'; +import { useFirestore, useFirestoreCollectionData } from 'reactfire'; +import BuildFailureDetails from '@site/src/components/docs/versions/builds/build-failure-details'; +import styles from './builds.module.scss'; +import BuildRow from './build-row'; +import { Record } from '../docker-image-link-or-retry-button'; + +interface RepoVersionInfo { + version: string; + major: number; + minor: number; + patch: number; +} + +interface Props { + ciJobId: string; + repoVersionInfo: RepoVersionInfo; + editorVersionInfo; +} + +const Builds = ({ ciJobId, repoVersionInfo, editorVersionInfo }: Props) => { + const loading =

Fetching builds...

; + + const ciBuilds = useFirestore().collection('ciBuilds').where('relatedJobId', '==', ciJobId); + + const { status, data } = useFirestoreCollectionData<{ [key: string]: any }>(ciBuilds); + const isLoading = status === 'loading'; + + if (isLoading) { + return loading; + } + + const expandable = { + expandedRowRender: (record) => ( + + ), + }; + + return ( + + + + + + + + + + {data.map((build: Record) => ( + {expandable.expandedRowRender(build)} + ))} +
StatusBuild IDImage typeOSTarget Platform
+ ); +}; + +export default Builds; diff --git a/src/components/docs/versions/date-time.tsx b/src/components/docs/versions/date-time.tsx index 58e243a4..212cafb7 100644 --- a/src/components/docs/versions/date-time.tsx +++ b/src/components/docs/versions/date-time.tsx @@ -1,4 +1,5 @@ import React from 'react'; +import Tooltip from '../../molecules/tooltip/tooltip'; interface Props { utcSeconds: number; @@ -10,8 +11,8 @@ const options: Intl.DateTimeFormatOptions = { day: 'numeric', hour: 'numeric', minute: 'numeric', - second: 'numeric', timeZoneName: 'short', + hour12: true, }; const DateTime = ({ utcSeconds }: Props) => { @@ -19,7 +20,13 @@ const DateTime = ({ utcSeconds }: Props) => { date.setUTCSeconds(utcSeconds); - return {`${date.toLocaleString('en-GB', options)}`}; + return ( + + + ( ... ) + + + ); }; export default DateTime; 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 bbd02291..544747a1 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,4 +1,3 @@ -import { Tooltip } from 'antd'; import React, { useState } from 'react'; import { HiOutlineRefresh } from 'react-icons/hi'; import { SimpleAuthCheck } from '@site/src/components/auth/safe-auth-check'; @@ -6,25 +5,32 @@ import DockerImageLink from '@site/src/components/docs/versions/docker-image-lin import { useAuthenticatedEndpoint } from '@site/src/core/hooks/use-authenticated-endpoint'; import { useNotification } from '@site/src/core/hooks/use-notification'; import Spinner from '@site/src/components/molecules/spinner'; +import Tooltip from '@site/src/components/molecules/tooltip/tooltip'; -interface Props { - record: { - buildId: string; - relatedJobId: string; - buildInfo: { - baseOs: string; - editorVersion: string; - targetPlatform: string; - repoVersion: string; - }; - dockerInfo: { - imageRepo: string; - imageName: string; - }; - status: string; +type Record = { + buildId: string; + relatedJobId: string; + buildInfo: { + baseOs: string; + editorVersion: string; + targetPlatform: string; + repoVersion: string; + }; + dockerInfo: { + digest: string; + imageRepo: string; + imageName: string; }; + status: string; + [key: string]: any; +}; + +interface Props { + record: Record; } +export { Record }; + const DockerImageLinkOrRetryButton = ({ record }: Props) => { const { buildInfo, dockerInfo, buildId, relatedJobId, status } = record; const { baseOs, editorVersion, targetPlatform, repoVersion } = buildInfo; @@ -55,7 +61,7 @@ const DockerImageLinkOrRetryButton = ({ record }: Props) => { return ( } requiredClaims={{ admin: true }}> - +