Path: blob/main/components/dashboard/src/prebuilds/detail/PrebuildTaskTab.tsx
2501 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 type { Prebuild } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb";7import { Suspense, memo, useEffect } from "react";8import { usePrebuildLogsEmitter } from "../../data/prebuilds/prebuild-logs-emitter";9import React from "react";10import { useToast } from "../../components/toasts/Toasts";11import { ApplicationError, ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error";12import { TabsContent } from "@podkit/tabs/Tabs";13import { PrebuildTaskErrorTab } from "./PrebuildTaskErrorTab";14import type { PlainMessage } from "@bufbuild/protobuf";15import { useHistory } from "react-router";16import { LoadingState } from "@podkit/loading/LoadingState";1718const WorkspaceLogs = React.lazy(() => import("../../components/WorkspaceLogs"));1920type Props = {21taskId: string;22prebuild: PlainMessage<Prebuild>;23};24export const PrebuildTaskTab = memo(({ taskId, prebuild }: Props) => {25const { emitter: logEmitter } = usePrebuildLogsEmitter(prebuild, taskId);26const [error, setError] = React.useState<ApplicationError | undefined>();27const { toast, dismissToast } = useToast();28const [activeToasts, setActiveToasts] = React.useState<Set<string>>(new Set());29const history = useHistory();3031useEffect(() => {32const logErrorListener = async (err: ApplicationError) => {33if (err.code === ErrorCodes.NOT_FOUND) {34setError(err);35return;36}3738const digest = await crypto.subtle.digest("sha256", new TextEncoder().encode(err.message + ":" + err.code));39const toastId = new TextDecoder().decode(digest);40toast("Fetching logs failed: " + err.message, { autoHide: false, id: toastId });41setActiveToasts((prev) => new Set(prev).add(toastId));42};4344logEmitter.on("logs-error", logErrorListener);4546return () => {47logEmitter.removeListener("logs-error", logErrorListener);48setError(undefined);49};50}, [logEmitter, taskId, toast]);5152useEffect(() => {53// When navigating away from the page, dismiss all toasts54history.listen(() => {55activeToasts.forEach((toastId) => {56dismissToast(toastId);57});58});59// eslint-disable-next-line react-hooks/exhaustive-deps60}, []);6162if (error) {63if (error.code === ErrorCodes.NOT_FOUND && taskId === "image-build") {64return (65<PrebuildTaskErrorTab taskId={taskId}>66<span className="flex justify-center items-center gap-2">67Pulling container image <LoadingState delay={false} size={16} />68</span>69</PrebuildTaskErrorTab>70);71}7273return (74<PrebuildTaskErrorTab taskId={taskId}>75Logs of this prebuild task are inaccessible. Use <code>gp validate --prebuild --headless</code> in a76workspace to see logs and debug prebuild issues.{" "}77<a78href="https://www.gitpod.io/docs/configure/workspaces#validate-your-gitpod-configuration"79target="_blank"80rel="noreferrer noopener"81className="gp-link"82>83Learn more84</a>85.86</PrebuildTaskErrorTab>87);88}8990return (91<TabsContent value={taskId} className="h-112 mt-0 border-pk-border-base">92<Suspense fallback={<div />}>93<WorkspaceLogs94key={prebuild.id + taskId}95classes="w-full h-full"96xtermClasses="absolute top-0 left-0 bottom-0 right-0 ml-6 my-0 mt-4"97taskId={taskId}98logsEmitter={logEmitter}99/>100</Suspense>101</TabsContent>102);103});104105106