Path: blob/main/components/dashboard/src/projects/prebuild-utils.tsx
2500 views
/**1* Copyright (c) 2024 Gitpod GmbH. All rights reserved.2* Licensed under the GNU Affero General Public License (AGPL).3* See License.AGPL.txt in the project root for license information.4*/56import { Prebuild, PrebuildPhase_Phase } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb";7import { PauseCircle, LucideProps, Clock, CheckCircle2, XCircle, Loader2Icon } from "lucide-react";8import type { ForwardRefExoticComponent } from "react";9import { cn } from "@podkit/lib/cn";1011import StatusDone from "../icons/StatusDone.svg";12import StatusFailed from "../icons/StatusFailed.svg";13import StatusCanceled from "../icons/StatusCanceled.svg";14import StatusPaused from "../icons/StatusPaused.svg";15import StatusRunning from "../icons/StatusRunning.svg";1617export function PrebuildStatus(p: { prebuild: Prebuild | undefined; classname?: string }) {18const prebuild = p.prebuild;1920const { className: iconColorClass, label } = prebuildDisplayProps(prebuild);21const PrebuildStatusIcon = prebuildStatusIconComponent(prebuild);22return (23<div className="flex flex-row gap-1.5 items-center capitalize">24<PrebuildStatusIcon className={cn(p.classname, iconColorClass)} />25<span>{label}</span>26</div>27);28}2930export function PrebuildStatusOld(props: { prebuild: Prebuild | undefined }) {31const prebuild = props.prebuild;3233return (34<div className="flex flex-col space-y-1 justify-center text-sm font-semibold">35<div>36<div className="flex space-x-1 items-center">37{prebuildStatusIcon(prebuild)}38{prebuildStatusLabel(prebuild)}39</div>40</div>41<div className="flex space-x-1 items-center text-gray-400">42<span className="text-left">{getPrebuildStatusDescription(prebuild)}</span>43</div>44</div>45);46}4748const prebuildDisplayProps = (prebuild: Prebuild | undefined): { className: string; label: string } => {49switch (prebuild?.status?.phase?.name) {50case undefined: // Fall through51case PrebuildPhase_Phase.UNSPECIFIED: // Fall through52case PrebuildPhase_Phase.QUEUED:53return { className: "text-orange-500", label: "pending" };54case PrebuildPhase_Phase.BUILDING:55return { className: "text-blue-500", label: "running" };56case PrebuildPhase_Phase.ABORTED:57return { className: "text-gray-500", label: "cancelled" };58case PrebuildPhase_Phase.FAILED:59return { className: "text-red-500", label: "error" };60case PrebuildPhase_Phase.TIMEOUT:61return { className: "text-red-500", label: "timeout" };62case PrebuildPhase_Phase.AVAILABLE:63if (prebuild.status?.message) {64return { className: "text-red-500", label: "failed" };65}66return { className: "text-green-500", label: "ready" };67}6869return { className: "", label: "" };70};7172export const prebuildStatusLabel = (prebuild: Prebuild | undefined): JSX.Element => {73const { className, label } = prebuildDisplayProps(prebuild);74return <span className={`font-medium ${className} uppercase`}>{label}</span>;75};7677const prebuildStatusIconComponent = (prebuild: Prebuild | undefined): ForwardRefExoticComponent<LucideProps> => {78switch (prebuild?.status?.phase?.name) {79case PrebuildPhase_Phase.UNSPECIFIED: // Fall through80case PrebuildPhase_Phase.QUEUED:81return PauseCircle;82case PrebuildPhase_Phase.BUILDING:83return Clock;84case PrebuildPhase_Phase.ABORTED:85case PrebuildPhase_Phase.TIMEOUT:86case PrebuildPhase_Phase.FAILED:87return XCircle;88case PrebuildPhase_Phase.AVAILABLE:89if (prebuild?.status?.message) {90return XCircle;91}92return CheckCircle2;93}9495return XCircle;96};9798export const prebuildStatusIcon = (prebuild?: Prebuild) => {99if (!prebuild) {100return <Loader2Icon size={20} className="text-gray-500 animate-spin" />;101}102103switch (prebuild?.status?.phase?.name) {104case PrebuildPhase_Phase.UNSPECIFIED: // Fall through105case PrebuildPhase_Phase.QUEUED:106return <img alt="" className="h-4 w-4" src={StatusPaused} />;107case PrebuildPhase_Phase.BUILDING:108return <img alt="" className="h-4 w-4" src={StatusRunning} />;109case PrebuildPhase_Phase.ABORTED:110return <img alt="" className="h-4 w-4" src={StatusCanceled} />;111case PrebuildPhase_Phase.FAILED:112return <img alt="" className="h-4 w-4" src={StatusFailed} />;113case PrebuildPhase_Phase.TIMEOUT:114return <img alt="" className="h-4 w-4" src={StatusFailed} />;115case PrebuildPhase_Phase.AVAILABLE:116if (prebuild?.status?.message) {117return <img alt="" className="h-4 w-4" src={StatusFailed} />;118}119return <img alt="" className="h-4 w-4" src={StatusDone} />;120}121};122123const getPrebuildStatusDescription = (prebuild: Prebuild | undefined): string => {124switch (prebuild?.status?.phase?.name) {125case PrebuildPhase_Phase.QUEUED:126return `Prebuild is queued and will be processed when there is execution capacity.`;127case PrebuildPhase_Phase.BUILDING:128return `Prebuild is currently in progress.`;129case PrebuildPhase_Phase.ABORTED:130return `Prebuild has been cancelled. Either a newer commit was pushed to the same branch, a user cancelled it manually, or the prebuild rate limit has been exceeded. ${131prebuild.status?.message || ""132}`;133case PrebuildPhase_Phase.FAILED:134return `Prebuild failed for system reasons. Please contact support. ${prebuild.status?.message || ""}`;135case PrebuildPhase_Phase.TIMEOUT:136return `Prebuild timed out. Either the image, or the prebuild tasks took too long. ${137prebuild.status?.message || ""138}`;139case PrebuildPhase_Phase.AVAILABLE:140if (prebuild.status?.message) {141return `The tasks executed in the prebuild returned a non-zero exit code. ${prebuild.status.message}`;142}143return `Prebuild completed successfully.`;144default:145return `Unknown prebuild status.`;146}147};148149150