Skip to content

Commit

Permalink
[public-api] migrate PrebuildService
Browse files Browse the repository at this point in the history
  • Loading branch information
akosyakov committed Nov 12, 2023
1 parent 5c70155 commit ccd31b6
Show file tree
Hide file tree
Showing 17 changed files with 3,228 additions and 183 deletions.
44 changes: 19 additions & 25 deletions components/dashboard/src/components/PrebuildLogs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import {
WorkspaceImageBuild,
HEADLESS_LOG_STREAM_STATUS_CODE_REGEX,
Disposable,
PrebuildWithStatus,
} from "@gitpod/gitpod-protocol";
import { getGitpodService } from "../service/service";
import { PrebuildStatus } from "../projects/Prebuilds";
import { converter, workspaceClient } from "../service/public-api";
import { converter, watchPrebuild, workspaceClient } from "../service/public-api";
import { GetWorkspaceRequest, WorkspacePhase_Phase } from "@gitpod/public-api/lib/gitpod/v1/workspace_pb";
import { Prebuild, Prebuild_Status } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb";

const WorkspaceLogs = React.lazy(() => import("./WorkspaceLogs"));

Expand All @@ -37,15 +37,18 @@ export default function PrebuildLogs(props: PrebuildLogsProps) {
>();
const [error, setError] = useState<Error | undefined>();
const [logsEmitter] = useState(new EventEmitter());
const [prebuild, setPrebuild] = useState<PrebuildWithStatus | undefined>();
const [prebuild, setPrebuild] = useState<Prebuild | undefined>();

const handlePrebuildUpdate = useCallback(
(prebuild: PrebuildWithStatus) => {
if (prebuild.info.buildWorkspaceId === props.workspaceId) {
(prebuild: Prebuild) => {
if (prebuild.buildWorkspaceId === props.workspaceId) {
setPrebuild(prebuild);

// In case the Prebuild got "aborted" or "time(d)out" we want to user to proceed anyway
if (props.onIgnorePrebuild && (prebuild.status === "aborted" || prebuild.status === "timeout")) {
if (
props.onIgnorePrebuild &&
(prebuild.status === Prebuild_Status.ABORTED || prebuild.status === Prebuild_Status.TIMEOUT)
) {
props.onIgnorePrebuild();
}
// TODO(gpl) We likely want to move the "happy path" logic (for status "available")
Expand Down Expand Up @@ -78,20 +81,6 @@ export default function PrebuildLogs(props: PrebuildLogsProps) {
setError(err);
}

// Try get hold of a recent Prebuild
try {
const pbws = await getGitpodService().server.findPrebuildByWorkspaceID(props.workspaceId);
if (pbws) {
const foundPrebuild = await getGitpodService().server.getPrebuild(pbws.id);
if (foundPrebuild) {
handlePrebuildUpdate(foundPrebuild);
}
}
} catch (err) {
console.error(err);
setError(err);
}

// Register for future updates
disposables.push(
getGitpodService().registerClient({
Expand All @@ -112,13 +101,18 @@ export default function PrebuildLogs(props: PrebuildLogsProps) {
}
logsEmitter.emit("logs", content.text);
},
onPrebuildUpdate(update: PrebuildWithStatus) {
if (update.info) {
handlePrebuildUpdate(update);
}
},
}),
);
disposables.push(
Disposable.create(() =>
watchPrebuild(
{
workspaceId: props.workspaceId,
},
handlePrebuildUpdate,
),
),
);
})();
return function cleanup() {
disposables.dispose();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,27 @@
* See License.AGPL.txt in the project root for license information.
*/

import { PrebuildWithStatus } from "@gitpod/gitpod-protocol";
import { useQuery } from "@tanstack/react-query";
import { getGitpodService } from "../../service/service";

export type LatestProjectPrebuildQueryResult = PrebuildWithStatus;
import { prebuildClient } from "../../service/public-api";
import { Prebuild } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb";

type Args = {
projectId: string;
};
export const useLatestProjectPrebuildQuery = ({ projectId }: Args) => {
return useQuery<LatestProjectPrebuildQueryResult>({
return useQuery<Prebuild>({
queryKey: getLatestProjectPrebuildQueryKey(projectId),
// Prevent bursting for latest project prebuilds too frequently
staleTime: 1000 * 60 * 1, // 1 minute
queryFn: async () => {
const latestPrebuilds = await getGitpodService().server.findPrebuilds({
projectId,
latest: true,
const response = await prebuildClient.listPrebuilds({
configurationId: projectId,
pagination: {
page: 1,
pageSize: 1,
},
});

return latestPrebuilds[0] || null;
return response.prebuilds[0] || null;
},
});
};
Expand Down
67 changes: 31 additions & 36 deletions components/dashboard/src/projects/Prebuild.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,90 +4,77 @@
* See License.AGPL.txt in the project root for license information.
*/

import { PrebuildWithStatus } from "@gitpod/gitpod-protocol";
import dayjs from "dayjs";
import { useEffect, useMemo, useState } from "react";
import { Redirect, useHistory, useParams } from "react-router";
import Header from "../components/Header";
import PrebuildLogs from "../components/PrebuildLogs";
import { Subheading } from "../components/typography/headings";
import Spinner from "../icons/Spinner.svg";
import { getGitpodService, gitpodHostUrl } from "../service/service";
import { gitpodHostUrl } from "../service/service";
import { useCurrentProject } from "./project-context";
import { shortCommitMessage } from "./render-utils";
import { prebuildClient, watchPrebuild } from "../service/public-api";
import { Prebuild, Prebuild_Status } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb";

export default function PrebuildPage() {
const history = useHistory();
const { project, loading } = useCurrentProject();

const { prebuildId } = useParams<{ prebuildId: string }>();

const [prebuild, setPrebuild] = useState<PrebuildWithStatus | undefined>();
const [prebuild, setPrebuild] = useState<Prebuild | undefined>();
const [isRerunningPrebuild, setIsRerunningPrebuild] = useState<boolean>(false);
const [isCancellingPrebuild, setIsCancellingPrebuild] = useState<boolean>(false);

useEffect(() => {
if (!project || !prebuildId) {
return;
}
(async () => {
const prebuilds = await getGitpodService().server.findPrebuilds({
projectId: project.id,
prebuildId,
});
setPrebuild(prebuilds[0]);
})();

return getGitpodService().registerClient({
onPrebuildUpdate(update: PrebuildWithStatus) {
if (update.info.id !== prebuildId) {
return;
}

setPrebuild(update);
},
}).dispose;
return watchPrebuild({ prebuildId }, (prebuild) => setPrebuild(prebuild));
}, [prebuildId, project]);

const title = useMemo(() => {
if (!prebuild) {
return "unknown prebuild";
}
return prebuild.info.branch;
return prebuild.branch;
}, [prebuild]);

const renderSubtitle = () => {
if (!prebuild) {
return "";
}
const startedByAvatar = prebuild.info.startedByAvatar && (
const startedByAvatar = prebuild.startedBy && (
<img
className="rounded-full w-4 h-4 inline-block align-text-bottom mr-2"
src={prebuild.info.startedByAvatar || ""}
alt={prebuild.info.startedBy}
src={prebuild.startedBy.avatarUrl}
alt={prebuild.startedBy.name}
/>
);
return (
<div className="flex">
<div className="my-auto">
<Subheading>
{startedByAvatar}Triggered {dayjs(prebuild.info.startedAt).fromNow()}
{startedByAvatar}Triggered {dayjs(prebuild.startTime?.toDate()).fromNow()}
</Subheading>
</div>
<p className="mx-2 my-auto">·</p>
<div className="my-auto">
<p className="text-gray-500 dark:text-gray-50">{shortCommitMessage(prebuild.info.changeTitle)}</p>
<p className="text-gray-500 dark:text-gray-50">
{shortCommitMessage(prebuild.commit?.message || "")}
</p>
</div>
{!!prebuild.info.basedOnPrebuildId && (
{!!prebuild.basedOnPrebuildId && (
<>
<p className="mx-2 my-auto">·</p>
<div className="my-auto">
<p className="text-gray-500 dark:text-gray-50">
Incremental Prebuild (
<a
className="gp-link"
title={prebuild.info.basedOnPrebuildId}
href={`./${prebuild.info.basedOnPrebuildId}`}
title={prebuild.basedOnPrebuildId}
href={`./${prebuild.basedOnPrebuildId}`}
>
base
</a>
Expand All @@ -106,7 +93,10 @@ export default function PrebuildPage() {
}
try {
setIsRerunningPrebuild(true);
await getGitpodService().server.triggerPrebuild(prebuild.info.projectId, prebuild.info.branch);
await prebuildClient.startPrebuild({
configurationId: prebuild.configurationId,
branch: prebuild.branch,
});
// TODO: Open a Prebuilds page that's specific to `prebuild.info.branch`?
if (project) {
history.push(`/projects/${project.id}/prebuilds`);
Expand All @@ -124,7 +114,10 @@ export default function PrebuildPage() {
}
try {
setIsCancellingPrebuild(true);
await getGitpodService().server.cancelPrebuild(prebuild.info.projectId, prebuild.info.id);
await prebuildClient.stopPrebuild({
prebuildId: prebuild.id,
configurationId: prebuild.configurationId,
});
} catch (error) {
console.error("Could not cancel prebuild", error);
} finally {
Expand All @@ -140,8 +133,10 @@ export default function PrebuildPage() {
<>
<Header title={title} subtitle={renderSubtitle()} />
<div className="app-container mt-8">
<PrebuildLogs workspaceId={prebuild?.info?.buildWorkspaceId}>
{["building", "queued"].includes(prebuild?.status || "") ? (
<PrebuildLogs workspaceId={prebuild?.buildWorkspaceId}>
{[Prebuild_Status.BUILDING, Prebuild_Status.QUEUED].includes(
prebuild?.status || Prebuild_Status.UNSPECIFIED,
) ? (
<button
className="danger flex items-center space-x-2"
disabled={isCancellingPrebuild}
Expand All @@ -162,13 +157,13 @@ export default function PrebuildPage() {
{isRerunningPrebuild && (
<img alt="" className="h-4 w-4 animate-spin filter brightness-150" src={Spinner} />
)}
<span>Rerun Prebuild ({prebuild?.info.branch})</span>
<span>Rerun Prebuild ({prebuild?.branch})</span>
</button>
{prebuild?.status === "available" ? (
{prebuild?.status === Prebuild_Status.AVAILABLE ? (
<a
className="my-auto"
href={gitpodHostUrl
.withContext(`open-prebuild/${prebuild?.info.id}/${prebuild?.info.changeUrl}`)
.withContext(`open-prebuild/${prebuild?.id}/${prebuild?.url}`)
.toString()}
>
<button>New Workspace (with this prebuild)</button>
Expand Down
Loading

0 comments on commit ccd31b6

Please sign in to comment.