From 698b1a33e485e0268981002eeaf7c4bcd4e31546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Wed, 24 Jan 2024 22:35:22 +0000 Subject: [PATCH 01/49] Init prebuilds list --- components/dashboard/src/app/AppRoutes.tsx | 4 + .../configurations/configuration-queries.ts | 2 +- .../prebuilds/organization-prebuilds-query.ts | 50 ++++++++ .../prebuilds/list/PrebuildEmptyListState.tsx | 22 ++++ .../src/prebuilds/list/PrebuildListItem.tsx | 66 ++++++++++ .../src/prebuilds/list/PrebuildsList.tsx | 83 +++++++++++++ .../src/prebuilds/list/PrebuildsTable.tsx | 113 ++++++++++++++++++ .../dashboard/src/projects/Prebuilds.tsx | 50 ++++++-- components/dashboard/src/projects/Project.tsx | 4 +- 9 files changed, 381 insertions(+), 13 deletions(-) create mode 100644 components/dashboard/src/data/prebuilds/organization-prebuilds-query.ts create mode 100644 components/dashboard/src/prebuilds/list/PrebuildEmptyListState.tsx create mode 100644 components/dashboard/src/prebuilds/list/PrebuildListItem.tsx create mode 100644 components/dashboard/src/prebuilds/list/PrebuildsList.tsx create mode 100644 components/dashboard/src/prebuilds/list/PrebuildsTable.tsx diff --git a/components/dashboard/src/app/AppRoutes.tsx b/components/dashboard/src/app/AppRoutes.tsx index edd9a93cb35de0..da018accda0050 100644 --- a/components/dashboard/src/app/AppRoutes.tsx +++ b/components/dashboard/src/app/AppRoutes.tsx @@ -80,6 +80,8 @@ const ConfigurationDetailPage = React.lazy( () => import(/* webpackPrefetch: true */ "../repositories/detail/ConfigurationDetailPage"), ); +const PrebuildListPage = React.lazy(() => import(/* webpackPrefetch: true */ "../prebuilds/list/PrebuildsList")); + export const AppRoutes = () => { const hash = getURLHash(); const location = useLocation(); @@ -206,6 +208,8 @@ export const AppRoutes = () => { + + {repoConfigListAndDetail && } {/* Handles all /repositories/:id/* routes in a nested router */} {repoConfigListAndDetail && } diff --git a/components/dashboard/src/data/configurations/configuration-queries.ts b/components/dashboard/src/data/configurations/configuration-queries.ts index a5b875d7f3c74d..141bed9e401494 100644 --- a/components/dashboard/src/data/configurations/configuration-queries.ts +++ b/components/dashboard/src/data/configurations/configuration-queries.ts @@ -32,7 +32,7 @@ export const useListConfigurations = (options: ListConfigurationsArgs) => { const { searchTerm = "", prebuildsEnabled, pageSize, sortBy, sortOrder } = options; return useInfiniteQuery( - getListConfigurationsQueryKey(org?.id || "", options), + getListConfigurationsQueryKey(org?.id ?? "", options), // QueryFn receives the past page's pageParam as it's argument async ({ pageParam: nextToken }) => { if (!org) { diff --git a/components/dashboard/src/data/prebuilds/organization-prebuilds-query.ts b/components/dashboard/src/data/prebuilds/organization-prebuilds-query.ts new file mode 100644 index 00000000000000..e8bece15af378b --- /dev/null +++ b/components/dashboard/src/data/prebuilds/organization-prebuilds-query.ts @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2024 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License.AGPL.txt in the project root for license information. + */ + +import { useInfiniteQuery } from "@tanstack/react-query"; +import { prebuildClient } from "../../service/public-api"; +import { ListOrganizationPrebuildsRequest_Filter } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; +import { useCurrentOrg } from "../organizations/orgs-query"; +import { PlainMessage } from "@bufbuild/protobuf"; + +type Args = { + filter: Partial>; + pageSize: number; +}; +export const useListOrganizationPrebuildsQuery = ({ filter, pageSize }: Args) => { + const { data: org } = useCurrentOrg(); + + return useInfiniteQuery( + getListConfigurationsPrebuildsQueryKey(org?.id ?? "", { filter, pageSize }), + async ({ pageParam: nextToken }) => { + if (!org) { + throw new Error("No org currently selected"); + } + + const { prebuilds, pagination } = await prebuildClient.listOrganizationPrebuilds({ + organizationId: org.id, + filter, + pagination: { pageSize, token: nextToken }, + }); + return { + prebuilds, + pagination, + }; + }, + { + enabled: !!org, + keepPreviousData: true, + getNextPageParam: (lastPage) => { + // Must ensure we return undefined if there are no more pages + return lastPage.pagination?.nextToken || undefined; + }, + }, + ); +}; + +export const getListConfigurationsPrebuildsQueryKey = (orgId: string, opts: Args) => { + return ["prebuilds", "list", orgId, opts]; +}; diff --git a/components/dashboard/src/prebuilds/list/PrebuildEmptyListState.tsx b/components/dashboard/src/prebuilds/list/PrebuildEmptyListState.tsx new file mode 100644 index 00000000000000..11979b70224051 --- /dev/null +++ b/components/dashboard/src/prebuilds/list/PrebuildEmptyListState.tsx @@ -0,0 +1,22 @@ +/** + * Copyright (c) 2024 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License.AGPL.txt in the project root for license information. + */ + +import { FC } from "react"; +import { Heading2, Subheading } from "@podkit/typography/Headings"; +import { cn } from "@podkit/lib/cn"; + +export const PrebuildListEmptyState: FC = () => { + return ( +
+
+ No prebuilds yet + + Go on, create Configurations and turn them on, I'll be waiting here... + +
+
+ ); +}; diff --git a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx new file mode 100644 index 00000000000000..a5c60736bbbdeb --- /dev/null +++ b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx @@ -0,0 +1,66 @@ +/** + * Copyright (c) 2024 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License.AGPL.txt in the project root for license information. + */ + +import { FC } from "react"; +import { TextMuted } from "@podkit/typography/TextMuted"; +import { Text } from "@podkit/typography/Text"; +import { LinkButton } from "@podkit/buttons/LinkButton"; +import { TableCell, TableRow } from "@podkit/tables/Table"; +import type { Prebuild } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; +import { useConfiguration } from "../../data/configurations/configuration-queries"; +import { prebuildDisplayProps, prebuildStatusIconName } from "../../projects/Prebuilds"; +import dayjs from "dayjs"; +import { cn } from "@podkit/lib/cn"; + +type Props = { + prebuild: Prebuild; +}; +export const RepositoryListItem: FC = ({ prebuild }) => { + const created = dayjs(prebuild.status?.startTime?.toDate()).fromNow(); + const { data: configuration } = useConfiguration(prebuild.configurationId); + const { className: iconColorClass, label } = prebuildDisplayProps(prebuild); + const PrebuildStatusIcon = prebuildStatusIconName(prebuild); + + return ( + + +
+ {configuration?.name} + branch (soon™) +
+
+ + + {prebuild.commit?.author && ( +
+ {prebuild.commit.message} +
+ + + {prebuild.commit.author.name} + +
+
+ )} +
+ + {created} + + +
+ + {label} +
+
+ + + + View + + +
+ ); +}; diff --git a/components/dashboard/src/prebuilds/list/PrebuildsList.tsx b/components/dashboard/src/prebuilds/list/PrebuildsList.tsx new file mode 100644 index 00000000000000..dd3194b911ad36 --- /dev/null +++ b/components/dashboard/src/prebuilds/list/PrebuildsList.tsx @@ -0,0 +1,83 @@ +/** + * Copyright (c) 2024 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License.AGPL.txt in the project root for license information. + */ + +import { FC, useEffect, useMemo } from "react"; +import { useHistory } from "react-router-dom"; +import { PageHeading } from "@podkit/layout/PageHeading"; +import { useDocumentTitle } from "../../hooks/use-document-title"; +import { useQueryParams } from "../../hooks/use-query-params"; +import { PrebuildListEmptyState } from "./PrebuildEmptyListState"; +import { useStateWithDebounce } from "../../hooks/use-state-with-debounce"; +import { PrebuildsTable } from "./PrebuildsTable"; +import { LoadingState } from "@podkit/loading/LoadingState"; +import { useListOrganizationPrebuildsQuery } from "../../data/prebuilds/organization-prebuilds-query"; + +const PrebuildsListPage: FC = () => { + useDocumentTitle("Prebuilds"); + + const history = useHistory(); + + const params = useQueryParams(); + const [searchTerm, setSearchTerm, searchTermDebounced] = useStateWithDebounce(params.get("search") || ""); + + useEffect(() => { + const params = new URLSearchParams(); + if (searchTermDebounced) { + params.set("search", searchTermDebounced); + } + params.toString(); + history.replace({ search: `?${params.toString()}` }); + }, [history, searchTermDebounced]); + + // TODO: handle isError case + const { data, isLoading, isFetching, isFetchingNextPage, isPreviousData, hasNextPage, fetchNextPage } = + useListOrganizationPrebuildsQuery({ + filter: { + searchTerm: searchTermDebounced, + }, + pageSize: 30, + }); + + const prebuilds = useMemo(() => { + return data?.pages.map((page) => page.prebuilds).flat() ?? []; + }, [data?.pages]); + + const hasMoreThanOnePage = (data?.pages.length ?? 0) > 1; + + // This tracks any filters/search params applied + const hasFilters = !!searchTermDebounced; + + // Show the table once we're done loading and either have results, or have filters applied + const showTable = !isLoading && (prebuilds.length > 0 || hasFilters); + + return ( + <> +
+ + + {isLoading && } + + {showTable && ( + fetchNextPage()} + onSearchTermChange={setSearchTerm} + /> + )} + + {!showTable && !isLoading && } +
+ + ); +}; + +export default PrebuildsListPage; diff --git a/components/dashboard/src/prebuilds/list/PrebuildsTable.tsx b/components/dashboard/src/prebuilds/list/PrebuildsTable.tsx new file mode 100644 index 00000000000000..356be895031e9a --- /dev/null +++ b/components/dashboard/src/prebuilds/list/PrebuildsTable.tsx @@ -0,0 +1,113 @@ +/** + * Copyright (c) 2024 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License.AGPL.txt in the project root for license information. + */ + +import { FC } from "react"; +import { TextInput } from "../../components/forms/TextInputField"; +import { Table, TableBody, TableHead, TableHeader, TableRow } from "@podkit/tables/Table"; +import { RepositoryListItem } from "./PrebuildListItem"; +import { LoadingButton } from "@podkit/buttons/LoadingButton"; +import { TextMuted } from "@podkit/typography/TextMuted"; +import { Subheading } from "@podkit/typography/Headings"; +import { cn } from "@podkit/lib/cn"; +import { LoadingState } from "@podkit/loading/LoadingState"; +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@podkit/select/Select"; +import { Prebuild } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; + +type Props = { + prebuilds: Prebuild[]; + searchTerm: string; + hasNextPage: boolean; + hasMoreThanOnePage: boolean; + isSearching: boolean; + isFetchingNextPage: boolean; + onSearchTermChange: (val: string) => void; + onLoadNextPage: () => void; +}; + +export const PrebuildsTable: FC = ({ + searchTerm, + prebuilds, + hasNextPage, + hasMoreThanOnePage, + isSearching, + isFetchingNextPage, + onSearchTermChange, + onLoadNextPage, +}) => { + return ( + <> + {/* Search/Filter bar */} +
+
+ {/* TODO: Add search icon on left - need to revisit TextInputs for podkit - and remove global styles */} + + {/* todo: add filtering logic */} + +
+
+
+ {prebuilds.length > 0 ? ( + + + + Repository + Commit + + Triggered + + Status + {/* Action column, loading status in header */} + + {isSearching && ( +
+ +
+ )} +
+
+
+ + {prebuilds.map((configuration) => { + return ; + })} + +
+ ) : ( +
+ No results found. Try adjusting your search terms. +
+ )} + +
+ {hasNextPage ? ( + + Load more + + ) : ( + hasMoreThanOnePage && All prebuilds are loaded + )} +
+
+ + ); +}; diff --git a/components/dashboard/src/projects/Prebuilds.tsx b/components/dashboard/src/projects/Prebuilds.tsx index 74aba58ac982e7..aa4aee3c7a6362 100644 --- a/components/dashboard/src/projects/Prebuilds.tsx +++ b/components/dashboard/src/projects/Prebuilds.tsx @@ -6,7 +6,7 @@ import dayjs from "dayjs"; import { Project } from "@gitpod/gitpod-protocol"; -import { useEffect, useState } from "react"; +import { ForwardRefExoticComponent, useEffect, useState } from "react"; import Header from "../components/Header"; import DropDown, { DropDownEntry } from "../components/DropDown"; import { ItemsList, Item, ItemField } from "../components/ItemsList"; @@ -25,6 +25,7 @@ import Tooltip from "../components/Tooltip"; import { prebuildClient, watchPrebuild } from "../service/public-api"; import { Prebuild, PrebuildPhase_Phase } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; import { Button } from "@podkit/buttons/Button"; +import { CheckCircle2, CircleSlash, Clock, HelpCircle, LucideProps, PauseCircle, XCircle } from "lucide-react"; export default function PrebuildsPage(props: { project?: Project; isAdminDashboard?: boolean }) { const currentProject = useCurrentProject(); @@ -284,25 +285,54 @@ export default function PrebuildsPage(props: { project?: Project; isAdminDashboa ); } -export function prebuildStatusLabel(prebuild?: Prebuild) { - switch (prebuild?.status?.phase?.name) { +export const prebuildDisplayProps = (prebuild: Prebuild): { className: string; label: string } => { + switch (prebuild.status?.phase?.name) { case PrebuildPhase_Phase.UNSPECIFIED: // Fall through case PrebuildPhase_Phase.QUEUED: - return pending; + return { className: "text-orange-500", label: "pending" }; case PrebuildPhase_Phase.BUILDING: - return running; + return { className: "text-blue-500", label: "running" }; case PrebuildPhase_Phase.ABORTED: - return canceled; + return { className: "text-gray-500", label: "canceled" }; case PrebuildPhase_Phase.FAILED: - return system error; + return { className: "text-red-500", label: "system error" }; + case PrebuildPhase_Phase.TIMEOUT: + return { className: "text-red-500", label: "timed out" }; + case PrebuildPhase_Phase.AVAILABLE: + if (prebuild.status?.message) { + return { className: "text-red-500", label: "failed" }; + } + return { className: "text-green-500", label: "ready" }; + } + + return { className: "", label: "" }; +}; + +export function prebuildStatusLabel(prebuild: Prebuild): JSX.Element { + const { className, label } = prebuildDisplayProps(prebuild); + return {label}; +} + +export function prebuildStatusIconName(prebuild: Prebuild): ForwardRefExoticComponent { + switch (prebuild.status?.phase?.name) { + case PrebuildPhase_Phase.UNSPECIFIED: // Fall through + case PrebuildPhase_Phase.QUEUED: + return PauseCircle; + case PrebuildPhase_Phase.BUILDING: + return Clock; + case PrebuildPhase_Phase.ABORTED: + return CircleSlash; case PrebuildPhase_Phase.TIMEOUT: - return timed out; + case PrebuildPhase_Phase.FAILED: + return XCircle; case PrebuildPhase_Phase.AVAILABLE: if (prebuild?.status?.message) { - return failed; + return XCircle; } - return ready; + return CheckCircle2; } + + return HelpCircle; } export function prebuildStatusIcon(prebuild?: Prebuild) { diff --git a/components/dashboard/src/projects/Project.tsx b/components/dashboard/src/projects/Project.tsx index ee3f87e7b56b49..4feac0d55b1b43 100644 --- a/components/dashboard/src/projects/Project.tsx +++ b/components/dashboard/src/projects/Project.tsx @@ -309,8 +309,8 @@ export default function ProjectsPage() { alt={branch.changeAuthor} /> ); - const statusIcon = prebuildStatusIcon(prebuild); - const status = prebuildStatusLabel(prebuild); + const statusIcon = prebuild && prebuildStatusIcon(prebuild); + const status = prebuild && prebuildStatusLabel(prebuild); return ( Date: Wed, 24 Jan 2024 22:43:49 +0000 Subject: [PATCH 02/49] Text size and color tweaks --- .../dashboard/src/prebuilds/list/PrebuildListItem.tsx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx index a5c60736bbbdeb..644d051f6e8d02 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx @@ -14,6 +14,7 @@ import { useConfiguration } from "../../data/configurations/configuration-querie import { prebuildDisplayProps, prebuildStatusIconName } from "../../projects/Prebuilds"; import dayjs from "dayjs"; import { cn } from "@podkit/lib/cn"; +import { shortCommitMessage } from "../../projects/render-utils"; type Props = { prebuild: Prebuild; @@ -36,7 +37,9 @@ export const RepositoryListItem: FC = ({ prebuild }) => { {prebuild.commit?.author && (
- {prebuild.commit.message} + + {shortCommitMessage(prebuild.commit.message)} +
@@ -47,12 +50,14 @@ export const RepositoryListItem: FC = ({ prebuild }) => { )} - {created} + + {created} +
- {label} + {label}
From 484e846193613be7137b49cda99575c8a350f740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Thu, 25 Jan 2024 08:23:57 +0000 Subject: [PATCH 03/49] Dropdown filtering UI --- .../dashboard/src/components/forms/TextInputField.tsx | 2 +- .../dashboard/src/prebuilds/list/PrebuildListItem.tsx | 6 +++--- .../dashboard/src/prebuilds/list/PrebuildsList.tsx | 2 +- .../dashboard/src/prebuilds/list/PrebuildsTable.tsx | 10 ++++++---- components/dashboard/src/projects/Prebuilds.tsx | 2 +- 5 files changed, 12 insertions(+), 10 deletions(-) diff --git a/components/dashboard/src/components/forms/TextInputField.tsx b/components/dashboard/src/components/forms/TextInputField.tsx index 30c36a7813384a..b6a81302b4e71c 100644 --- a/components/dashboard/src/components/forms/TextInputField.tsx +++ b/components/dashboard/src/components/forms/TextInputField.tsx @@ -9,7 +9,7 @@ import { useId } from "../../hooks/useId"; import { InputField } from "./InputField"; import { cn } from "@podkit/lib/cn"; -type TextInputFieldTypes = "text" | "password" | "email" | "url"; +type TextInputFieldTypes = "text" | "password" | "email" | "url" | "search"; type Props = TextInputProps & { label?: ReactNode; diff --git a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx index 644d051f6e8d02..a38681c9104163 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx @@ -30,7 +30,7 @@ export const RepositoryListItem: FC = ({ prebuild }) => {
{configuration?.name} - branch (soon™) + {prebuild.ref}
@@ -40,7 +40,7 @@ export const RepositoryListItem: FC = ({ prebuild }) => { {shortCommitMessage(prebuild.commit.message)} -
+
{prebuild.commit.author.name} @@ -51,7 +51,7 @@ export const RepositoryListItem: FC = ({ prebuild }) => { - {created} + {created} diff --git a/components/dashboard/src/prebuilds/list/PrebuildsList.tsx b/components/dashboard/src/prebuilds/list/PrebuildsList.tsx index dd3194b911ad36..19f938bfbc25e8 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildsList.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildsList.tsx @@ -56,7 +56,7 @@ const PrebuildsListPage: FC = () => { return ( <>
- + {isLoading && } diff --git a/components/dashboard/src/prebuilds/list/PrebuildsTable.tsx b/components/dashboard/src/prebuilds/list/PrebuildsTable.tsx index 356be895031e9a..5004f4d12019a9 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildsTable.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildsTable.tsx @@ -46,17 +46,19 @@ export const PrebuildsTable: FC = ({ {/* todo: add filtering logic */}
diff --git a/components/dashboard/src/projects/Prebuilds.tsx b/components/dashboard/src/projects/Prebuilds.tsx index aa4aee3c7a6362..0693e6119a2214 100644 --- a/components/dashboard/src/projects/Prebuilds.tsx +++ b/components/dashboard/src/projects/Prebuilds.tsx @@ -293,7 +293,7 @@ export const prebuildDisplayProps = (prebuild: Prebuild): { className: string; l case PrebuildPhase_Phase.BUILDING: return { className: "text-blue-500", label: "running" }; case PrebuildPhase_Phase.ABORTED: - return { className: "text-gray-500", label: "canceled" }; + return { className: "text-gray-500", label: "cancelled" }; case PrebuildPhase_Phase.FAILED: return { className: "text-red-500", label: "system error" }; case PrebuildPhase_Phase.TIMEOUT: From f88c6dd547a3de220c4fbf45ae4d3bb0ebdd6e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Thu, 25 Jan 2024 17:55:45 +0000 Subject: [PATCH 04/49] wip changes --- .../src/prebuilds/list/PrebuildsList.tsx | 56 +++++++++++++++++-- .../src/prebuilds/list/PrebuildsTable.tsx | 35 ++++++++---- 2 files changed, 76 insertions(+), 15 deletions(-) diff --git a/components/dashboard/src/prebuilds/list/PrebuildsList.tsx b/components/dashboard/src/prebuilds/list/PrebuildsList.tsx index 19f938bfbc25e8..e64d35df34f50d 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildsList.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildsList.tsx @@ -4,16 +4,20 @@ * See License.AGPL.txt in the project root for license information. */ -import { FC, useEffect, useMemo } from "react"; +import { FC, useCallback, useEffect, useMemo, useState } from "react"; import { useHistory } from "react-router-dom"; import { PageHeading } from "@podkit/layout/PageHeading"; import { useDocumentTitle } from "../../hooks/use-document-title"; import { useQueryParams } from "../../hooks/use-query-params"; import { PrebuildListEmptyState } from "./PrebuildEmptyListState"; import { useStateWithDebounce } from "../../hooks/use-state-with-debounce"; -import { PrebuildsTable } from "./PrebuildsTable"; +import { Filter, PrebuildsTable } from "./PrebuildsTable"; import { LoadingState } from "@podkit/loading/LoadingState"; import { useListOrganizationPrebuildsQuery } from "../../data/prebuilds/organization-prebuilds-query"; +import { PrebuildPhase_Phase } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; + +const STATUS_FILTER = ["succeeded", "failed", "unfinished", undefined] as const; // undefined means any status +export type STATUS_FILTER_VALUES = typeof STATUS_FILTER[number]; const PrebuildsListPage: FC = () => { useDocumentTitle("Prebuilds"); @@ -21,22 +25,39 @@ const PrebuildsListPage: FC = () => { const history = useHistory(); const params = useQueryParams(); - const [searchTerm, setSearchTerm, searchTermDebounced] = useStateWithDebounce(params.get("search") || ""); + const [searchTerm, setSearchTerm, searchTermDebounced] = useStateWithDebounce(params.get("search") ?? ""); + const [statusFilter, setPrebuildsFilter] = useState(parseStatus(params)); + + const handleFilterChange = useCallback((filter: Filter) => { + setPrebuildsFilter(filter.status); + }, []); + const filter = useMemo(() => { + return { + status: statusFilter, + }; + }, [statusFilter]); useEffect(() => { const params = new URLSearchParams(); if (searchTermDebounced) { params.set("search", searchTermDebounced); } + + // Since "any" is the default, we don't need to set it in the url + if (statusFilter) { + params.set("prebuilds", statusFilter); + } + params.toString(); history.replace({ search: `?${params.toString()}` }); - }, [history, searchTermDebounced]); + }, [history, statusFilter, searchTermDebounced]); // TODO: handle isError case const { data, isLoading, isFetching, isFetchingNextPage, isPreviousData, hasNextPage, fetchNextPage } = useListOrganizationPrebuildsQuery({ filter: { searchTerm: searchTermDebounced, + status: toApiStatus(filter.status), }, pageSize: 30, }); @@ -48,7 +69,7 @@ const PrebuildsListPage: FC = () => { const hasMoreThanOnePage = (data?.pages.length ?? 0) > 1; // This tracks any filters/search params applied - const hasFilters = !!searchTermDebounced; + const hasFilters = !!searchTermDebounced || !!filter.status; // Show the table once we're done loading and either have results, or have filters applied const showTable = !isLoading && (prebuilds.length > 0 || hasFilters); @@ -68,8 +89,10 @@ const PrebuildsListPage: FC = () => { isSearching={isFetching && isPreviousData} isFetchingNextPage={isFetchingNextPage} hasNextPage={!!hasNextPage} + filter={filter} hasMoreThanOnePage={hasMoreThanOnePage} onLoadNextPage={() => fetchNextPage()} + onFilterChange={handleFilterChange} onSearchTermChange={setSearchTerm} /> )} @@ -80,4 +103,27 @@ const PrebuildsListPage: FC = () => { ); }; +const toApiStatus = (status: STATUS_FILTER_VALUES): PrebuildPhase_Phase | undefined => { + switch (status) { + case "failed": + return PrebuildPhase_Phase.FAILED; // todo: adjust to needs of proper status + case "succeeded": + return PrebuildPhase_Phase.AVAILABLE; + case "unfinished": + return PrebuildPhase_Phase.BUILDING; + } + + return undefined; +}; + +const parseStatus = (params: URLSearchParams): STATUS_FILTER_VALUES => { + const filter = params.get("prebuilds"); + const validValues = Object.values(STATUS_FILTER).filter((val) => !!val); + if (filter && validValues.includes(filter as any)) { + return filter as STATUS_FILTER_VALUES; + } + + return undefined; +}; + export default PrebuildsListPage; diff --git a/components/dashboard/src/prebuilds/list/PrebuildsTable.tsx b/components/dashboard/src/prebuilds/list/PrebuildsTable.tsx index 5004f4d12019a9..758b039fd3773f 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildsTable.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildsTable.tsx @@ -15,18 +15,24 @@ import { cn } from "@podkit/lib/cn"; import { LoadingState } from "@podkit/loading/LoadingState"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@podkit/select/Select"; import { Prebuild } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; +import { STATUS_FILTER_VALUES } from "./PrebuildsList"; + +export type Filter = { + status?: STATUS_FILTER_VALUES; +}; type Props = { prebuilds: Prebuild[]; searchTerm: string; + filter?: Filter; hasNextPage: boolean; hasMoreThanOnePage: boolean; isSearching: boolean; isFetchingNextPage: boolean; onSearchTermChange: (val: string) => void; + onFilterChange: (val: Filter) => void; onLoadNextPage: () => void; }; - export const PrebuildsTable: FC = ({ searchTerm, prebuilds, @@ -34,7 +40,9 @@ export const PrebuildsTable: FC = ({ hasMoreThanOnePage, isSearching, isFetchingNextPage, + filter, onSearchTermChange, + onFilterChange, onLoadNextPage, }) => { return ( @@ -44,21 +52,28 @@ export const PrebuildsTable: FC = ({
{/* TODO: Add search icon on left - need to revisit TextInputs for podkit - and remove global styles */} - {/* todo: add filtering logic */} - { + if (status === "any") { + onFilterChange({ status: undefined }); + return; + } + onFilterChange({ status: status as STATUS_FILTER_VALUES }); + }} + > + + - Any status - Failing - Succeeding + Any + Failed + Succeeded
From 8793b9879a21071338a0cb79ca390f70b4c00811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Thu, 25 Jan 2024 18:25:05 +0000 Subject: [PATCH 05/49] File renames and such --- components/dashboard/src/app/AppRoutes.tsx | 2 +- .../{PrebuildsList.tsx => PrebuildList.tsx} | 18 ++++++++++-------- .../{PrebuildsTable.tsx => PrebuildTable.tsx} | 8 ++------ 3 files changed, 13 insertions(+), 15 deletions(-) rename components/dashboard/src/prebuilds/list/{PrebuildsList.tsx => PrebuildList.tsx} (87%) rename components/dashboard/src/prebuilds/list/{PrebuildsTable.tsx => PrebuildTable.tsx} (97%) diff --git a/components/dashboard/src/app/AppRoutes.tsx b/components/dashboard/src/app/AppRoutes.tsx index da018accda0050..d6a675ba1f0361 100644 --- a/components/dashboard/src/app/AppRoutes.tsx +++ b/components/dashboard/src/app/AppRoutes.tsx @@ -80,7 +80,7 @@ const ConfigurationDetailPage = React.lazy( () => import(/* webpackPrefetch: true */ "../repositories/detail/ConfigurationDetailPage"), ); -const PrebuildListPage = React.lazy(() => import(/* webpackPrefetch: true */ "../prebuilds/list/PrebuildsList")); +const PrebuildListPage = React.lazy(() => import(/* webpackPrefetch: true */ "../prebuilds/list/PrebuildList")); export const AppRoutes = () => { const hash = getURLHash(); diff --git a/components/dashboard/src/prebuilds/list/PrebuildsList.tsx b/components/dashboard/src/prebuilds/list/PrebuildList.tsx similarity index 87% rename from components/dashboard/src/prebuilds/list/PrebuildsList.tsx rename to components/dashboard/src/prebuilds/list/PrebuildList.tsx index e64d35df34f50d..fd25200de3d884 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildsList.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildList.tsx @@ -11,13 +11,16 @@ import { useDocumentTitle } from "../../hooks/use-document-title"; import { useQueryParams } from "../../hooks/use-query-params"; import { PrebuildListEmptyState } from "./PrebuildEmptyListState"; import { useStateWithDebounce } from "../../hooks/use-state-with-debounce"; -import { Filter, PrebuildsTable } from "./PrebuildsTable"; +import { PrebuildsTable } from "./PrebuildTable"; import { LoadingState } from "@podkit/loading/LoadingState"; import { useListOrganizationPrebuildsQuery } from "../../data/prebuilds/organization-prebuilds-query"; import { PrebuildPhase_Phase } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; -const STATUS_FILTER = ["succeeded", "failed", "unfinished", undefined] as const; // undefined means any status -export type STATUS_FILTER_VALUES = typeof STATUS_FILTER[number]; +const STATUS_FILTER_VALUES = ["succeeded", "failed", "unfinished", undefined] as const; // undefined means any status +export type STATUS_OPTION = typeof STATUS_FILTER_VALUES[number]; +export type Filter = { + status?: STATUS_OPTION; +}; const PrebuildsListPage: FC = () => { useDocumentTitle("Prebuilds"); @@ -43,7 +46,6 @@ const PrebuildsListPage: FC = () => { params.set("search", searchTermDebounced); } - // Since "any" is the default, we don't need to set it in the url if (statusFilter) { params.set("prebuilds", statusFilter); } @@ -103,7 +105,7 @@ const PrebuildsListPage: FC = () => { ); }; -const toApiStatus = (status: STATUS_FILTER_VALUES): PrebuildPhase_Phase | undefined => { +const toApiStatus = (status: STATUS_OPTION): PrebuildPhase_Phase | undefined => { switch (status) { case "failed": return PrebuildPhase_Phase.FAILED; // todo: adjust to needs of proper status @@ -116,11 +118,11 @@ const toApiStatus = (status: STATUS_FILTER_VALUES): PrebuildPhase_Phase | undefi return undefined; }; -const parseStatus = (params: URLSearchParams): STATUS_FILTER_VALUES => { +const parseStatus = (params: URLSearchParams): STATUS_OPTION => { const filter = params.get("prebuilds"); - const validValues = Object.values(STATUS_FILTER).filter((val) => !!val); + const validValues = Object.values(STATUS_FILTER_VALUES).filter((val) => !!val); if (filter && validValues.includes(filter as any)) { - return filter as STATUS_FILTER_VALUES; + return filter as STATUS_OPTION; } return undefined; diff --git a/components/dashboard/src/prebuilds/list/PrebuildsTable.tsx b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx similarity index 97% rename from components/dashboard/src/prebuilds/list/PrebuildsTable.tsx rename to components/dashboard/src/prebuilds/list/PrebuildTable.tsx index 758b039fd3773f..17bc37e575fc5a 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildsTable.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx @@ -15,11 +15,7 @@ import { cn } from "@podkit/lib/cn"; import { LoadingState } from "@podkit/loading/LoadingState"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@podkit/select/Select"; import { Prebuild } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; -import { STATUS_FILTER_VALUES } from "./PrebuildsList"; - -export type Filter = { - status?: STATUS_FILTER_VALUES; -}; +import { Filter, STATUS_OPTION } from "./PrebuildList"; type Props = { prebuilds: Prebuild[]; @@ -64,7 +60,7 @@ export const PrebuildsTable: FC = ({ onFilterChange({ status: undefined }); return; } - onFilterChange({ status: status as STATUS_FILTER_VALUES }); + onFilterChange({ status: status as STATUS_OPTION }); }} > From e5aa4b48a82db7367b74a1c076be54b355face53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Thu, 25 Jan 2024 20:11:41 +0000 Subject: [PATCH 06/49] Filter by state --- .../src/prebuilds/list/PrebuildList.tsx | 12 +- .../src/typeorm/workspace-db-impl.ts | 46 ++- components/gitpod-db/src/workspace-db.ts | 3 +- .../public-api/gitpod/v1/prebuild.proto | 8 +- components/public-api/go/v1/prebuild.pb.go | 383 ++++++++++-------- .../src/public-api-converter.ts | 21 +- .../src/gitpod/v1/prebuild_connect.ts | 131 +++--- .../typescript/src/gitpod/v1/prebuild_pb.ts | 38 +- .../server/src/api/prebuild-service-api.ts | 10 +- .../server/src/prebuilds/prebuild-manager.ts | 3 +- 10 files changed, 398 insertions(+), 257 deletions(-) diff --git a/components/dashboard/src/prebuilds/list/PrebuildList.tsx b/components/dashboard/src/prebuilds/list/PrebuildList.tsx index fd25200de3d884..6d011f284bb1f1 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildList.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildList.tsx @@ -14,7 +14,7 @@ import { useStateWithDebounce } from "../../hooks/use-state-with-debounce"; import { PrebuildsTable } from "./PrebuildTable"; import { LoadingState } from "@podkit/loading/LoadingState"; import { useListOrganizationPrebuildsQuery } from "../../data/prebuilds/organization-prebuilds-query"; -import { PrebuildPhase_Phase } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; +import { ListOrganizationPrebuildsRequest_Filter_State } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; const STATUS_FILTER_VALUES = ["succeeded", "failed", "unfinished", undefined] as const; // undefined means any status export type STATUS_OPTION = typeof STATUS_FILTER_VALUES[number]; @@ -59,7 +59,7 @@ const PrebuildsListPage: FC = () => { useListOrganizationPrebuildsQuery({ filter: { searchTerm: searchTermDebounced, - status: toApiStatus(filter.status), + state: toApiStatus(filter.status), }, pageSize: 30, }); @@ -105,14 +105,14 @@ const PrebuildsListPage: FC = () => { ); }; -const toApiStatus = (status: STATUS_OPTION): PrebuildPhase_Phase | undefined => { +const toApiStatus = (status: STATUS_OPTION): ListOrganizationPrebuildsRequest_Filter_State | undefined => { switch (status) { case "failed": - return PrebuildPhase_Phase.FAILED; // todo: adjust to needs of proper status + return ListOrganizationPrebuildsRequest_Filter_State.FAILED; // todo: adjust to needs of proper status case "succeeded": - return PrebuildPhase_Phase.AVAILABLE; + return ListOrganizationPrebuildsRequest_Filter_State.SUCCEEDED; case "unfinished": - return PrebuildPhase_Phase.BUILDING; + return ListOrganizationPrebuildsRequest_Filter_State.UNFINISHED; } return undefined; diff --git a/components/gitpod-db/src/typeorm/workspace-db-impl.ts b/components/gitpod-db/src/typeorm/workspace-db-impl.ts index 0d2597f31570fe..c40bc0faf60395 100644 --- a/components/gitpod-db/src/typeorm/workspace-db-impl.ts +++ b/components/gitpod-db/src/typeorm/workspace-db-impl.ts @@ -1054,7 +1054,7 @@ export class TypeORMWorkspaceDBImpl extends TransactionalDBImpl imp id: string; branch?: string; }; - status: PrebuiltWorkspaceState; + state?: "succeeded" | "failed" | "unfinished"; searchTerm?: string; }, ): Promise { @@ -1072,8 +1072,48 @@ export class TypeORMWorkspaceDBImpl extends TransactionalDBImpl imp .skip(offset) .take(limit); - if (filter?.status) { - query.andWhere("pws.state = :state", { state: filter.status }); + if (filter?.state) { + const { state } = filter; + // translating API state to DB state + switch (state) { + case "failed": + query.andWhere( + new Brackets((qb) => { + qb.where("pws.state = :failedState", { failedState: "failed" }) + .orWhere("pws.state = :abortedState", { abortedState: "aborted" }) + .orWhere("pws.state = :timeoutState", { timeoutState: "timeout" }) + .orWhere( + new Brackets((qbInner) => { + qbInner + .where("pws.state = :availableState", { availableState: "available" }) + .andWhere("pws.error IS NOT NULL AND pws.error <> ''"); + }), + ); + }), + ); + break; + case "succeeded": + query.andWhere( + new Brackets((qb) => { + qb.where("pws.state = :state", { state: "available" }).andWhere( + new Brackets((qbInner) => { + qbInner.where("pws.error IS NULL").orWhere("pws.error = ''"); + }), + ); + }), + ); + break; + case "unfinished": + query.andWhere( + new Brackets((qb) => { + qb.where("pws.state = :queuedState", { queuedState: "queued" }).orWhere( + "pws.state = :buildingState", + { buildingState: "building" }, + ); + }), + ); + break; + } } if (filter?.configuration?.id) { diff --git a/components/gitpod-db/src/workspace-db.ts b/components/gitpod-db/src/workspace-db.ts index 71c6f92861ee2d..7d4fe1617e27d0 100644 --- a/components/gitpod-db/src/workspace-db.ts +++ b/components/gitpod-db/src/workspace-db.ts @@ -20,7 +20,6 @@ import { PrebuildInfo, AdminGetWorkspacesQuery, SnapshotState, - PrebuiltWorkspaceState, } from "@gitpod/gitpod-protocol"; export type MaybeWorkspace = Workspace | undefined; @@ -180,7 +179,7 @@ export interface WorkspaceDB { id: string; branch?: string; }; - status?: PrebuiltWorkspaceState; + state?: "succeeded" | "failed" | "unfinished"; searchTerm?: string; }, ): Promise; diff --git a/components/public-api/gitpod/v1/prebuild.proto b/components/public-api/gitpod/v1/prebuild.proto index 00c245cca517b5..e24796e4cf3045 100644 --- a/components/public-api/gitpod/v1/prebuild.proto +++ b/components/public-api/gitpod/v1/prebuild.proto @@ -70,7 +70,13 @@ message ListOrganizationPrebuildsRequest { string id = 1; string branch = 2; } - PrebuildPhase.Phase status = 1; + enum State { + STATE_UNSPECIFIED = 0; + STATE_SUCCEEDED = 1; + STATE_FAILED = 2; + STATE_UNFINISHED = 3; + } + State state = 1; Configuration configuration = 2; // Filter the search down by searching for configuration names matching the // query diff --git a/components/public-api/go/v1/prebuild.pb.go b/components/public-api/go/v1/prebuild.pb.go index 6b09dbba79bbcb..abcd7d7d94f8d6 100644 --- a/components/public-api/go/v1/prebuild.pb.go +++ b/components/public-api/go/v1/prebuild.pb.go @@ -25,6 +25,58 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type ListOrganizationPrebuildsRequest_Filter_State int32 + +const ( + ListOrganizationPrebuildsRequest_Filter_STATE_UNSPECIFIED ListOrganizationPrebuildsRequest_Filter_State = 0 + ListOrganizationPrebuildsRequest_Filter_STATE_SUCCEEDED ListOrganizationPrebuildsRequest_Filter_State = 1 + ListOrganizationPrebuildsRequest_Filter_STATE_FAILED ListOrganizationPrebuildsRequest_Filter_State = 2 + ListOrganizationPrebuildsRequest_Filter_STATE_UNFINISHED ListOrganizationPrebuildsRequest_Filter_State = 3 +) + +// Enum value maps for ListOrganizationPrebuildsRequest_Filter_State. +var ( + ListOrganizationPrebuildsRequest_Filter_State_name = map[int32]string{ + 0: "STATE_UNSPECIFIED", + 1: "STATE_SUCCEEDED", + 2: "STATE_FAILED", + 3: "STATE_UNFINISHED", + } + ListOrganizationPrebuildsRequest_Filter_State_value = map[string]int32{ + "STATE_UNSPECIFIED": 0, + "STATE_SUCCEEDED": 1, + "STATE_FAILED": 2, + "STATE_UNFINISHED": 3, + } +) + +func (x ListOrganizationPrebuildsRequest_Filter_State) Enum() *ListOrganizationPrebuildsRequest_Filter_State { + p := new(ListOrganizationPrebuildsRequest_Filter_State) + *p = x + return p +} + +func (x ListOrganizationPrebuildsRequest_Filter_State) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ListOrganizationPrebuildsRequest_Filter_State) Descriptor() protoreflect.EnumDescriptor { + return file_gitpod_v1_prebuild_proto_enumTypes[0].Descriptor() +} + +func (ListOrganizationPrebuildsRequest_Filter_State) Type() protoreflect.EnumType { + return &file_gitpod_v1_prebuild_proto_enumTypes[0] +} + +func (x ListOrganizationPrebuildsRequest_Filter_State) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ListOrganizationPrebuildsRequest_Filter_State.Descriptor instead. +func (ListOrganizationPrebuildsRequest_Filter_State) EnumDescriptor() ([]byte, []int) { + return file_gitpod_v1_prebuild_proto_rawDescGZIP(), []int{10, 0, 0} +} + type PrebuildPhase_Phase int32 const ( @@ -70,11 +122,11 @@ func (x PrebuildPhase_Phase) String() string { } func (PrebuildPhase_Phase) Descriptor() protoreflect.EnumDescriptor { - return file_gitpod_v1_prebuild_proto_enumTypes[0].Descriptor() + return file_gitpod_v1_prebuild_proto_enumTypes[1].Descriptor() } func (PrebuildPhase_Phase) Type() protoreflect.EnumType { - return &file_gitpod_v1_prebuild_proto_enumTypes[0] + return &file_gitpod_v1_prebuild_proto_enumTypes[1] } func (x PrebuildPhase_Phase) Number() protoreflect.EnumNumber { @@ -967,7 +1019,7 @@ type ListOrganizationPrebuildsRequest_Filter struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Status PrebuildPhase_Phase `protobuf:"varint,1,opt,name=status,proto3,enum=gitpod.v1.PrebuildPhase_Phase" json:"status,omitempty"` + State ListOrganizationPrebuildsRequest_Filter_State `protobuf:"varint,1,opt,name=state,proto3,enum=gitpod.v1.ListOrganizationPrebuildsRequest_Filter_State" json:"state,omitempty"` Configuration *ListOrganizationPrebuildsRequest_Filter_Configuration `protobuf:"bytes,2,opt,name=configuration,proto3" json:"configuration,omitempty"` // Filter the search down by searching for configuration names matching the // query @@ -1006,11 +1058,11 @@ func (*ListOrganizationPrebuildsRequest_Filter) Descriptor() ([]byte, []int) { return file_gitpod_v1_prebuild_proto_rawDescGZIP(), []int{10, 0} } -func (x *ListOrganizationPrebuildsRequest_Filter) GetStatus() PrebuildPhase_Phase { +func (x *ListOrganizationPrebuildsRequest_Filter) GetState() ListOrganizationPrebuildsRequest_Filter_State { if x != nil { - return x.Status + return x.State } - return PrebuildPhase_PHASE_UNSPECIFIED + return ListOrganizationPrebuildsRequest_Filter_STATE_UNSPECIFIED } func (x *ListOrganizationPrebuildsRequest_Filter) GetConfiguration() *ListOrganizationPrebuildsRequest_Filter_Configuration { @@ -1147,7 +1199,7 @@ var file_gitpod_v1_prebuild_proto_rawDesc = []byte{ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, - 0x08, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x22, 0xda, 0x03, 0x0a, 0x20, 0x4c, 0x69, + 0x08, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x22, 0xcf, 0x04, 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, @@ -1161,114 +1213,122 @@ var file_gitpod_v1_prebuild_proto_rawDesc = []byte{ 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x1a, 0x82, 0x02, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x36, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x67, - 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x50, 0x68, 0x61, 0x73, 0x65, 0x2e, 0x50, 0x68, 0x61, 0x73, 0x65, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x12, 0x66, 0x0a, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x69, + 0x72, 0x1a, 0xf7, 0x02, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x4e, 0x0a, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x38, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, - 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x74, 0x65, 0x72, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x54, 0x65, 0x72, 0x6d, 0x1a, 0x37, 0x0a, - 0x0d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, - 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0x95, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x4f, - 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, - 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0a, - 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x67, - 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, - 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x0a, 0x09, 0x70, - 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, - 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x62, 0x75, - 0x69, 0x6c, 0x64, 0x52, 0x09, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x22, 0xae, - 0x02, 0x0a, 0x08, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x25, 0x0a, 0x0c, 0x77, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x62, 0x61, 0x73, 0x65, 0x64, 0x5f, 0x6f, 0x6e, 0x5f, 0x70, - 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x11, 0x62, 0x61, 0x73, 0x65, 0x64, 0x4f, 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x10, - 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x72, 0x65, 0x66, - 0x12, 0x29, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x11, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x63, - 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x55, 0x72, 0x6c, 0x12, 0x31, 0x0a, 0x06, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x67, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x66, 0x0a, 0x0d, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x74, + 0x65, 0x72, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x61, 0x72, 0x63, + 0x68, 0x54, 0x65, 0x72, 0x6d, 0x1a, 0x37, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0x5b, + 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x45, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, + 0x0a, 0x0f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, + 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, + 0x4c, 0x45, 0x44, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, + 0x4e, 0x46, 0x49, 0x4e, 0x49, 0x53, 0x48, 0x45, 0x44, 0x10, 0x03, 0x22, 0x95, 0x01, 0x0a, 0x21, + 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, + 0x31, 0x2e, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x31, 0x0a, 0x09, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x09, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, + 0x6c, 0x64, 0x73, 0x22, 0xae, 0x02, 0x0a, 0x08, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, + 0x12, 0x25, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, + 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x62, 0x61, 0x73, 0x65, 0x64, + 0x5f, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x62, 0x61, 0x73, 0x65, 0x64, 0x4f, 0x6e, 0x50, 0x72, + 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x29, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, + 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x55, 0x72, + 0x6c, 0x12, 0x31, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, + 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, + 0x61, 0x74, 0x75, 0x73, 0x22, 0x95, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, + 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x50, 0x68, 0x61, 0x73, 0x65, + 0x52, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, + 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, + 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xd7, 0x01, 0x0a, + 0x0d, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x50, 0x68, 0x61, 0x73, 0x65, 0x12, 0x32, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, - 0x95, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, - 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x50, 0x68, 0x61, 0x73, 0x65, 0x52, 0x05, 0x70, 0x68, 0x61, - 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x18, 0x0a, - 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xd7, 0x01, 0x0a, 0x0d, 0x50, 0x72, 0x65, 0x62, - 0x75, 0x69, 0x6c, 0x64, 0x50, 0x68, 0x61, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x04, 0x6e, 0x61, 0x6d, - 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x50, 0x68, 0x61, 0x73, - 0x65, 0x2e, 0x50, 0x68, 0x61, 0x73, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x91, 0x01, - 0x0a, 0x05, 0x50, 0x68, 0x61, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x50, 0x48, 0x41, 0x53, 0x45, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, - 0x0a, 0x0c, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x51, 0x55, 0x45, 0x55, 0x45, 0x44, 0x10, 0x01, - 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x42, 0x55, 0x49, 0x4c, 0x44, 0x49, - 0x4e, 0x47, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x41, 0x42, - 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x48, 0x41, 0x53, 0x45, - 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x04, 0x12, 0x13, 0x0a, 0x0f, 0x50, 0x48, - 0x41, 0x53, 0x45, 0x5f, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x10, 0x05, 0x12, - 0x10, 0x0a, 0x0c, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, 0x44, 0x10, - 0x06, 0x32, 0xb8, 0x04, 0x0a, 0x0f, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x54, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, - 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, - 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, 0x0a, 0x0e, 0x43, - 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x20, 0x2e, - 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, - 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x21, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, 0x63, - 0x65, 0x6c, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, - 0x69, 0x6c, 0x64, 0x12, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, - 0x47, 0x65, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x47, - 0x65, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x62, - 0x75, 0x69, 0x6c, 0x64, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, - 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x56, 0x0a, 0x0d, 0x57, 0x61, - 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x1f, 0x2e, 0x67, 0x69, - 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, + 0x64, 0x50, 0x68, 0x61, 0x73, 0x65, 0x2e, 0x50, 0x68, 0x61, 0x73, 0x65, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x22, 0x91, 0x01, 0x0a, 0x05, 0x50, 0x68, 0x61, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x11, + 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, + 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x51, 0x55, 0x45, + 0x55, 0x45, 0x44, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x42, + 0x55, 0x49, 0x4c, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x48, 0x41, + 0x53, 0x45, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, + 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x04, 0x12, + 0x13, 0x0a, 0x0f, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, + 0x4c, 0x45, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x46, 0x41, + 0x49, 0x4c, 0x45, 0x44, 0x10, 0x06, 0x32, 0xb8, 0x04, 0x0a, 0x0f, 0x50, 0x72, 0x65, 0x62, 0x75, + 0x69, 0x6c, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x54, 0x0a, 0x0d, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x1f, 0x2e, 0x67, 0x69, + 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, - 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, + 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x30, 0x01, 0x12, 0x78, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, - 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x12, - 0x2b, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, - 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x62, - 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x67, - 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, - 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x39, 0x5a, 0x37, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, - 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x63, 0x6f, 0x6d, 0x70, - 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x2d, 0x61, 0x70, - 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x12, 0x57, 0x0a, 0x0e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, + 0x6c, 0x64, 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, + 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x47, 0x65, 0x74, + 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, + 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, + 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x0d, 0x4c, 0x69, 0x73, + 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, + 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, + 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, + 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x62, + 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, + 0x56, 0x0a, 0x0d, 0x57, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, + 0x63, 0x68, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, + 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x78, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4f, + 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, + 0x69, 0x6c, 0x64, 0x73, 0x12, 0x2b, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x2c, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, + 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, + 0x00, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, + 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x2d, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1283,61 +1343,62 @@ func file_gitpod_v1_prebuild_proto_rawDescGZIP() []byte { return file_gitpod_v1_prebuild_proto_rawDescData } -var file_gitpod_v1_prebuild_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_gitpod_v1_prebuild_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_gitpod_v1_prebuild_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_gitpod_v1_prebuild_proto_goTypes = []interface{}{ - (PrebuildPhase_Phase)(0), // 0: gitpod.v1.PrebuildPhase.Phase - (*GetPrebuildRequest)(nil), // 1: gitpod.v1.GetPrebuildRequest - (*GetPrebuildResponse)(nil), // 2: gitpod.v1.GetPrebuildResponse - (*ListPrebuildsRequest)(nil), // 3: gitpod.v1.ListPrebuildsRequest - (*ListPrebuildsResponse)(nil), // 4: gitpod.v1.ListPrebuildsResponse - (*StartPrebuildRequest)(nil), // 5: gitpod.v1.StartPrebuildRequest - (*StartPrebuildResponse)(nil), // 6: gitpod.v1.StartPrebuildResponse - (*CancelPrebuildRequest)(nil), // 7: gitpod.v1.CancelPrebuildRequest - (*CancelPrebuildResponse)(nil), // 8: gitpod.v1.CancelPrebuildResponse - (*WatchPrebuildRequest)(nil), // 9: gitpod.v1.WatchPrebuildRequest - (*WatchPrebuildResponse)(nil), // 10: gitpod.v1.WatchPrebuildResponse - (*ListOrganizationPrebuildsRequest)(nil), // 11: gitpod.v1.ListOrganizationPrebuildsRequest - (*ListOrganizationPrebuildsResponse)(nil), // 12: gitpod.v1.ListOrganizationPrebuildsResponse - (*Prebuild)(nil), // 13: gitpod.v1.Prebuild - (*PrebuildStatus)(nil), // 14: gitpod.v1.PrebuildStatus - (*PrebuildPhase)(nil), // 15: gitpod.v1.PrebuildPhase - (*ListOrganizationPrebuildsRequest_Filter)(nil), // 16: gitpod.v1.ListOrganizationPrebuildsRequest.Filter - (*ListOrganizationPrebuildsRequest_Filter_Configuration)(nil), // 17: gitpod.v1.ListOrganizationPrebuildsRequest.Filter.Configuration - (*PaginationRequest)(nil), // 18: gitpod.v1.PaginationRequest - (*PaginationResponse)(nil), // 19: gitpod.v1.PaginationResponse - (*Commit)(nil), // 20: gitpod.v1.Commit - (*timestamppb.Timestamp)(nil), // 21: google.protobuf.Timestamp + (ListOrganizationPrebuildsRequest_Filter_State)(0), // 0: gitpod.v1.ListOrganizationPrebuildsRequest.Filter.State + (PrebuildPhase_Phase)(0), // 1: gitpod.v1.PrebuildPhase.Phase + (*GetPrebuildRequest)(nil), // 2: gitpod.v1.GetPrebuildRequest + (*GetPrebuildResponse)(nil), // 3: gitpod.v1.GetPrebuildResponse + (*ListPrebuildsRequest)(nil), // 4: gitpod.v1.ListPrebuildsRequest + (*ListPrebuildsResponse)(nil), // 5: gitpod.v1.ListPrebuildsResponse + (*StartPrebuildRequest)(nil), // 6: gitpod.v1.StartPrebuildRequest + (*StartPrebuildResponse)(nil), // 7: gitpod.v1.StartPrebuildResponse + (*CancelPrebuildRequest)(nil), // 8: gitpod.v1.CancelPrebuildRequest + (*CancelPrebuildResponse)(nil), // 9: gitpod.v1.CancelPrebuildResponse + (*WatchPrebuildRequest)(nil), // 10: gitpod.v1.WatchPrebuildRequest + (*WatchPrebuildResponse)(nil), // 11: gitpod.v1.WatchPrebuildResponse + (*ListOrganizationPrebuildsRequest)(nil), // 12: gitpod.v1.ListOrganizationPrebuildsRequest + (*ListOrganizationPrebuildsResponse)(nil), // 13: gitpod.v1.ListOrganizationPrebuildsResponse + (*Prebuild)(nil), // 14: gitpod.v1.Prebuild + (*PrebuildStatus)(nil), // 15: gitpod.v1.PrebuildStatus + (*PrebuildPhase)(nil), // 16: gitpod.v1.PrebuildPhase + (*ListOrganizationPrebuildsRequest_Filter)(nil), // 17: gitpod.v1.ListOrganizationPrebuildsRequest.Filter + (*ListOrganizationPrebuildsRequest_Filter_Configuration)(nil), // 18: gitpod.v1.ListOrganizationPrebuildsRequest.Filter.Configuration + (*PaginationRequest)(nil), // 19: gitpod.v1.PaginationRequest + (*PaginationResponse)(nil), // 20: gitpod.v1.PaginationResponse + (*Commit)(nil), // 21: gitpod.v1.Commit + (*timestamppb.Timestamp)(nil), // 22: google.protobuf.Timestamp } var file_gitpod_v1_prebuild_proto_depIdxs = []int32{ - 13, // 0: gitpod.v1.GetPrebuildResponse.prebuild:type_name -> gitpod.v1.Prebuild - 18, // 1: gitpod.v1.ListPrebuildsRequest.pagination:type_name -> gitpod.v1.PaginationRequest - 19, // 2: gitpod.v1.ListPrebuildsResponse.pagination:type_name -> gitpod.v1.PaginationResponse - 13, // 3: gitpod.v1.ListPrebuildsResponse.prebuilds:type_name -> gitpod.v1.Prebuild - 13, // 4: gitpod.v1.WatchPrebuildResponse.prebuild:type_name -> gitpod.v1.Prebuild - 18, // 5: gitpod.v1.ListOrganizationPrebuildsRequest.pagination:type_name -> gitpod.v1.PaginationRequest - 16, // 6: gitpod.v1.ListOrganizationPrebuildsRequest.filter:type_name -> gitpod.v1.ListOrganizationPrebuildsRequest.Filter - 19, // 7: gitpod.v1.ListOrganizationPrebuildsResponse.pagination:type_name -> gitpod.v1.PaginationResponse - 13, // 8: gitpod.v1.ListOrganizationPrebuildsResponse.prebuilds:type_name -> gitpod.v1.Prebuild - 20, // 9: gitpod.v1.Prebuild.commit:type_name -> gitpod.v1.Commit - 14, // 10: gitpod.v1.Prebuild.status:type_name -> gitpod.v1.PrebuildStatus - 15, // 11: gitpod.v1.PrebuildStatus.phase:type_name -> gitpod.v1.PrebuildPhase - 21, // 12: gitpod.v1.PrebuildStatus.start_time:type_name -> google.protobuf.Timestamp - 0, // 13: gitpod.v1.PrebuildPhase.name:type_name -> gitpod.v1.PrebuildPhase.Phase - 0, // 14: gitpod.v1.ListOrganizationPrebuildsRequest.Filter.status:type_name -> gitpod.v1.PrebuildPhase.Phase - 17, // 15: gitpod.v1.ListOrganizationPrebuildsRequest.Filter.configuration:type_name -> gitpod.v1.ListOrganizationPrebuildsRequest.Filter.Configuration - 5, // 16: gitpod.v1.PrebuildService.StartPrebuild:input_type -> gitpod.v1.StartPrebuildRequest - 7, // 17: gitpod.v1.PrebuildService.CancelPrebuild:input_type -> gitpod.v1.CancelPrebuildRequest - 1, // 18: gitpod.v1.PrebuildService.GetPrebuild:input_type -> gitpod.v1.GetPrebuildRequest - 3, // 19: gitpod.v1.PrebuildService.ListPrebuilds:input_type -> gitpod.v1.ListPrebuildsRequest - 9, // 20: gitpod.v1.PrebuildService.WatchPrebuild:input_type -> gitpod.v1.WatchPrebuildRequest - 11, // 21: gitpod.v1.PrebuildService.ListOrganizationPrebuilds:input_type -> gitpod.v1.ListOrganizationPrebuildsRequest - 6, // 22: gitpod.v1.PrebuildService.StartPrebuild:output_type -> gitpod.v1.StartPrebuildResponse - 8, // 23: gitpod.v1.PrebuildService.CancelPrebuild:output_type -> gitpod.v1.CancelPrebuildResponse - 2, // 24: gitpod.v1.PrebuildService.GetPrebuild:output_type -> gitpod.v1.GetPrebuildResponse - 4, // 25: gitpod.v1.PrebuildService.ListPrebuilds:output_type -> gitpod.v1.ListPrebuildsResponse - 10, // 26: gitpod.v1.PrebuildService.WatchPrebuild:output_type -> gitpod.v1.WatchPrebuildResponse - 12, // 27: gitpod.v1.PrebuildService.ListOrganizationPrebuilds:output_type -> gitpod.v1.ListOrganizationPrebuildsResponse + 14, // 0: gitpod.v1.GetPrebuildResponse.prebuild:type_name -> gitpod.v1.Prebuild + 19, // 1: gitpod.v1.ListPrebuildsRequest.pagination:type_name -> gitpod.v1.PaginationRequest + 20, // 2: gitpod.v1.ListPrebuildsResponse.pagination:type_name -> gitpod.v1.PaginationResponse + 14, // 3: gitpod.v1.ListPrebuildsResponse.prebuilds:type_name -> gitpod.v1.Prebuild + 14, // 4: gitpod.v1.WatchPrebuildResponse.prebuild:type_name -> gitpod.v1.Prebuild + 19, // 5: gitpod.v1.ListOrganizationPrebuildsRequest.pagination:type_name -> gitpod.v1.PaginationRequest + 17, // 6: gitpod.v1.ListOrganizationPrebuildsRequest.filter:type_name -> gitpod.v1.ListOrganizationPrebuildsRequest.Filter + 20, // 7: gitpod.v1.ListOrganizationPrebuildsResponse.pagination:type_name -> gitpod.v1.PaginationResponse + 14, // 8: gitpod.v1.ListOrganizationPrebuildsResponse.prebuilds:type_name -> gitpod.v1.Prebuild + 21, // 9: gitpod.v1.Prebuild.commit:type_name -> gitpod.v1.Commit + 15, // 10: gitpod.v1.Prebuild.status:type_name -> gitpod.v1.PrebuildStatus + 16, // 11: gitpod.v1.PrebuildStatus.phase:type_name -> gitpod.v1.PrebuildPhase + 22, // 12: gitpod.v1.PrebuildStatus.start_time:type_name -> google.protobuf.Timestamp + 1, // 13: gitpod.v1.PrebuildPhase.name:type_name -> gitpod.v1.PrebuildPhase.Phase + 0, // 14: gitpod.v1.ListOrganizationPrebuildsRequest.Filter.state:type_name -> gitpod.v1.ListOrganizationPrebuildsRequest.Filter.State + 18, // 15: gitpod.v1.ListOrganizationPrebuildsRequest.Filter.configuration:type_name -> gitpod.v1.ListOrganizationPrebuildsRequest.Filter.Configuration + 6, // 16: gitpod.v1.PrebuildService.StartPrebuild:input_type -> gitpod.v1.StartPrebuildRequest + 8, // 17: gitpod.v1.PrebuildService.CancelPrebuild:input_type -> gitpod.v1.CancelPrebuildRequest + 2, // 18: gitpod.v1.PrebuildService.GetPrebuild:input_type -> gitpod.v1.GetPrebuildRequest + 4, // 19: gitpod.v1.PrebuildService.ListPrebuilds:input_type -> gitpod.v1.ListPrebuildsRequest + 10, // 20: gitpod.v1.PrebuildService.WatchPrebuild:input_type -> gitpod.v1.WatchPrebuildRequest + 12, // 21: gitpod.v1.PrebuildService.ListOrganizationPrebuilds:input_type -> gitpod.v1.ListOrganizationPrebuildsRequest + 7, // 22: gitpod.v1.PrebuildService.StartPrebuild:output_type -> gitpod.v1.StartPrebuildResponse + 9, // 23: gitpod.v1.PrebuildService.CancelPrebuild:output_type -> gitpod.v1.CancelPrebuildResponse + 3, // 24: gitpod.v1.PrebuildService.GetPrebuild:output_type -> gitpod.v1.GetPrebuildResponse + 5, // 25: gitpod.v1.PrebuildService.ListPrebuilds:output_type -> gitpod.v1.ListPrebuildsResponse + 11, // 26: gitpod.v1.PrebuildService.WatchPrebuild:output_type -> gitpod.v1.WatchPrebuildResponse + 13, // 27: gitpod.v1.PrebuildService.ListOrganizationPrebuilds:output_type -> gitpod.v1.ListOrganizationPrebuildsResponse 22, // [22:28] is the sub-list for method output_type 16, // [16:22] is the sub-list for method input_type 16, // [16:16] is the sub-list for extension type_name @@ -1567,7 +1628,7 @@ func file_gitpod_v1_prebuild_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_gitpod_v1_prebuild_proto_rawDesc, - NumEnums: 1, + NumEnums: 2, NumMessages: 17, NumExtensions: 0, NumServices: 1, diff --git a/components/public-api/typescript-common/src/public-api-converter.ts b/components/public-api/typescript-common/src/public-api-converter.ts index f7fb4291e39632..7544312096e18e 100644 --- a/components/public-api/typescript-common/src/public-api-converter.ts +++ b/components/public-api/typescript-common/src/public-api-converter.ts @@ -97,6 +97,7 @@ import { PrebuildStatus, PrebuildPhase, PrebuildPhase_Phase, + ListOrganizationPrebuildsRequest_Filter_State as PrebuildFilterState, } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; import { ApplicationError, ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error"; import { InvalidGitpodYMLError, RepositoryNotFoundError, UnauthorizedRepositoryAccessError } from "./public-api-errors"; @@ -1147,20 +1148,14 @@ export class PublicAPIConverter { return PrebuildPhase_Phase.UNSPECIFIED; } - fromPrebuildPhase(status: PrebuildPhase_Phase): PrebuiltWorkspaceState | undefined { - switch (status) { - case PrebuildPhase_Phase.QUEUED: - return "queued"; - case PrebuildPhase_Phase.BUILDING: - return "building"; - case PrebuildPhase_Phase.ABORTED: - return "aborted"; - case PrebuildPhase_Phase.TIMEOUT: - return "timeout"; - case PrebuildPhase_Phase.AVAILABLE: - return "available"; - case PrebuildPhase_Phase.FAILED: + fromPrebuildFilterState(state: PrebuildFilterState) { + switch (state) { + case PrebuildFilterState.SUCCEEDED: + return "succeeded"; + case PrebuildFilterState.FAILED: return "failed"; + case PrebuildFilterState.UNFINISHED: + return "unfinished"; } return undefined; } diff --git a/components/public-api/typescript/src/gitpod/v1/prebuild_connect.ts b/components/public-api/typescript/src/gitpod/v1/prebuild_connect.ts index 0f295c1be25b58..87e984c750b577 100644 --- a/components/public-api/typescript/src/gitpod/v1/prebuild_connect.ts +++ b/components/public-api/typescript/src/gitpod/v1/prebuild_connect.ts @@ -9,70 +9,83 @@ /* eslint-disable */ // @ts-nocheck -import { CancelPrebuildRequest, CancelPrebuildResponse, GetPrebuildRequest, GetPrebuildResponse, ListOrganizationPrebuildsRequest, ListOrganizationPrebuildsResponse, ListPrebuildsRequest, ListPrebuildsResponse, StartPrebuildRequest, StartPrebuildResponse, WatchPrebuildRequest, WatchPrebuildResponse } from "./prebuild_pb.js"; +import { + CancelPrebuildRequest, + CancelPrebuildResponse, + GetPrebuildRequest, + GetPrebuildResponse, + ListOrganizationPrebuildsRequest, + ListOrganizationPrebuildsResponse, + ListPrebuildsRequest, + ListPrebuildsResponse, + StartPrebuildRequest, + StartPrebuildResponse, + WatchPrebuildRequest, + WatchPrebuildResponse, +} from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; import { MethodKind } from "@bufbuild/protobuf"; /** * @generated from service gitpod.v1.PrebuildService */ export const PrebuildService = { - typeName: "gitpod.v1.PrebuildService", - methods: { - /** - * @generated from rpc gitpod.v1.PrebuildService.StartPrebuild - */ - startPrebuild: { - name: "StartPrebuild", - I: StartPrebuildRequest, - O: StartPrebuildResponse, - kind: MethodKind.Unary, + typeName: "gitpod.v1.PrebuildService", + methods: { + /** + * @generated from rpc gitpod.v1.PrebuildService.StartPrebuild + */ + startPrebuild: { + name: "StartPrebuild", + I: StartPrebuildRequest, + O: StartPrebuildResponse, + kind: MethodKind.Unary, + }, + /** + * @generated from rpc gitpod.v1.PrebuildService.CancelPrebuild + */ + cancelPrebuild: { + name: "CancelPrebuild", + I: CancelPrebuildRequest, + O: CancelPrebuildResponse, + kind: MethodKind.Unary, + }, + /** + * @generated from rpc gitpod.v1.PrebuildService.GetPrebuild + */ + getPrebuild: { + name: "GetPrebuild", + I: GetPrebuildRequest, + O: GetPrebuildResponse, + kind: MethodKind.Unary, + }, + /** + * @generated from rpc gitpod.v1.PrebuildService.ListPrebuilds + */ + listPrebuilds: { + name: "ListPrebuilds", + I: ListPrebuildsRequest, + O: ListPrebuildsResponse, + kind: MethodKind.Unary, + }, + /** + * @generated from rpc gitpod.v1.PrebuildService.WatchPrebuild + */ + watchPrebuild: { + name: "WatchPrebuild", + I: WatchPrebuildRequest, + O: WatchPrebuildResponse, + kind: MethodKind.ServerStreaming, + }, + /** + * ListOrganizationPrebuilds lists all prebuilds of an organization + * + * @generated from rpc gitpod.v1.PrebuildService.ListOrganizationPrebuilds + */ + listOrganizationPrebuilds: { + name: "ListOrganizationPrebuilds", + I: ListOrganizationPrebuildsRequest, + O: ListOrganizationPrebuildsResponse, + kind: MethodKind.Unary, + }, }, - /** - * @generated from rpc gitpod.v1.PrebuildService.CancelPrebuild - */ - cancelPrebuild: { - name: "CancelPrebuild", - I: CancelPrebuildRequest, - O: CancelPrebuildResponse, - kind: MethodKind.Unary, - }, - /** - * @generated from rpc gitpod.v1.PrebuildService.GetPrebuild - */ - getPrebuild: { - name: "GetPrebuild", - I: GetPrebuildRequest, - O: GetPrebuildResponse, - kind: MethodKind.Unary, - }, - /** - * @generated from rpc gitpod.v1.PrebuildService.ListPrebuilds - */ - listPrebuilds: { - name: "ListPrebuilds", - I: ListPrebuildsRequest, - O: ListPrebuildsResponse, - kind: MethodKind.Unary, - }, - /** - * @generated from rpc gitpod.v1.PrebuildService.WatchPrebuild - */ - watchPrebuild: { - name: "WatchPrebuild", - I: WatchPrebuildRequest, - O: WatchPrebuildResponse, - kind: MethodKind.ServerStreaming, - }, - /** - * ListOrganizationPrebuilds lists all prebuilds of an organization - * - * @generated from rpc gitpod.v1.PrebuildService.ListOrganizationPrebuilds - */ - listOrganizationPrebuilds: { - name: "ListOrganizationPrebuilds", - I: ListOrganizationPrebuildsRequest, - O: ListOrganizationPrebuildsResponse, - kind: MethodKind.Unary, - }, - } } as const; diff --git a/components/public-api/typescript/src/gitpod/v1/prebuild_pb.ts b/components/public-api/typescript/src/gitpod/v1/prebuild_pb.ts index a3d449a497ada3..20a11a8047c87b 100644 --- a/components/public-api/typescript/src/gitpod/v1/prebuild_pb.ts +++ b/components/public-api/typescript/src/gitpod/v1/prebuild_pb.ts @@ -479,9 +479,9 @@ export class ListOrganizationPrebuildsRequest extends Message { /** - * @generated from field: gitpod.v1.PrebuildPhase.Phase status = 1; + * @generated from field: gitpod.v1.ListOrganizationPrebuildsRequest.Filter.State state = 1; */ - status = PrebuildPhase_Phase.UNSPECIFIED; + state = ListOrganizationPrebuildsRequest_Filter_State.UNSPECIFIED; /** * @generated from field: gitpod.v1.ListOrganizationPrebuildsRequest.Filter.Configuration configuration = 2; @@ -504,7 +504,7 @@ export class ListOrganizationPrebuildsRequest_Filter extends Message [ - { no: 1, name: "status", kind: "enum", T: proto3.getEnumType(PrebuildPhase_Phase) }, + { no: 1, name: "state", kind: "enum", T: proto3.getEnumType(ListOrganizationPrebuildsRequest_Filter_State) }, { no: 2, name: "configuration", kind: "message", T: ListOrganizationPrebuildsRequest_Filter_Configuration }, { no: 3, name: "search_term", kind: "scalar", T: 9 /* ScalarType.STRING */ }, ]); @@ -526,6 +526,38 @@ export class ListOrganizationPrebuildsRequest_Filter extends Message Date: Thu, 25 Jan 2024 20:22:47 +0000 Subject: [PATCH 07/49] fix path --- .../public-api/typescript/src/gitpod/v1/prebuild_connect.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/public-api/typescript/src/gitpod/v1/prebuild_connect.ts b/components/public-api/typescript/src/gitpod/v1/prebuild_connect.ts index 87e984c750b577..bc22b0740944b2 100644 --- a/components/public-api/typescript/src/gitpod/v1/prebuild_connect.ts +++ b/components/public-api/typescript/src/gitpod/v1/prebuild_connect.ts @@ -22,7 +22,7 @@ import { StartPrebuildResponse, WatchPrebuildRequest, WatchPrebuildResponse, -} from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; +} from "./prebuild_pb.js"; import { MethodKind } from "@bufbuild/protobuf"; /** From eaa2c1f1f99848552bde2c877ea6f99b0840ba83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Fri, 26 Jan 2024 20:17:10 +0000 Subject: [PATCH 08/49] Add configuration ID filtering --- .../prebuilds/organization-prebuilds-query.ts | 3 ++- .../src/prebuilds/list/PrebuildList.tsx | 22 +++++++++++++++++-- .../src/prebuilds/list/PrebuildTable.tsx | 11 +++++----- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/components/dashboard/src/data/prebuilds/organization-prebuilds-query.ts b/components/dashboard/src/data/prebuilds/organization-prebuilds-query.ts index e8bece15af378b..55db64498ac68a 100644 --- a/components/dashboard/src/data/prebuilds/organization-prebuilds-query.ts +++ b/components/dashboard/src/data/prebuilds/organization-prebuilds-query.ts @@ -9,9 +9,10 @@ import { prebuildClient } from "../../service/public-api"; import { ListOrganizationPrebuildsRequest_Filter } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; import { useCurrentOrg } from "../organizations/orgs-query"; import { PlainMessage } from "@bufbuild/protobuf"; +import type { DeepPartial } from "@gitpod/gitpod-protocol/lib/util/deep-partial"; type Args = { - filter: Partial>; + filter: DeepPartial>; pageSize: number; }; export const useListOrganizationPrebuildsQuery = ({ filter, pageSize }: Args) => { diff --git a/components/dashboard/src/prebuilds/list/PrebuildList.tsx b/components/dashboard/src/prebuilds/list/PrebuildList.tsx index 6d011f284bb1f1..aec4c6081eb87a 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildList.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildList.tsx @@ -15,11 +15,13 @@ import { PrebuildsTable } from "./PrebuildTable"; import { LoadingState } from "@podkit/loading/LoadingState"; import { useListOrganizationPrebuildsQuery } from "../../data/prebuilds/organization-prebuilds-query"; import { ListOrganizationPrebuildsRequest_Filter_State } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; +import { validate } from "uuid"; const STATUS_FILTER_VALUES = ["succeeded", "failed", "unfinished", undefined] as const; // undefined means any status export type STATUS_OPTION = typeof STATUS_FILTER_VALUES[number]; export type Filter = { status?: STATUS_OPTION; + configurationId?: string; }; const PrebuildsListPage: FC = () => { @@ -30,6 +32,7 @@ const PrebuildsListPage: FC = () => { const params = useQueryParams(); const [searchTerm, setSearchTerm, searchTermDebounced] = useStateWithDebounce(params.get("search") ?? ""); const [statusFilter, setPrebuildsFilter] = useState(parseStatus(params)); + const configurationFilter = useMemo(() => parseConfigurationId(params), [params]); const handleFilterChange = useCallback((filter: Filter) => { setPrebuildsFilter(filter.status); @@ -37,8 +40,9 @@ const PrebuildsListPage: FC = () => { const filter = useMemo(() => { return { status: statusFilter, + configurationId: configurationFilter, }; - }, [statusFilter]); + }, [configurationFilter, statusFilter]); useEffect(() => { const params = new URLSearchParams(); @@ -50,9 +54,13 @@ const PrebuildsListPage: FC = () => { params.set("prebuilds", statusFilter); } + if (configurationFilter) { + params.set("configurationId", configurationFilter); + } + params.toString(); history.replace({ search: `?${params.toString()}` }); - }, [history, statusFilter, searchTermDebounced]); + }, [history, statusFilter, searchTermDebounced, configurationFilter]); // TODO: handle isError case const { data, isLoading, isFetching, isFetchingNextPage, isPreviousData, hasNextPage, fetchNextPage } = @@ -60,6 +68,7 @@ const PrebuildsListPage: FC = () => { filter: { searchTerm: searchTermDebounced, state: toApiStatus(filter.status), + ...(configurationFilter ? { configuration: { id: configurationFilter } } : {}), }, pageSize: 30, }); @@ -128,4 +137,13 @@ const parseStatus = (params: URLSearchParams): STATUS_OPTION => { return undefined; }; +const parseConfigurationId = (params: URLSearchParams): string | undefined => { + const configuration = params.get("configurationId"); + if (configuration && validate(configuration)) { + return configuration; + } + + return undefined; +}; + export default PrebuildsListPage; diff --git a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx index 17bc37e575fc5a..f10a4d3222a47c 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx @@ -57,19 +57,20 @@ export const PrebuildsTable: FC = ({ value={filter?.status} onValueChange={(status) => { if (status === "any") { - onFilterChange({ status: undefined }); + onFilterChange({ ...filter, status: undefined }); return; } - onFilterChange({ status: status as STATUS_OPTION }); + onFilterChange({ ...filter, status: status as STATUS_OPTION }); }} > - Any - Failed - Succeeded + All + Failing + Successfull + In progress
From 0d045e6526913a0a52bb2dc355cf45b3ddb911aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 29 Jan 2024 07:58:01 +0000 Subject: [PATCH 09/49] Prebuild list error state --- .../src/prebuilds/list/PrebuildList.tsx | 31 +++++++++++++------ ...stState.tsx => PrebuildListEmptyState.tsx} | 2 +- .../prebuilds/list/PrebuildListErrorState.tsx | 23 ++++++++++++++ 3 files changed, 45 insertions(+), 11 deletions(-) rename components/dashboard/src/prebuilds/list/{PrebuildEmptyListState.tsx => PrebuildListEmptyState.tsx} (88%) create mode 100644 components/dashboard/src/prebuilds/list/PrebuildListErrorState.tsx diff --git a/components/dashboard/src/prebuilds/list/PrebuildList.tsx b/components/dashboard/src/prebuilds/list/PrebuildList.tsx index aec4c6081eb87a..b4c86523788fb8 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildList.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildList.tsx @@ -9,7 +9,8 @@ import { useHistory } from "react-router-dom"; import { PageHeading } from "@podkit/layout/PageHeading"; import { useDocumentTitle } from "../../hooks/use-document-title"; import { useQueryParams } from "../../hooks/use-query-params"; -import { PrebuildListEmptyState } from "./PrebuildEmptyListState"; +import { PrebuildListEmptyState } from "./PrebuildListEmptyState"; +import { PrebuildListErrorState } from "./PrebuildListErrorState"; import { useStateWithDebounce } from "../../hooks/use-state-with-debounce"; import { PrebuildsTable } from "./PrebuildTable"; import { LoadingState } from "@podkit/loading/LoadingState"; @@ -63,15 +64,24 @@ const PrebuildsListPage: FC = () => { }, [history, statusFilter, searchTermDebounced, configurationFilter]); // TODO: handle isError case - const { data, isLoading, isFetching, isFetchingNextPage, isPreviousData, hasNextPage, fetchNextPage } = - useListOrganizationPrebuildsQuery({ - filter: { - searchTerm: searchTermDebounced, - state: toApiStatus(filter.status), - ...(configurationFilter ? { configuration: { id: configurationFilter } } : {}), - }, - pageSize: 30, - }); + const { + data, + isLoading, + isFetching, + isFetchingNextPage, + isPreviousData, + hasNextPage, + fetchNextPage, + isError, + error, + } = useListOrganizationPrebuildsQuery({ + filter: { + searchTerm: searchTermDebounced, + state: toApiStatus(filter.status), + ...(configurationFilter ? { configuration: { id: configurationFilter } } : {}), + }, + pageSize: 30, + }); const prebuilds = useMemo(() => { return data?.pages.map((page) => page.prebuilds).flat() ?? []; @@ -109,6 +119,7 @@ const PrebuildsListPage: FC = () => { )} {!showTable && !isLoading && } + {isError && }
); diff --git a/components/dashboard/src/prebuilds/list/PrebuildEmptyListState.tsx b/components/dashboard/src/prebuilds/list/PrebuildListEmptyState.tsx similarity index 88% rename from components/dashboard/src/prebuilds/list/PrebuildEmptyListState.tsx rename to components/dashboard/src/prebuilds/list/PrebuildListEmptyState.tsx index 11979b70224051..24a82c22491394 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildEmptyListState.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildListEmptyState.tsx @@ -14,7 +14,7 @@ export const PrebuildListEmptyState: FC = () => {
No prebuilds yet - Go on, create Configurations and turn them on, I'll be waiting here... + Go on, import some repositories and turn prebuilds on. We'll be patiently waiting.
diff --git a/components/dashboard/src/prebuilds/list/PrebuildListErrorState.tsx b/components/dashboard/src/prebuilds/list/PrebuildListErrorState.tsx new file mode 100644 index 00000000000000..0e57d97396bf40 --- /dev/null +++ b/components/dashboard/src/prebuilds/list/PrebuildListErrorState.tsx @@ -0,0 +1,23 @@ +/** + * Copyright (c) 2024 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License.AGPL.txt in the project root for license information. + */ + +import { FC } from "react"; +import { Heading2, Subheading } from "@podkit/typography/Headings"; +import { cn } from "@podkit/lib/cn"; + +type Props = { + error: unknown; +}; +export const PrebuildListErrorState: FC = ({ error }: Props) => { + return ( +
+
+ Prebuilds failed to load + Error: {error}. +
+
+ ); +}; From f9b46c84f96fd205148ffeda5adb499dbf71c76d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 29 Jan 2024 08:49:17 +0000 Subject: [PATCH 10/49] Protobuf sorting definition --- .../public-api/gitpod/v1/prebuild.proto | 2 + components/public-api/go/v1/prebuild.pb.go | 441 +++++++++--------- .../src/gitpod/v1/prebuild_connect.ts | 131 +++--- .../typescript/src/gitpod/v1/prebuild_pb.ts | 7 + 4 files changed, 296 insertions(+), 285 deletions(-) diff --git a/components/public-api/gitpod/v1/prebuild.proto b/components/public-api/gitpod/v1/prebuild.proto index e24796e4cf3045..745a2f220125b7 100644 --- a/components/public-api/gitpod/v1/prebuild.proto +++ b/components/public-api/gitpod/v1/prebuild.proto @@ -4,6 +4,7 @@ package gitpod.v1; import "gitpod/v1/pagination.proto"; import "gitpod/v1/scm.proto"; +import "gitpod/v1/sorting.proto"; import "google/protobuf/timestamp.proto"; option go_package = "github.com/gitpod-io/gitpod/components/public-api/go/v1"; @@ -85,6 +86,7 @@ message ListOrganizationPrebuildsRequest { PaginationRequest pagination = 1; string organization_id = 2; Filter filter = 3; + Sort sort = 4; } message ListOrganizationPrebuildsResponse { diff --git a/components/public-api/go/v1/prebuild.pb.go b/components/public-api/go/v1/prebuild.pb.go index abcd7d7d94f8d6..1196a9aee98cd4 100644 --- a/components/public-api/go/v1/prebuild.pb.go +++ b/components/public-api/go/v1/prebuild.pb.go @@ -686,6 +686,7 @@ type ListOrganizationPrebuildsRequest struct { Pagination *PaginationRequest `protobuf:"bytes,1,opt,name=pagination,proto3" json:"pagination,omitempty"` OrganizationId string `protobuf:"bytes,2,opt,name=organization_id,json=organizationId,proto3" json:"organization_id,omitempty"` Filter *ListOrganizationPrebuildsRequest_Filter `protobuf:"bytes,3,opt,name=filter,proto3" json:"filter,omitempty"` + Sort *Sort `protobuf:"bytes,4,opt,name=sort,proto3" json:"sort,omitempty"` } func (x *ListOrganizationPrebuildsRequest) Reset() { @@ -741,6 +742,13 @@ func (x *ListOrganizationPrebuildsRequest) GetFilter() *ListOrganizationPrebuild return nil } +func (x *ListOrganizationPrebuildsRequest) GetSort() *Sort { + if x != nil { + return x.Sort + } + return nil +} + type ListOrganizationPrebuildsResponse struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1142,193 +1150,197 @@ var file_gitpod_v1_prebuild_proto_rawDesc = []byte{ 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x1a, 0x1a, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x76, 0x31, 0x2f, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x13, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6d, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x35, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x72, - 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, - 0x0b, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x22, 0x46, - 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x08, 0x70, 0x72, - 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x22, 0xbf, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x50, - 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, - 0x3c, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, - 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, - 0x63, 0x65, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, - 0x17, 0x0a, 0x07, 0x67, 0x69, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x67, 0x69, 0x74, 0x52, 0x65, 0x66, 0x22, 0x89, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, - 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, - 0x76, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x31, 0x0a, 0x09, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x18, 0x02, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, - 0x2e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x09, 0x70, 0x72, 0x65, 0x62, 0x75, - 0x69, 0x6c, 0x64, 0x73, 0x22, 0x5a, 0x0a, 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x65, - 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x74, 0x5f, 0x72, - 0x65, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x74, 0x52, 0x65, 0x66, - 0x22, 0x38, 0x0a, 0x15, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, - 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, - 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x22, 0x38, 0x0a, 0x15, 0x43, 0x61, - 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, - 0x6c, 0x64, 0x49, 0x64, 0x22, 0x18, 0x0a, 0x16, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x72, - 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6f, - 0x0a, 0x14, 0x57, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x21, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, - 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x70, - 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x10, 0x63, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x42, 0x07, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x22, - 0x48, 0x0a, 0x15, 0x57, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x62, - 0x75, 0x69, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x69, 0x74, - 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, - 0x08, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x22, 0xcf, 0x04, 0x0a, 0x20, 0x4c, 0x69, - 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, - 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, - 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, - 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, - 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, - 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x4a, 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, - 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, - 0x72, 0x1a, 0xf7, 0x02, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x4e, 0x0a, 0x05, - 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x38, 0x2e, 0x67, 0x69, - 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, - 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x66, 0x0a, 0x0d, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x74, - 0x65, 0x72, 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x61, 0x72, 0x63, - 0x68, 0x54, 0x65, 0x72, 0x6d, 0x1a, 0x37, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0x5b, - 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x45, - 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, - 0x0a, 0x0f, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, - 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, - 0x4c, 0x45, 0x44, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, - 0x4e, 0x46, 0x49, 0x4e, 0x49, 0x53, 0x48, 0x45, 0x44, 0x10, 0x03, 0x22, 0x95, 0x01, 0x0a, 0x21, - 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, - 0x31, 0x2e, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x12, 0x31, 0x0a, 0x09, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, - 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x09, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, - 0x6c, 0x64, 0x73, 0x22, 0xae, 0x02, 0x0a, 0x08, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, - 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, - 0x12, 0x25, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, - 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x62, 0x61, 0x73, 0x65, 0x64, - 0x5f, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x62, 0x61, 0x73, 0x65, 0x64, 0x4f, 0x6e, 0x50, 0x72, - 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x29, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, - 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, - 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, - 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x55, 0x72, - 0x6c, 0x12, 0x31, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x19, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, - 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, - 0x61, 0x74, 0x75, 0x73, 0x22, 0x95, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, - 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x50, 0x68, 0x61, 0x73, 0x65, - 0x52, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, - 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, - 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xd7, 0x01, 0x0a, - 0x0d, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x50, 0x68, 0x61, 0x73, 0x65, 0x12, 0x32, - 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x67, - 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, - 0x64, 0x50, 0x68, 0x61, 0x73, 0x65, 0x2e, 0x50, 0x68, 0x61, 0x73, 0x65, 0x52, 0x04, 0x6e, 0x61, - 0x6d, 0x65, 0x22, 0x91, 0x01, 0x0a, 0x05, 0x50, 0x68, 0x61, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x11, - 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, - 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x51, 0x55, 0x45, - 0x55, 0x45, 0x44, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x42, - 0x55, 0x49, 0x4c, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x48, 0x41, - 0x53, 0x45, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, - 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x04, 0x12, - 0x13, 0x0a, 0x0f, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, - 0x4c, 0x45, 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x46, 0x41, - 0x49, 0x4c, 0x45, 0x44, 0x10, 0x06, 0x32, 0xb8, 0x04, 0x0a, 0x0f, 0x50, 0x72, 0x65, 0x62, 0x75, - 0x69, 0x6c, 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x54, 0x0a, 0x0d, 0x53, 0x74, - 0x61, 0x72, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x1f, 0x2e, 0x67, 0x69, - 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x65, - 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, - 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, - 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x57, 0x0a, 0x0e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, - 0x6c, 0x64, 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x43, - 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, - 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x47, 0x65, 0x74, - 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, - 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, - 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x0d, 0x4c, 0x69, 0x73, - 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, - 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, - 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, - 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x62, - 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, - 0x56, 0x0a, 0x0d, 0x57, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, - 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, - 0x63, 0x68, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, - 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x78, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4f, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x17, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x76, + 0x31, 0x2f, 0x73, 0x6f, 0x72, 0x74, 0x69, 0x6e, 0x67, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, + 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x22, 0x35, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, + 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, + 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x22, 0x46, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, 0x72, + 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x2f, + 0x0a, 0x08, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x13, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, + 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x08, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x22, + 0xbf, 0x01, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, + 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x25, 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, + 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x29, 0x0a, + 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x74, 0x5f, + 0x72, 0x65, 0x66, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x67, 0x69, 0x74, 0x52, 0x65, + 0x66, 0x22, 0x89, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, + 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x0a, 0x70, + 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x69, + 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x52, 0x0a, + 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, 0x0a, 0x09, 0x70, 0x72, + 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, + 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, + 0x6c, 0x64, 0x52, 0x09, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x22, 0x5a, 0x0a, + 0x14, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, + 0x12, 0x17, 0x0a, 0x07, 0x67, 0x69, 0x74, 0x5f, 0x72, 0x65, 0x66, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x06, 0x67, 0x69, 0x74, 0x52, 0x65, 0x66, 0x22, 0x38, 0x0a, 0x15, 0x53, 0x74, 0x61, + 0x72, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, + 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, + 0x64, 0x49, 0x64, 0x22, 0x38, 0x0a, 0x15, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x72, 0x65, + 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x0b, + 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x22, 0x18, 0x0a, + 0x16, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6f, 0x0a, 0x14, 0x57, 0x61, 0x74, 0x63, 0x68, + 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x21, 0x0a, 0x0b, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0a, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x49, 0x64, 0x12, 0x2b, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0f, + 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x42, + 0x07, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x22, 0x48, 0x0a, 0x15, 0x57, 0x61, 0x74, 0x63, + 0x68, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x2f, 0x0a, 0x08, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x08, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, + 0x6c, 0x64, 0x22, 0xf4, 0x04, 0x0a, 0x20, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, + 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x69, + 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0f, 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x6f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x4a, + 0x0a, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x32, + 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, - 0x69, 0x6c, 0x64, 0x73, 0x12, 0x2b, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x2c, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, + 0x65, 0x72, 0x52, 0x06, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x23, 0x0a, 0x04, 0x73, 0x6f, + 0x72, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, + 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x6f, 0x72, 0x74, 0x52, 0x04, 0x73, 0x6f, 0x72, 0x74, 0x1a, + 0xf7, 0x02, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x4e, 0x0a, 0x05, 0x73, 0x74, + 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x38, 0x2e, 0x67, 0x69, 0x74, 0x70, + 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, + 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x53, 0x74, + 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x66, 0x0a, 0x0d, 0x63, 0x6f, + 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x40, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, + 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, + 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x0d, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x5f, 0x74, 0x65, 0x72, + 0x6d, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x54, + 0x65, 0x72, 0x6d, 0x1a, 0x37, 0x0a, 0x0d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x02, 0x69, 0x64, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x62, 0x72, 0x61, 0x6e, 0x63, 0x68, 0x22, 0x5b, 0x0a, 0x05, + 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, + 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x13, 0x0a, 0x0f, + 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x55, 0x43, 0x43, 0x45, 0x45, 0x44, 0x45, 0x44, 0x10, + 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x45, + 0x44, 0x10, 0x02, 0x12, 0x14, 0x0a, 0x10, 0x53, 0x54, 0x41, 0x54, 0x45, 0x5f, 0x55, 0x4e, 0x46, + 0x49, 0x4e, 0x49, 0x53, 0x48, 0x45, 0x44, 0x10, 0x03, 0x22, 0x95, 0x01, 0x0a, 0x21, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, - 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, - 0x00, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, - 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x75, 0x62, 0x6c, - 0x69, 0x63, 0x2d, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x3d, 0x0a, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, + 0x50, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x52, 0x0a, 0x70, 0x61, 0x67, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x31, + 0x0a, 0x09, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, + 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x09, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x73, 0x22, 0xae, 0x02, 0x0a, 0x08, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x25, + 0x0a, 0x0c, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, 0x52, 0x0b, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x49, 0x64, 0x12, 0x2f, 0x0a, 0x14, 0x62, 0x61, 0x73, 0x65, 0x64, 0x5f, 0x6f, + 0x6e, 0x5f, 0x70, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x11, 0x62, 0x61, 0x73, 0x65, 0x64, 0x4f, 0x6e, 0x50, 0x72, 0x65, 0x62, + 0x75, 0x69, 0x6c, 0x64, 0x49, 0x64, 0x12, 0x29, 0x0a, 0x10, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x12, 0x10, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, + 0x72, 0x65, 0x66, 0x12, 0x29, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x18, 0x06, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, + 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x1f, + 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x07, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74, 0x55, 0x72, 0x6c, 0x12, + 0x31, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x62, + 0x75, 0x69, 0x6c, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x22, 0x95, 0x01, 0x0a, 0x0e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x2e, 0x0a, 0x05, 0x70, 0x68, 0x61, 0x73, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x50, 0x68, 0x61, 0x73, 0x65, 0x52, 0x05, + 0x70, 0x68, 0x61, 0x73, 0x65, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, + 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xd7, 0x01, 0x0a, 0x0d, 0x50, + 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x50, 0x68, 0x61, 0x73, 0x65, 0x12, 0x32, 0x0a, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x67, 0x69, 0x74, + 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x50, + 0x68, 0x61, 0x73, 0x65, 0x2e, 0x50, 0x68, 0x61, 0x73, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x22, 0x91, 0x01, 0x0a, 0x05, 0x50, 0x68, 0x61, 0x73, 0x65, 0x12, 0x15, 0x0a, 0x11, 0x50, 0x48, + 0x41, 0x53, 0x45, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x51, 0x55, 0x45, 0x55, 0x45, + 0x44, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x42, 0x55, 0x49, + 0x4c, 0x44, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x48, 0x41, 0x53, 0x45, + 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x45, 0x44, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x50, 0x48, + 0x41, 0x53, 0x45, 0x5f, 0x54, 0x49, 0x4d, 0x45, 0x4f, 0x55, 0x54, 0x10, 0x04, 0x12, 0x13, 0x0a, + 0x0f, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, + 0x10, 0x05, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x48, 0x41, 0x53, 0x45, 0x5f, 0x46, 0x41, 0x49, 0x4c, + 0x45, 0x44, 0x10, 0x06, 0x32, 0xb8, 0x04, 0x0a, 0x0f, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, + 0x64, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x54, 0x0a, 0x0d, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x70, + 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, + 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, + 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x50, 0x72, 0x65, 0x62, + 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x57, + 0x0a, 0x0e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, + 0x12, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x61, 0x6e, + 0x63, 0x65, 0x6c, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x43, + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x4e, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x50, 0x72, + 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, + 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, + 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x50, + 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, + 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, + 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x70, + 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, + 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x56, 0x0a, + 0x0d, 0x57, 0x61, 0x74, 0x63, 0x68, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x12, 0x1f, + 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, 0x68, + 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x20, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x57, 0x61, 0x74, 0x63, + 0x68, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x78, 0x0a, 0x19, 0x4c, 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, + 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, + 0x64, 0x73, 0x12, 0x2b, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, + 0x72, 0x65, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2c, 0x2e, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x4f, 0x72, 0x67, 0x61, 0x6e, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x72, 0x65, 0x62, + 0x75, 0x69, 0x6c, 0x64, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, + 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, + 0x74, 0x70, 0x6f, 0x64, 0x2d, 0x69, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x70, 0x6f, 0x64, 0x2f, 0x63, + 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, + 0x2d, 0x61, 0x70, 0x69, 0x2f, 0x67, 0x6f, 0x2f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } var ( @@ -1367,8 +1379,9 @@ var file_gitpod_v1_prebuild_proto_goTypes = []interface{}{ (*ListOrganizationPrebuildsRequest_Filter_Configuration)(nil), // 18: gitpod.v1.ListOrganizationPrebuildsRequest.Filter.Configuration (*PaginationRequest)(nil), // 19: gitpod.v1.PaginationRequest (*PaginationResponse)(nil), // 20: gitpod.v1.PaginationResponse - (*Commit)(nil), // 21: gitpod.v1.Commit - (*timestamppb.Timestamp)(nil), // 22: google.protobuf.Timestamp + (*Sort)(nil), // 21: gitpod.v1.Sort + (*Commit)(nil), // 22: gitpod.v1.Commit + (*timestamppb.Timestamp)(nil), // 23: google.protobuf.Timestamp } var file_gitpod_v1_prebuild_proto_depIdxs = []int32{ 14, // 0: gitpod.v1.GetPrebuildResponse.prebuild:type_name -> gitpod.v1.Prebuild @@ -1378,32 +1391,33 @@ var file_gitpod_v1_prebuild_proto_depIdxs = []int32{ 14, // 4: gitpod.v1.WatchPrebuildResponse.prebuild:type_name -> gitpod.v1.Prebuild 19, // 5: gitpod.v1.ListOrganizationPrebuildsRequest.pagination:type_name -> gitpod.v1.PaginationRequest 17, // 6: gitpod.v1.ListOrganizationPrebuildsRequest.filter:type_name -> gitpod.v1.ListOrganizationPrebuildsRequest.Filter - 20, // 7: gitpod.v1.ListOrganizationPrebuildsResponse.pagination:type_name -> gitpod.v1.PaginationResponse - 14, // 8: gitpod.v1.ListOrganizationPrebuildsResponse.prebuilds:type_name -> gitpod.v1.Prebuild - 21, // 9: gitpod.v1.Prebuild.commit:type_name -> gitpod.v1.Commit - 15, // 10: gitpod.v1.Prebuild.status:type_name -> gitpod.v1.PrebuildStatus - 16, // 11: gitpod.v1.PrebuildStatus.phase:type_name -> gitpod.v1.PrebuildPhase - 22, // 12: gitpod.v1.PrebuildStatus.start_time:type_name -> google.protobuf.Timestamp - 1, // 13: gitpod.v1.PrebuildPhase.name:type_name -> gitpod.v1.PrebuildPhase.Phase - 0, // 14: gitpod.v1.ListOrganizationPrebuildsRequest.Filter.state:type_name -> gitpod.v1.ListOrganizationPrebuildsRequest.Filter.State - 18, // 15: gitpod.v1.ListOrganizationPrebuildsRequest.Filter.configuration:type_name -> gitpod.v1.ListOrganizationPrebuildsRequest.Filter.Configuration - 6, // 16: gitpod.v1.PrebuildService.StartPrebuild:input_type -> gitpod.v1.StartPrebuildRequest - 8, // 17: gitpod.v1.PrebuildService.CancelPrebuild:input_type -> gitpod.v1.CancelPrebuildRequest - 2, // 18: gitpod.v1.PrebuildService.GetPrebuild:input_type -> gitpod.v1.GetPrebuildRequest - 4, // 19: gitpod.v1.PrebuildService.ListPrebuilds:input_type -> gitpod.v1.ListPrebuildsRequest - 10, // 20: gitpod.v1.PrebuildService.WatchPrebuild:input_type -> gitpod.v1.WatchPrebuildRequest - 12, // 21: gitpod.v1.PrebuildService.ListOrganizationPrebuilds:input_type -> gitpod.v1.ListOrganizationPrebuildsRequest - 7, // 22: gitpod.v1.PrebuildService.StartPrebuild:output_type -> gitpod.v1.StartPrebuildResponse - 9, // 23: gitpod.v1.PrebuildService.CancelPrebuild:output_type -> gitpod.v1.CancelPrebuildResponse - 3, // 24: gitpod.v1.PrebuildService.GetPrebuild:output_type -> gitpod.v1.GetPrebuildResponse - 5, // 25: gitpod.v1.PrebuildService.ListPrebuilds:output_type -> gitpod.v1.ListPrebuildsResponse - 11, // 26: gitpod.v1.PrebuildService.WatchPrebuild:output_type -> gitpod.v1.WatchPrebuildResponse - 13, // 27: gitpod.v1.PrebuildService.ListOrganizationPrebuilds:output_type -> gitpod.v1.ListOrganizationPrebuildsResponse - 22, // [22:28] is the sub-list for method output_type - 16, // [16:22] is the sub-list for method input_type - 16, // [16:16] is the sub-list for extension type_name - 16, // [16:16] is the sub-list for extension extendee - 0, // [0:16] is the sub-list for field type_name + 21, // 7: gitpod.v1.ListOrganizationPrebuildsRequest.sort:type_name -> gitpod.v1.Sort + 20, // 8: gitpod.v1.ListOrganizationPrebuildsResponse.pagination:type_name -> gitpod.v1.PaginationResponse + 14, // 9: gitpod.v1.ListOrganizationPrebuildsResponse.prebuilds:type_name -> gitpod.v1.Prebuild + 22, // 10: gitpod.v1.Prebuild.commit:type_name -> gitpod.v1.Commit + 15, // 11: gitpod.v1.Prebuild.status:type_name -> gitpod.v1.PrebuildStatus + 16, // 12: gitpod.v1.PrebuildStatus.phase:type_name -> gitpod.v1.PrebuildPhase + 23, // 13: gitpod.v1.PrebuildStatus.start_time:type_name -> google.protobuf.Timestamp + 1, // 14: gitpod.v1.PrebuildPhase.name:type_name -> gitpod.v1.PrebuildPhase.Phase + 0, // 15: gitpod.v1.ListOrganizationPrebuildsRequest.Filter.state:type_name -> gitpod.v1.ListOrganizationPrebuildsRequest.Filter.State + 18, // 16: gitpod.v1.ListOrganizationPrebuildsRequest.Filter.configuration:type_name -> gitpod.v1.ListOrganizationPrebuildsRequest.Filter.Configuration + 6, // 17: gitpod.v1.PrebuildService.StartPrebuild:input_type -> gitpod.v1.StartPrebuildRequest + 8, // 18: gitpod.v1.PrebuildService.CancelPrebuild:input_type -> gitpod.v1.CancelPrebuildRequest + 2, // 19: gitpod.v1.PrebuildService.GetPrebuild:input_type -> gitpod.v1.GetPrebuildRequest + 4, // 20: gitpod.v1.PrebuildService.ListPrebuilds:input_type -> gitpod.v1.ListPrebuildsRequest + 10, // 21: gitpod.v1.PrebuildService.WatchPrebuild:input_type -> gitpod.v1.WatchPrebuildRequest + 12, // 22: gitpod.v1.PrebuildService.ListOrganizationPrebuilds:input_type -> gitpod.v1.ListOrganizationPrebuildsRequest + 7, // 23: gitpod.v1.PrebuildService.StartPrebuild:output_type -> gitpod.v1.StartPrebuildResponse + 9, // 24: gitpod.v1.PrebuildService.CancelPrebuild:output_type -> gitpod.v1.CancelPrebuildResponse + 3, // 25: gitpod.v1.PrebuildService.GetPrebuild:output_type -> gitpod.v1.GetPrebuildResponse + 5, // 26: gitpod.v1.PrebuildService.ListPrebuilds:output_type -> gitpod.v1.ListPrebuildsResponse + 11, // 27: gitpod.v1.PrebuildService.WatchPrebuild:output_type -> gitpod.v1.WatchPrebuildResponse + 13, // 28: gitpod.v1.PrebuildService.ListOrganizationPrebuilds:output_type -> gitpod.v1.ListOrganizationPrebuildsResponse + 23, // [23:29] is the sub-list for method output_type + 17, // [17:23] is the sub-list for method input_type + 17, // [17:17] is the sub-list for extension type_name + 17, // [17:17] is the sub-list for extension extendee + 0, // [0:17] is the sub-list for field type_name } func init() { file_gitpod_v1_prebuild_proto_init() } @@ -1413,6 +1427,7 @@ func file_gitpod_v1_prebuild_proto_init() { } file_gitpod_v1_pagination_proto_init() file_gitpod_v1_scm_proto_init() + file_gitpod_v1_sorting_proto_init() if !protoimpl.UnsafeEnabled { file_gitpod_v1_prebuild_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GetPrebuildRequest); i { diff --git a/components/public-api/typescript/src/gitpod/v1/prebuild_connect.ts b/components/public-api/typescript/src/gitpod/v1/prebuild_connect.ts index bc22b0740944b2..0f295c1be25b58 100644 --- a/components/public-api/typescript/src/gitpod/v1/prebuild_connect.ts +++ b/components/public-api/typescript/src/gitpod/v1/prebuild_connect.ts @@ -9,83 +9,70 @@ /* eslint-disable */ // @ts-nocheck -import { - CancelPrebuildRequest, - CancelPrebuildResponse, - GetPrebuildRequest, - GetPrebuildResponse, - ListOrganizationPrebuildsRequest, - ListOrganizationPrebuildsResponse, - ListPrebuildsRequest, - ListPrebuildsResponse, - StartPrebuildRequest, - StartPrebuildResponse, - WatchPrebuildRequest, - WatchPrebuildResponse, -} from "./prebuild_pb.js"; +import { CancelPrebuildRequest, CancelPrebuildResponse, GetPrebuildRequest, GetPrebuildResponse, ListOrganizationPrebuildsRequest, ListOrganizationPrebuildsResponse, ListPrebuildsRequest, ListPrebuildsResponse, StartPrebuildRequest, StartPrebuildResponse, WatchPrebuildRequest, WatchPrebuildResponse } from "./prebuild_pb.js"; import { MethodKind } from "@bufbuild/protobuf"; /** * @generated from service gitpod.v1.PrebuildService */ export const PrebuildService = { - typeName: "gitpod.v1.PrebuildService", - methods: { - /** - * @generated from rpc gitpod.v1.PrebuildService.StartPrebuild - */ - startPrebuild: { - name: "StartPrebuild", - I: StartPrebuildRequest, - O: StartPrebuildResponse, - kind: MethodKind.Unary, - }, - /** - * @generated from rpc gitpod.v1.PrebuildService.CancelPrebuild - */ - cancelPrebuild: { - name: "CancelPrebuild", - I: CancelPrebuildRequest, - O: CancelPrebuildResponse, - kind: MethodKind.Unary, - }, - /** - * @generated from rpc gitpod.v1.PrebuildService.GetPrebuild - */ - getPrebuild: { - name: "GetPrebuild", - I: GetPrebuildRequest, - O: GetPrebuildResponse, - kind: MethodKind.Unary, - }, - /** - * @generated from rpc gitpod.v1.PrebuildService.ListPrebuilds - */ - listPrebuilds: { - name: "ListPrebuilds", - I: ListPrebuildsRequest, - O: ListPrebuildsResponse, - kind: MethodKind.Unary, - }, - /** - * @generated from rpc gitpod.v1.PrebuildService.WatchPrebuild - */ - watchPrebuild: { - name: "WatchPrebuild", - I: WatchPrebuildRequest, - O: WatchPrebuildResponse, - kind: MethodKind.ServerStreaming, - }, - /** - * ListOrganizationPrebuilds lists all prebuilds of an organization - * - * @generated from rpc gitpod.v1.PrebuildService.ListOrganizationPrebuilds - */ - listOrganizationPrebuilds: { - name: "ListOrganizationPrebuilds", - I: ListOrganizationPrebuildsRequest, - O: ListOrganizationPrebuildsResponse, - kind: MethodKind.Unary, - }, + typeName: "gitpod.v1.PrebuildService", + methods: { + /** + * @generated from rpc gitpod.v1.PrebuildService.StartPrebuild + */ + startPrebuild: { + name: "StartPrebuild", + I: StartPrebuildRequest, + O: StartPrebuildResponse, + kind: MethodKind.Unary, }, + /** + * @generated from rpc gitpod.v1.PrebuildService.CancelPrebuild + */ + cancelPrebuild: { + name: "CancelPrebuild", + I: CancelPrebuildRequest, + O: CancelPrebuildResponse, + kind: MethodKind.Unary, + }, + /** + * @generated from rpc gitpod.v1.PrebuildService.GetPrebuild + */ + getPrebuild: { + name: "GetPrebuild", + I: GetPrebuildRequest, + O: GetPrebuildResponse, + kind: MethodKind.Unary, + }, + /** + * @generated from rpc gitpod.v1.PrebuildService.ListPrebuilds + */ + listPrebuilds: { + name: "ListPrebuilds", + I: ListPrebuildsRequest, + O: ListPrebuildsResponse, + kind: MethodKind.Unary, + }, + /** + * @generated from rpc gitpod.v1.PrebuildService.WatchPrebuild + */ + watchPrebuild: { + name: "WatchPrebuild", + I: WatchPrebuildRequest, + O: WatchPrebuildResponse, + kind: MethodKind.ServerStreaming, + }, + /** + * ListOrganizationPrebuilds lists all prebuilds of an organization + * + * @generated from rpc gitpod.v1.PrebuildService.ListOrganizationPrebuilds + */ + listOrganizationPrebuilds: { + name: "ListOrganizationPrebuilds", + I: ListOrganizationPrebuildsRequest, + O: ListOrganizationPrebuildsResponse, + kind: MethodKind.Unary, + }, + } } as const; diff --git a/components/public-api/typescript/src/gitpod/v1/prebuild_pb.ts b/components/public-api/typescript/src/gitpod/v1/prebuild_pb.ts index 20a11a8047c87b..0ac0bb7459c594 100644 --- a/components/public-api/typescript/src/gitpod/v1/prebuild_pb.ts +++ b/components/public-api/typescript/src/gitpod/v1/prebuild_pb.ts @@ -12,6 +12,7 @@ import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf"; import { Message, proto3, Timestamp } from "@bufbuild/protobuf"; import { PaginationRequest, PaginationResponse } from "./pagination_pb.js"; +import { Sort } from "./sorting_pb.js"; import { Commit } from "./scm_pb.js"; /** @@ -444,6 +445,11 @@ export class ListOrganizationPrebuildsRequest extends Message) { super(); proto3.util.initPartial(data, this); @@ -455,6 +461,7 @@ export class ListOrganizationPrebuildsRequest extends Message): ListOrganizationPrebuildsRequest { From 0c6dd3bfdfde9eac2c23eda764e414f51ee29511 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 29 Jan 2024 15:31:45 +0000 Subject: [PATCH 11/49] API-level sorting --- .../src/typeorm/workspace-db-impl.ts | 18 +++++++++++------- components/gitpod-db/src/workspace-db.ts | 10 +++++++--- .../src/public-api-converter.ts | 19 +++++++++++++++++++ .../src/api/configuration-service-api.ts | 4 ++-- .../server/src/api/prebuild-service-api.ts | 11 ++++++++++- .../server/src/prebuilds/prebuild-manager.ts | 8 ++++++-- 6 files changed, 55 insertions(+), 15 deletions(-) diff --git a/components/gitpod-db/src/typeorm/workspace-db-impl.ts b/components/gitpod-db/src/typeorm/workspace-db-impl.ts index c40bc0faf60395..4dfb41fdb464da 100644 --- a/components/gitpod-db/src/typeorm/workspace-db-impl.ts +++ b/components/gitpod-db/src/typeorm/workspace-db-impl.ts @@ -1047,9 +1047,9 @@ export class TypeORMWorkspaceDBImpl extends TransactionalDBImpl imp */ async findPrebuiltWorkspacesByOrganization( organizationId: string, - offset = 0, - limit = 25, - filter?: { + offset: number, + limit: number, + filter: { configuration?: { id: string; branch?: string; @@ -1057,11 +1057,15 @@ export class TypeORMWorkspaceDBImpl extends TransactionalDBImpl imp state?: "succeeded" | "failed" | "unfinished"; searchTerm?: string; }, + sort: { + field: string; + order?: "ASC" | "DESC"; + }, ): Promise { const repo = await this.getPrebuiltWorkspaceRepo(); const query = repo .createQueryBuilder("pws") - .orderBy("pws.creationTime", "DESC") + .orderBy("pws.creationTime", sort.order ?? "DESC") .innerJoinAndMapOne( "pws.workspace", DBWorkspace, @@ -1072,7 +1076,7 @@ export class TypeORMWorkspaceDBImpl extends TransactionalDBImpl imp .skip(offset) .take(limit); - if (filter?.state) { + if (filter.state) { const { state } = filter; // translating API state to DB state switch (state) { @@ -1116,14 +1120,14 @@ export class TypeORMWorkspaceDBImpl extends TransactionalDBImpl imp } } - if (filter?.configuration?.id) { + if (filter.configuration?.id) { query.andWhere("pws.projectId = :projectId", { projectId: filter.configuration.id }); if (filter.configuration.branch) { query.andWhere("pws.branch = :branch", { branch: filter.configuration.branch }); } } - const normalizedSearchTerm = filter?.searchTerm?.trim(); + const normalizedSearchTerm = filter.searchTerm?.trim(); if (normalizedSearchTerm) { query.innerJoinAndMapOne("pws.project", DBProject, "project", "pws.projectId = project.id"); query.andWhere( diff --git a/components/gitpod-db/src/workspace-db.ts b/components/gitpod-db/src/workspace-db.ts index 7d4fe1617e27d0..661b7b2b1cda89 100644 --- a/components/gitpod-db/src/workspace-db.ts +++ b/components/gitpod-db/src/workspace-db.ts @@ -172,9 +172,9 @@ export interface WorkspaceDB { findPrebuiltWorkspacesByProject(projectId: string, branch?: string, limit?: number): Promise; findPrebuiltWorkspacesByOrganization( organizationId: string, - offset?: number, - limit?: number, - filter?: { + offset: number, + limit: number, + filter: { configuration?: { id: string; branch?: string; @@ -182,6 +182,10 @@ export interface WorkspaceDB { state?: "succeeded" | "failed" | "unfinished"; searchTerm?: string; }, + sort: { + field: string; + order?: "ASC" | "DESC"; + }, ): Promise; findPrebuiltWorkspaceById(prebuildId: string): Promise; diff --git a/components/public-api/typescript-common/src/public-api-converter.ts b/components/public-api/typescript-common/src/public-api-converter.ts index 7544312096e18e..31b3edd2c515f7 100644 --- a/components/public-api/typescript-common/src/public-api-converter.ts +++ b/components/public-api/typescript-common/src/public-api-converter.ts @@ -153,6 +153,7 @@ import { RoleOrPermission as ProtocolRoleOrPermission } from "@gitpod/gitpod-pro import { parseGoDurationToMs } from "@gitpod/gitpod-protocol/lib/util/timeutil"; import { isWorkspaceRegion } from "@gitpod/gitpod-protocol/lib/workspace-cluster"; import { GitpodServer } from "@gitpod/gitpod-protocol"; +import { Sort, SortOrder } from "@gitpod/public-api/lib/gitpod/v1/sorting_pb"; export type PartialConfiguration = DeepPartial & Pick; @@ -879,6 +880,24 @@ export class PublicAPIConverter { }); } + fromSort(sort: Sort) { + return { + order: this.fromSortOrder(sort.order), + field: sort.field + } as const; + } + + fromSortOrder(order: SortOrder) { + switch (order) { + case SortOrder.ASC: + return "ASC"; + case SortOrder.DESC: + return "DESC"; + default: + return undefined; + } + } + toOrgMemberRole(role: OrgMemberRole): OrganizationRole { switch (role) { case "owner": diff --git a/components/server/src/api/configuration-service-api.ts b/components/server/src/api/configuration-service-api.ts index f15754350a3dd7..8613c674477e17 100644 --- a/components/server/src/api/configuration-service-api.ts +++ b/components/server/src/api/configuration-service-api.ts @@ -124,9 +124,9 @@ export class ConfigurationServiceAPI implements ServiceImpl { @@ -169,11 +170,18 @@ export class PrebuildServiceAPI implements ServiceImpl this.apiConverter.toPrebuild(pb)); diff --git a/components/server/src/prebuilds/prebuild-manager.ts b/components/server/src/prebuilds/prebuild-manager.ts index 9971986f72f3b1..8046aee7afbf74 100644 --- a/components/server/src/prebuilds/prebuild-manager.ts +++ b/components/server/src/prebuilds/prebuild-manager.ts @@ -208,13 +208,17 @@ export class PrebuildManager { limit: number; offset?: number; }, - filter?: PrebuildFilter, + filter: PrebuildFilter, + sort: { + field: string; + order?: "DESC" | "ASC"; + }, ): Promise { await this.auth.checkPermissionOnOrganization(userId, "read_prebuild", organizationId); const prebuiltWorkspaces = await this.workspaceDB .trace(ctx) - .findPrebuiltWorkspacesByOrganization(organizationId, pagination.offset, pagination.limit, filter); + .findPrebuiltWorkspacesByOrganization(organizationId, pagination.offset, pagination.limit, filter, sort); const prebuildMap = new Map(prebuiltWorkspaces.map((prebuild) => [prebuild.id, prebuild])); const infos = await this.workspaceDB.trace({}).findPrebuildInfos([...prebuildMap.keys()]); From 93fcd91925cdcb89bab7f154c96b3f10b968e375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 29 Jan 2024 16:20:19 +0000 Subject: [PATCH 12/49] Simplify pagination --- .../gitpod-db/src/typeorm/workspace-db-impl.ts | 15 +++++++++------ components/gitpod-db/src/workspace-db.ts | 6 ++++-- components/server/src/api/prebuild-service-api.ts | 2 +- .../server/src/prebuilds/prebuild-manager.ts | 4 ++-- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/components/gitpod-db/src/typeorm/workspace-db-impl.ts b/components/gitpod-db/src/typeorm/workspace-db-impl.ts index 4dfb41fdb464da..8bf1fc8977b76b 100644 --- a/components/gitpod-db/src/typeorm/workspace-db-impl.ts +++ b/components/gitpod-db/src/typeorm/workspace-db-impl.ts @@ -1040,15 +1040,17 @@ export class TypeORMWorkspaceDBImpl extends TransactionalDBImpl imp /** * Finds prebuilt workspaces by organization with optional filtering and pagination. * @param organizationId The ID of the organization. - * @param offset Offset for pagination. - * @param limit Limit for pagination. + * @param pagination Pagination per page size and result offset. * @param filter Filters for the search. + * @param sort Sort field and direction * @returns A promise that resolves to an array of PrebuiltWorkspace objects. */ async findPrebuiltWorkspacesByOrganization( organizationId: string, - offset: number, - limit: number, + pagination: { + offset: number; + limit: number; + }, filter: { configuration?: { id: string; @@ -1065,6 +1067,7 @@ export class TypeORMWorkspaceDBImpl extends TransactionalDBImpl imp const repo = await this.getPrebuiltWorkspaceRepo(); const query = repo .createQueryBuilder("pws") + // todo: take sort field into account .orderBy("pws.creationTime", sort.order ?? "DESC") .innerJoinAndMapOne( "pws.workspace", @@ -1073,8 +1076,8 @@ export class TypeORMWorkspaceDBImpl extends TransactionalDBImpl imp "pws.buildWorkspaceId = ws.id AND ws.organizationId = :organizationId", { organizationId }, ) - .skip(offset) - .take(limit); + .skip(pagination.offset) + .take(pagination.limit); if (filter.state) { const { state } = filter; diff --git a/components/gitpod-db/src/workspace-db.ts b/components/gitpod-db/src/workspace-db.ts index 661b7b2b1cda89..ed0907372b8c0a 100644 --- a/components/gitpod-db/src/workspace-db.ts +++ b/components/gitpod-db/src/workspace-db.ts @@ -172,8 +172,10 @@ export interface WorkspaceDB { findPrebuiltWorkspacesByProject(projectId: string, branch?: string, limit?: number): Promise; findPrebuiltWorkspacesByOrganization( organizationId: string, - offset: number, - limit: number, + pagination: { + offset: number; + limit: number; + }, filter: { configuration?: { id: string; diff --git a/components/server/src/api/prebuild-service-api.ts b/components/server/src/api/prebuild-service-api.ts index d62bb56b8c84ae..f5afc29df71ddd 100644 --- a/components/server/src/api/prebuild-service-api.ts +++ b/components/server/src/api/prebuild-service-api.ts @@ -170,7 +170,7 @@ export class PrebuildServiceAPI implements ServiceImpl [prebuild.id, prebuild])); const infos = await this.workspaceDB.trace({}).findPrebuildInfos([...prebuildMap.keys()]); From ea422f5f10d1c135a8b97d935e2e8248002b9e2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 29 Jan 2024 16:47:22 +0000 Subject: [PATCH 13/49] Fix undefined inference --- components/server/src/api/prebuild-service-api.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/components/server/src/api/prebuild-service-api.ts b/components/server/src/api/prebuild-service-api.ts index f5afc29df71ddd..b4b1b5a0dccf73 100644 --- a/components/server/src/api/prebuild-service-api.ts +++ b/components/server/src/api/prebuild-service-api.ts @@ -146,7 +146,7 @@ export class PrebuildServiceAPI implements ServiceImpl { - const { organizationId, pagination, filter } = request; + const { organizationId, pagination, filter, sort } = request; const userId = ctxUserId(); const limit = pagination?.pageSize ?? 25; @@ -156,6 +156,9 @@ export class PrebuildServiceAPI implements ServiceImpl 100) { + throw new ApplicationError(ErrorCodes.BAD_REQUEST, "searchTerm must be less than 100 characters"); + } if (!uuidValidate(organizationId)) { throw new ApplicationError(ErrorCodes.BAD_REQUEST, "organizationId is required"); } @@ -175,12 +178,10 @@ export class PrebuildServiceAPI implements ServiceImpl Date: Mon, 29 Jan 2024 17:24:47 +0000 Subject: [PATCH 14/49] Dashboard adopt sort behavior --- .../podkit/tables/SortableTable.tsx | 3 +- .../prebuilds/organization-prebuilds-query.ts | 9 ++- .../src/prebuilds/list/PrebuildList.tsx | 61 +++++++++++++++++-- .../src/prebuilds/list/PrebuildTable.tsx | 24 ++++++-- .../src/repositories/list/RepositoryTable.tsx | 2 +- 5 files changed, 84 insertions(+), 15 deletions(-) diff --git a/components/dashboard/src/components/podkit/tables/SortableTable.tsx b/components/dashboard/src/components/podkit/tables/SortableTable.tsx index 687da2b46b4a0f..334935fd6b4cb1 100644 --- a/components/dashboard/src/components/podkit/tables/SortableTable.tsx +++ b/components/dashboard/src/components/podkit/tables/SortableTable.tsx @@ -11,11 +11,12 @@ import { ChevronDownIcon, ChevronUpIcon } from "lucide-react"; import { cn } from "@podkit/lib/cn"; export type TableSortOrder = "asc" | "desc"; +export type SortCallback = (sortBy: string, sortOrder: TableSortOrder) => void; export type SortableTableHeadProps = { columnName: string; sortOrder?: TableSortOrder; - onSort: (sortBy: string, sortOrder: TableSortOrder) => void; + onSort: SortCallback; } & HideableCellProps; export const SortableTableHead = React.forwardRef< HTMLTableCellElement, diff --git a/components/dashboard/src/data/prebuilds/organization-prebuilds-query.ts b/components/dashboard/src/data/prebuilds/organization-prebuilds-query.ts index 55db64498ac68a..ac41c5e3bd1bab 100644 --- a/components/dashboard/src/data/prebuilds/organization-prebuilds-query.ts +++ b/components/dashboard/src/data/prebuilds/organization-prebuilds-query.ts @@ -8,18 +8,20 @@ import { useInfiniteQuery } from "@tanstack/react-query"; import { prebuildClient } from "../../service/public-api"; import { ListOrganizationPrebuildsRequest_Filter } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; import { useCurrentOrg } from "../organizations/orgs-query"; -import { PlainMessage } from "@bufbuild/protobuf"; +import { PartialMessage, PlainMessage } from "@bufbuild/protobuf"; import type { DeepPartial } from "@gitpod/gitpod-protocol/lib/util/deep-partial"; +import { Sort } from "@gitpod/public-api/lib/gitpod/v1/sorting_pb"; type Args = { filter: DeepPartial>; + sort: PartialMessage; pageSize: number; }; -export const useListOrganizationPrebuildsQuery = ({ filter, pageSize }: Args) => { +export const useListOrganizationPrebuildsQuery = ({ filter, pageSize, sort }: Args) => { const { data: org } = useCurrentOrg(); return useInfiniteQuery( - getListConfigurationsPrebuildsQueryKey(org?.id ?? "", { filter, pageSize }), + getListConfigurationsPrebuildsQueryKey(org?.id ?? "", { filter, pageSize, sort }), async ({ pageParam: nextToken }) => { if (!org) { throw new Error("No org currently selected"); @@ -28,6 +30,7 @@ export const useListOrganizationPrebuildsQuery = ({ filter, pageSize }: Args) => const { prebuilds, pagination } = await prebuildClient.listOrganizationPrebuilds({ organizationId: org.id, filter, + sort, pagination: { pageSize, token: nextToken }, }); return { diff --git a/components/dashboard/src/prebuilds/list/PrebuildList.tsx b/components/dashboard/src/prebuilds/list/PrebuildList.tsx index b4c86523788fb8..392e3756b948af 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildList.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildList.tsx @@ -17,24 +17,37 @@ import { LoadingState } from "@podkit/loading/LoadingState"; import { useListOrganizationPrebuildsQuery } from "../../data/prebuilds/organization-prebuilds-query"; import { ListOrganizationPrebuildsRequest_Filter_State } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; import { validate } from "uuid"; +import type { TableSortOrder } from "@podkit/tables/SortableTable"; +import { SortOrder } from "@gitpod/public-api/lib/gitpod/v1/sorting_pb"; const STATUS_FILTER_VALUES = ["succeeded", "failed", "unfinished", undefined] as const; // undefined means any status -export type STATUS_OPTION = typeof STATUS_FILTER_VALUES[number]; +export type StatusOption = typeof STATUS_FILTER_VALUES[number]; export type Filter = { - status?: STATUS_OPTION; + status?: StatusOption; configurationId?: string; }; +const SORT_FIELD_VALUES = ["creationTime"] as const; +export type SortField = typeof SORT_FIELD_VALUES[number]; +export type Sort = { + sortBy: SortField; + sortOrder: TableSortOrder; +}; + const PrebuildsListPage: FC = () => { useDocumentTitle("Prebuilds"); const history = useHistory(); const params = useQueryParams(); + const [searchTerm, setSearchTerm, searchTermDebounced] = useStateWithDebounce(params.get("search") ?? ""); const [statusFilter, setPrebuildsFilter] = useState(parseStatus(params)); const configurationFilter = useMemo(() => parseConfigurationId(params), [params]); + const [sortBy, setSortBy] = useState(parseSortBy(params)); + const [sortOrder, setSortOrder] = useState(parseSortOrder(params)); + const handleFilterChange = useCallback((filter: Filter) => { setPrebuildsFilter(filter.status); }, []); @@ -45,6 +58,20 @@ const PrebuildsListPage: FC = () => { }; }, [configurationFilter, statusFilter]); + const sort = useMemo(() => { + return { + sortBy, + sortOrder, + }; + }, [sortBy, sortOrder]); + const handleSort = useCallback( + (columnName: SortField, newSortOrder: TableSortOrder) => { + setSortBy(columnName); + setSortOrder(newSortOrder); + }, + [setSortOrder], + ); + useEffect(() => { const params = new URLSearchParams(); if (searchTermDebounced) { @@ -80,6 +107,10 @@ const PrebuildsListPage: FC = () => { state: toApiStatus(filter.status), ...(configurationFilter ? { configuration: { id: configurationFilter } } : {}), }, + sort: { + order: sortOrder === "desc" ? SortOrder.DESC : SortOrder.ASC, + field: sortBy, + }, pageSize: 30, }); @@ -111,10 +142,12 @@ const PrebuildsListPage: FC = () => { isFetchingNextPage={isFetchingNextPage} hasNextPage={!!hasNextPage} filter={filter} + sort={sort} hasMoreThanOnePage={hasMoreThanOnePage} onLoadNextPage={() => fetchNextPage()} onFilterChange={handleFilterChange} onSearchTermChange={setSearchTerm} + onSort={handleSort} /> )} @@ -125,7 +158,7 @@ const PrebuildsListPage: FC = () => { ); }; -const toApiStatus = (status: STATUS_OPTION): ListOrganizationPrebuildsRequest_Filter_State | undefined => { +const toApiStatus = (status: StatusOption): ListOrganizationPrebuildsRequest_Filter_State | undefined => { switch (status) { case "failed": return ListOrganizationPrebuildsRequest_Filter_State.FAILED; // todo: adjust to needs of proper status @@ -138,16 +171,34 @@ const toApiStatus = (status: STATUS_OPTION): ListOrganizationPrebuildsRequest_Fi return undefined; }; -const parseStatus = (params: URLSearchParams): STATUS_OPTION => { +const parseStatus = (params: URLSearchParams): StatusOption => { const filter = params.get("prebuilds"); const validValues = Object.values(STATUS_FILTER_VALUES).filter((val) => !!val); if (filter && validValues.includes(filter as any)) { - return filter as STATUS_OPTION; + return filter as StatusOption; } return undefined; }; +const parseSortOrder = (params: URLSearchParams): TableSortOrder => { + const sortOrder = params.get("sortOrder"); + if (sortOrder === "asc" || sortOrder === "desc") { + return sortOrder; + } + return "desc"; +}; + +const parseSortBy = (params: URLSearchParams): SortField => { + const sortBy = params.get("sortBy"); + + // todo: potentially allow more fields + if (sortBy === "creationTime") { + return sortBy; + } + return "creationTime"; +}; + const parseConfigurationId = (params: URLSearchParams): string | undefined => { const configuration = params.get("configurationId"); if (configuration && validate(configuration)) { diff --git a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx index f10a4d3222a47c..ff6d0863ae7cf5 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx @@ -15,12 +15,17 @@ import { cn } from "@podkit/lib/cn"; import { LoadingState } from "@podkit/loading/LoadingState"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@podkit/select/Select"; import { Prebuild } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; -import { Filter, STATUS_OPTION } from "./PrebuildList"; +import { Filter, SortField, StatusOption } from "./PrebuildList"; +import { SortCallback, SortableTableHead, TableSortOrder } from "@podkit/tables/SortableTable"; type Props = { prebuilds: Prebuild[]; searchTerm: string; filter?: Filter; + sort: { + sortBy: SortField; + sortOrder: TableSortOrder; + }; hasNextPage: boolean; hasMoreThanOnePage: boolean; isSearching: boolean; @@ -28,6 +33,7 @@ type Props = { onSearchTermChange: (val: string) => void; onFilterChange: (val: Filter) => void; onLoadNextPage: () => void; + onSort: (columnName: SortField, direction: TableSortOrder) => void; }; export const PrebuildsTable: FC = ({ searchTerm, @@ -37,9 +43,11 @@ export const PrebuildsTable: FC = ({ isSearching, isFetchingNextPage, filter, + sort, onSearchTermChange, onFilterChange, onLoadNextPage, + onSort, }) => { return ( <> @@ -54,13 +62,13 @@ export const PrebuildsTable: FC = ({ placeholder="Search prebuilds" /> = ({ All Failing - Successfull + Successful In progress From e16daa5444ae83c2b4e16d7d3bd6c54ae637cca7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Wed, 31 Jan 2024 10:49:51 +0000 Subject: [PATCH 23/49] Make configuration filter disableable --- .../src/prebuilds/list/ConfigurationInput.tsx | 11 +++++++++-- .../dashboard/src/prebuilds/list/PrebuildTable.tsx | 6 +++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx b/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx index 75c87751002bfe..c5be93ca84f8bf 100644 --- a/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx +++ b/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx @@ -5,7 +5,6 @@ */ import { FC, useCallback, useMemo, useState } from "react"; -import type { Configuration } from "@gitpod/public-api/lib/gitpod/v1/configuration_pb"; import { useConfiguration, useListConfigurations } from "../../data/configurations/configuration-queries"; import { Combobox, ComboboxElement, ComboboxSelectedItem } from "@podkit/combobox/Combobox"; @@ -62,6 +61,12 @@ export default function ConfigurationDropdown({ } as ComboboxElement; }); + result.unshift({ + id: "", + element: , + isSelectable: true, + }); + return result; }, [configurations, selectedConfiguration, selectedConfigurationId]); @@ -89,7 +94,9 @@ export default function ConfigurationDropdown({ } type SuggestedRepositoryOptionProps = { - repo: Configuration; + repo: { + name: string; + }; }; const SuggestedRepositoryOption: FC = ({ repo }) => { const { name } = repo; diff --git a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx index dc63c1f55d1254..3a39c1b85c6b1e 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx @@ -53,7 +53,11 @@ export const PrebuildsTable: FC = ({ { - console.debug("Got an onChange ID", configurationId); + if (!configurationId) { + // If the reset item is selected, we reset the filter + onFilterChange({ ...filter, configurationId: undefined }); + } + onFilterChange({ ...filter, configurationId }); }} /> From 7bac1408aeacf387583ef5de15537e9094e6a236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Wed, 31 Jan 2024 11:28:00 +0000 Subject: [PATCH 24/49] Use in in SQL --- components/gitpod-db/src/typeorm/workspace-db-impl.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/components/gitpod-db/src/typeorm/workspace-db-impl.ts b/components/gitpod-db/src/typeorm/workspace-db-impl.ts index eceb275e4e9383..306cdd8ee36f70 100644 --- a/components/gitpod-db/src/typeorm/workspace-db-impl.ts +++ b/components/gitpod-db/src/typeorm/workspace-db-impl.ts @@ -1108,14 +1108,7 @@ export class TypeORMWorkspaceDBImpl extends TransactionalDBImpl imp ); break; case "unfinished": - query.andWhere( - new Brackets((qb) => { - qb.where("pws.state = :queuedState", { queuedState: "queued" }).orWhere( - "pws.state = :buildingState", - { buildingState: "building" }, - ); - }), - ); + query.andWhere("pws.state IN (:...states)", { states: ["queued", "building"] }); break; } } From 2d218d3e32b9e5c1b3ab72f1e38ecb37306a6db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Wed, 31 Jan 2024 11:56:03 +0000 Subject: [PATCH 25/49] Minor styling adjustements --- .../src/components/podkit/combobox/Combobox.tsx | 9 +++++++-- .../dashboard/src/prebuilds/list/ConfigurationInput.tsx | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/components/dashboard/src/components/podkit/combobox/Combobox.tsx b/components/dashboard/src/components/podkit/combobox/Combobox.tsx index 24301f4a185df2..c96eaa85649098 100644 --- a/components/dashboard/src/components/podkit/combobox/Combobox.tsx +++ b/components/dashboard/src/components/podkit/combobox/Combobox.tsx @@ -24,6 +24,7 @@ export interface ComboboxProps { disableSearch?: boolean; expanded?: boolean; className?: string; + itemClassName?: string; onSelectionChange: (id: string) => void; // Meant to allow consumers to react to search changes even though state is managed internally onSearchChange?: (searchString: string) => void; @@ -39,6 +40,7 @@ export const Combobox: FunctionComponent = ({ disableSearch, children, className, + itemClassName, onSelectionChange, onSearchChange, }) => { @@ -240,6 +242,7 @@ export const Combobox: FunctionComponent = ({ key={element.id} element={element} isActive={element.id === selectedElementTemp} + className={itemClassName} onSelected={onSelected} onFocused={setActiveElement} /> @@ -309,11 +312,12 @@ export const ComboboxSelectedItem: FC = ({ type ComboboxItemProps = { element: ComboboxElement; isActive: boolean; + className?: string; onSelected: (id: string) => void; onFocused: (id: string) => void; }; -export const ComboboxItem: FC = ({ element, isActive, onSelected, onFocused }) => { +export const ComboboxItem: FC = ({ element, isActive, className, onSelected, onFocused }) => { let selectionClasses = `bg-pk-surface-tertiary/25 cursor-pointer`; if (isActive) { selectionClasses = `bg-pk-content-tertiary/10 cursor-pointer focus:outline-none focus:ring-0`; @@ -321,10 +325,11 @@ export const ComboboxItem: FC = ({ element, isActive, onSelec if (!element.isSelectable) { selectionClasses = ``; } + return (
  • { if (element.isSelectable) { onSelected(element.id); diff --git a/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx b/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx index c5be93ca84f8bf..af6612fb0355ff 100644 --- a/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx +++ b/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx @@ -82,6 +82,7 @@ export default function ConfigurationDropdown({ loading={isLoading} onSearchChange={setSearchTerm} className="h-8 w-48 bg-pk-surface-primary hover:bg-pk-surface-primary px-0 border border-pk-border-base text-sm text-pk-content-primary" + itemClassName="font-normal" > Date: Wed, 31 Jan 2024 16:33:10 +0000 Subject: [PATCH 26/49] Nav item --- components/dashboard/src/app/AppRoutes.tsx | 13 ++++++++----- components/dashboard/src/data/featureflag-query.ts | 3 +-- .../dashboard/src/menu/OrganizationSelector.tsx | 14 ++++++++++---- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/components/dashboard/src/app/AppRoutes.tsx b/components/dashboard/src/app/AppRoutes.tsx index d6a675ba1f0361..d3f58801543efd 100644 --- a/components/dashboard/src/app/AppRoutes.tsx +++ b/components/dashboard/src/app/AppRoutes.tsx @@ -85,7 +85,7 @@ const PrebuildListPage = React.lazy(() => import(/* webpackPrefetch: true */ ".. export const AppRoutes = () => { const hash = getURLHash(); const location = useLocation(); - const repoConfigListAndDetail = useFeatureFlag("repoConfigListAndDetail"); + const configurationsAndPrebuilds = useFeatureFlag("configurationsAndPrebuilds"); // TODO: Add a Route for this instead of inspecting location manually if (location.pathname.startsWith("/blocked")) { @@ -208,11 +208,14 @@ export const AppRoutes = () => { - - - {repoConfigListAndDetail && } + {configurationsAndPrebuilds && } + {configurationsAndPrebuilds && ( + + )} {/* Handles all /repositories/:id/* routes in a nested router */} - {repoConfigListAndDetail && } + {configurationsAndPrebuilds && ( + + )} {/* basic redirect for old team slugs */} diff --git a/components/dashboard/src/data/featureflag-query.ts b/components/dashboard/src/data/featureflag-query.ts index 0ee6771d1d4f5e..c89c15d0642694 100644 --- a/components/dashboard/src/data/featureflag-query.ts +++ b/components/dashboard/src/data/featureflag-query.ts @@ -27,8 +27,7 @@ const featureFlags = { newProjectIncrementalRepoSearchBBS: false, repositoryFinderSearch: false, createProjectModal: false, - repoConfigListAndDetail: false, - showRepoConfigMenuItem: false, + configurationsAndPrebuilds: false, /** * Whether to enable org-level workspace class restrictions */ diff --git a/components/dashboard/src/menu/OrganizationSelector.tsx b/components/dashboard/src/menu/OrganizationSelector.tsx index 927611051b7d8e..67163d4832694e 100644 --- a/components/dashboard/src/menu/OrganizationSelector.tsx +++ b/components/dashboard/src/menu/OrganizationSelector.tsx @@ -25,15 +25,14 @@ export default function OrganizationSelector() { const hasMemberPermission = useHasRolePermission(OrganizationRole.MEMBER); const { data: billingMode } = useOrgBillingMode(); const getOrgURL = useGetOrgURL(); - const repoConfigListAndDetail = useFeatureFlag("repoConfigListAndDetail"); - const showRepoConfigMenuItem = useFeatureFlag("showRepoConfigMenuItem"); + const configurationsAndPrebuilds = useFeatureFlag("configurationsAndPrebuilds"); // we should have an API to ask for permissions, until then we duplicate the logic here const canCreateOrgs = user && !isOrganizationOwned(user); const userFullName = user?.name || "..."; - let activeOrgEntry = !currentOrg.data + const activeOrgEntry = !currentOrg.data ? { title: userFullName, customContent: , @@ -61,7 +60,7 @@ export default function OrganizationSelector() { // collaborator can't access projects, members, usage and billing if (hasMemberPermission) { // Check both flags as one just controls if the menu item is present, the other if the page is accessible - if (repoConfigListAndDetail && showRepoConfigMenuItem) { + if (configurationsAndPrebuilds) { linkEntries.push({ title: "Repositories", customContent: Repositories, @@ -69,6 +68,13 @@ export default function OrganizationSelector() { separator: false, link: "/repositories", }); + linkEntries.push({ + title: "Prebuilds", + customContent: Prebuilds, + active: false, + separator: false, + link: "/prebuilds", + }); } linkEntries.push({ title: "Members", From 55e9e04a419b67f9ddfbd02700ab2123e7fb3214 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Wed, 31 Jan 2024 17:48:28 +0000 Subject: [PATCH 27/49] Rename menu item --- .../src/repositories/detail/ConfigurationDetailPage.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/components/dashboard/src/repositories/detail/ConfigurationDetailPage.tsx b/components/dashboard/src/repositories/detail/ConfigurationDetailPage.tsx index 3313f33f3cff55..0614836c35adf7 100644 --- a/components/dashboard/src/repositories/detail/ConfigurationDetailPage.tsx +++ b/components/dashboard/src/repositories/detail/ConfigurationDetailPage.tsx @@ -6,7 +6,7 @@ import { BreadcrumbNav } from "@podkit/breadcrumbs/BreadcrumbNav"; import { Button } from "@podkit/buttons/Button"; -import { AlertTriangle, Loader2 } from "lucide-react"; +import { AlertTriangle } from "lucide-react"; import { FC, useMemo } from "react"; import Alert from "../../components/Alert"; import { WidePageWithSubMenu } from "../../components/WidePageWithSubmenu"; @@ -18,6 +18,7 @@ import { ConfigurationDetailWorkspaces } from "./ConfigurationDetailWorkspaces"; import { ConfigurationDetailPrebuilds } from "./ConfigurationDetailPrebuilds"; import { ConfigurationVariableList } from "./variables/ConfigurationVariableList"; import { useWorkspaceClasses } from "../../data/workspaces/workspace-classes-query"; +import { LoadingState } from "@podkit/loading/LoadingState"; type PageRouteParams = { id: string; @@ -40,7 +41,7 @@ const ConfigurationDetailPage: FC = () => { link: [url], }, { - title: "Prebuilds", + title: "Prebuild settings", link: [`${url}/prebuilds`], icon: !prebuildsEnabled ? : undefined, }, @@ -64,7 +65,7 @@ const ConfigurationDetailPage: FC = () => { backLink="/repositories" /> - {isLoading && } + {isLoading && } {error ? (
    From 925581ff98f42973cb4f8be5d001182344f46b2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Wed, 31 Jan 2024 17:49:08 +0000 Subject: [PATCH 28/49] =?UTF-8?q?Const=20=F0=9F=A4=B7=E2=80=8D=E2=99=82?= =?UTF-8?q?=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/repositories/detail/ConfigurationDetailPage.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dashboard/src/repositories/detail/ConfigurationDetailPage.tsx b/components/dashboard/src/repositories/detail/ConfigurationDetailPage.tsx index 0614836c35adf7..fa90c7cfce9665 100644 --- a/components/dashboard/src/repositories/detail/ConfigurationDetailPage.tsx +++ b/components/dashboard/src/repositories/detail/ConfigurationDetailPage.tsx @@ -29,7 +29,7 @@ const ConfigurationDetailPage: FC = () => { useWorkspaceClasses(); const { id } = useParams(); - let { path, url } = useRouteMatch(); + const { path, url } = useRouteMatch(); const { data, error, isLoading, refetch } = useConfiguration(id); const prebuildsEnabled = !!data?.prebuildSettings?.enabled; From 129bb4b6a2e1bfab8c28a2cd1be736e1233baf41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Wed, 31 Jan 2024 17:54:18 +0000 Subject: [PATCH 29/49] Always display filter reset opt --- .../src/prebuilds/list/ConfigurationInput.tsx | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx b/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx index af6612fb0355ff..15f2a3b8ab4794 100644 --- a/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx +++ b/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx @@ -43,8 +43,14 @@ export default function ConfigurationDropdown({ }, [configurations, selectedConfigurationId]); const getElements = useCallback(() => { + const resetFilterItem: ComboboxElement = { + id: "", + element: , + isSelectable: true, + }; + if (!configurations) { - return []; + return [resetFilterItem]; } const allRepositories = configurations; @@ -61,11 +67,7 @@ export default function ConfigurationDropdown({ } as ComboboxElement; }); - result.unshift({ - id: "", - element: , - isSelectable: true, - }); + result.unshift(resetFilterItem); return result; }, [configurations, selectedConfiguration, selectedConfigurationId]); From a8c4a1db76553093bd1b031cb67258884b01b822 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Wed, 31 Jan 2024 20:22:08 +0000 Subject: [PATCH 30/49] Add prebuild link to prebuild settings --- .../components/podkit/combobox/Combobox.tsx | 3 ++ .../src/prebuilds/list/ConfigurationInput.tsx | 5 ++-- .../detail/ConfigurationDetailPrebuilds.tsx | 30 ++++++++++++------- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/components/dashboard/src/components/podkit/combobox/Combobox.tsx b/components/dashboard/src/components/podkit/combobox/Combobox.tsx index c96eaa85649098..351cb7fd3d4fe0 100644 --- a/components/dashboard/src/components/podkit/combobox/Combobox.tsx +++ b/components/dashboard/src/components/podkit/combobox/Combobox.tsx @@ -24,6 +24,7 @@ export interface ComboboxProps { disableSearch?: boolean; expanded?: boolean; className?: string; + dropDownClassName?: string; itemClassName?: string; onSelectionChange: (id: string) => void; // Meant to allow consumers to react to search changes even though state is managed internally @@ -40,6 +41,7 @@ export const Combobox: FunctionComponent = ({ disableSearch, children, className, + dropDownClassName, itemClassName, onSelectionChange, onSearchChange, @@ -207,6 +209,7 @@ export const Combobox: FunctionComponent = ({ "rounded-b-lg p-2 filter drop-shadow-xl z-50 outline-none", "bg-pk-surface-secondary", "w-[--radix-popover-trigger-width]", + dropDownClassName, )} onKeyDown={onKeyDown} > diff --git a/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx b/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx index 15f2a3b8ab4794..15d4c9d7bc6e73 100644 --- a/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx +++ b/components/dashboard/src/prebuilds/list/ConfigurationInput.tsx @@ -84,7 +84,8 @@ export default function ConfigurationDropdown({ loading={isLoading} onSearchChange={setSearchTerm} className="h-8 w-48 bg-pk-surface-primary hover:bg-pk-surface-primary px-0 border border-pk-border-base text-sm text-pk-content-primary" - itemClassName="font-normal" + dropDownClassName="text-pk-content-primary" + itemClassName="font-normal focus:text-accent-foreground cursor-default select-none" > = ({ repo }) return (
    - {name && {name}} + {name && {name}}
    ); }; diff --git a/components/dashboard/src/repositories/detail/ConfigurationDetailPrebuilds.tsx b/components/dashboard/src/repositories/detail/ConfigurationDetailPrebuilds.tsx index c6eb530cf05cf0..7335233212fa95 100644 --- a/components/dashboard/src/repositories/detail/ConfigurationDetailPrebuilds.tsx +++ b/components/dashboard/src/repositories/detail/ConfigurationDetailPrebuilds.tsx @@ -14,6 +14,7 @@ import { PrebuildSettingsForm } from "./prebuilds/PrebuildSettingsForm"; import { useConfigurationMutation } from "../../data/configurations/configuration-queries"; import { LoadingState } from "@podkit/loading/LoadingState"; import { EnablePrebuildsError } from "./prebuilds/EnablePrebuildsError"; +import { Link } from "react-router-dom"; type Props = { configuration: Configuration; @@ -68,18 +69,25 @@ export const ConfigurationDetailPrebuilds: FC = ({ configuration }) => { !!configuration.prebuildSettings?.enabled ? "Prebuilds are enabled" : "Prebuilds are disabled" } description={ - - Enabling requires permissions to configure repository webhooks.{" "} - - Learn more - + <> + + Enabling requires permissions to configure repository webhooks.{" "} + + Learn more + + . + +
    + + View prebuild history + . -
    + } /> From e3906d03ba39445f127dfc7b944d9e7700225e8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Wed, 31 Jan 2024 20:32:07 +0000 Subject: [PATCH 31/49] Simplify --- components/dashboard/src/prebuilds/list/PrebuildTable.tsx | 5 ----- 1 file changed, 5 deletions(-) diff --git a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx index 3a39c1b85c6b1e..2ba28c0711742a 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx @@ -53,11 +53,6 @@ export const PrebuildsTable: FC = ({ { - if (!configurationId) { - // If the reset item is selected, we reset the filter - onFilterChange({ ...filter, configurationId: undefined }); - } - onFilterChange({ ...filter, configurationId }); }} /> From f957cb12fe48777222000365419093bcf834ba17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Wed, 31 Jan 2024 20:33:52 +0000 Subject: [PATCH 32/49] Don't throw errors All my homies hate throwing in `server` --- .../server/src/prebuilds/prebuild-manager.ts | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/components/server/src/prebuilds/prebuild-manager.ts b/components/server/src/prebuilds/prebuild-manager.ts index 5310d346392893..b0c52dd6b73270 100644 --- a/components/server/src/prebuilds/prebuild-manager.ts +++ b/components/server/src/prebuilds/prebuild-manager.ts @@ -271,19 +271,21 @@ export class PrebuildManager { const infos = await this.workspaceDB.trace({}).findPrebuildInfos(prebuildIds); const prebuildInfosMap = new Map(infos.map((info) => [info.id, info])); - return prebuiltWorkspaces.map((prebuild) => { - const info = prebuildInfosMap.get(prebuild.id); - if (!info) { - throw new Error("Could not find prebuild info for prebuild " + prebuild.id); - } + return prebuiltWorkspaces + .map((prebuild) => { + const info = prebuildInfosMap.get(prebuild.id); + if (!info) { + return; + } - const fullPrebuild: PrebuildWithStatus = { info, status: prebuild.state }; - if (prebuild.error) { - fullPrebuild.error = prebuild.error; - } + const fullPrebuild: PrebuildWithStatus = { info, status: prebuild.state }; + if (prebuild.error) { + fullPrebuild.error = prebuild.error; + } - return fullPrebuild; - }); + return fullPrebuild; + }) + .filter((prebuild): prebuild is PrebuildWithStatus => !!prebuild); // filter out potential undefined values } async findPrebuildByWorkspaceID( From 57e625e33b2e918fa0ef228197a7a542117ab2b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Wed, 31 Jan 2024 21:29:20 +0000 Subject: [PATCH 33/49] FF hook --- components/dashboard/src/app/AppRoutes.tsx | 4 ++-- components/dashboard/src/data/featureflag-query.ts | 4 ++++ components/dashboard/src/menu/OrganizationSelector.tsx | 4 ++-- components/dashboard/src/prebuilds/list/PrebuildListItem.tsx | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-) diff --git a/components/dashboard/src/app/AppRoutes.tsx b/components/dashboard/src/app/AppRoutes.tsx index d3f58801543efd..1560e0eb1aa3fa 100644 --- a/components/dashboard/src/app/AppRoutes.tsx +++ b/components/dashboard/src/app/AppRoutes.tsx @@ -36,7 +36,7 @@ import { CreateWorkspacePage } from "../workspaces/CreateWorkspacePage"; import { WebsocketClients } from "./WebsocketClients"; import { BlockedEmailDomains } from "../admin/BlockedEmailDomains"; import { AppNotifications } from "../AppNotifications"; -import { useFeatureFlag } from "../data/featureflag-query"; +import { useHasConfigurationsAndPrebuildsEnabled } from "../data/featureflag-query"; import { projectsPathInstallGitHubApp } from "../projects/projects.routes"; import { Heading1, Subheading } from "@podkit/typography/Headings"; @@ -85,7 +85,7 @@ const PrebuildListPage = React.lazy(() => import(/* webpackPrefetch: true */ ".. export const AppRoutes = () => { const hash = getURLHash(); const location = useLocation(); - const configurationsAndPrebuilds = useFeatureFlag("configurationsAndPrebuilds"); + const configurationsAndPrebuilds = useHasConfigurationsAndPrebuildsEnabled(); // TODO: Add a Route for this instead of inspecting location manually if (location.pathname.startsWith("/blocked")) { diff --git a/components/dashboard/src/data/featureflag-query.ts b/components/dashboard/src/data/featureflag-query.ts index c89c15d0642694..8fe4e907ffb451 100644 --- a/components/dashboard/src/data/featureflag-query.ts +++ b/components/dashboard/src/data/featureflag-query.ts @@ -81,6 +81,10 @@ export const useIsDataOps = () => { return useFeatureFlag("dataops"); }; +export const useHasConfigurationsAndPrebuildsEnabled = () => { + return useFeatureFlag("configurationsAndPrebuilds"); +}; + export const useReportDashboardLoggingTracing = () => { const enabled = useDedicatedFeatureFlag("dashboard_logging_tracing"); diff --git a/components/dashboard/src/menu/OrganizationSelector.tsx b/components/dashboard/src/menu/OrganizationSelector.tsx index 67163d4832694e..dc0a94b7f0c1fc 100644 --- a/components/dashboard/src/menu/OrganizationSelector.tsx +++ b/components/dashboard/src/menu/OrganizationSelector.tsx @@ -11,7 +11,7 @@ import { useCurrentUser } from "../user-context"; import { useCurrentOrg, useOrganizations } from "../data/organizations/orgs-query"; import { useLocation } from "react-router"; import { useOrgBillingMode } from "../data/billing-mode/org-billing-mode-query"; -import { useFeatureFlag } from "../data/featureflag-query"; +import { useHasConfigurationsAndPrebuildsEnabled } from "../data/featureflag-query"; import { useIsOwner, useListOrganizationMembers, useHasRolePermission } from "../data/organizations/members-query"; import { isOrganizationOwned } from "@gitpod/public-api-common/lib/user-utils"; import { OrganizationRole } from "@gitpod/public-api/lib/gitpod/v1/organization_pb"; @@ -25,7 +25,7 @@ export default function OrganizationSelector() { const hasMemberPermission = useHasRolePermission(OrganizationRole.MEMBER); const { data: billingMode } = useOrgBillingMode(); const getOrgURL = useGetOrgURL(); - const configurationsAndPrebuilds = useFeatureFlag("configurationsAndPrebuilds"); + const configurationsAndPrebuilds = useHasConfigurationsAndPrebuildsEnabled(); // we should have an API to ask for permissions, until then we duplicate the logic here const canCreateOrgs = user && !isOrganizationOwned(user); diff --git a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx index a38681c9104163..6cd00536aea98f 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx @@ -62,7 +62,7 @@ export const RepositoryListItem: FC = ({ prebuild }) => { - + View From 5a78ecb265a601dd9bb14d8c7d569b1bd9f8fdcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Wed, 31 Jan 2024 21:36:47 +0000 Subject: [PATCH 34/49] Name failed to load state --- .../dashboard/src/prebuilds/list/PrebuildListItem.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx index 6cd00536aea98f..f280cb3cc3c783 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx @@ -21,7 +21,7 @@ type Props = { }; export const RepositoryListItem: FC = ({ prebuild }) => { const created = dayjs(prebuild.status?.startTime?.toDate()).fromNow(); - const { data: configuration } = useConfiguration(prebuild.configurationId); + const { data: configuration, isError: isConfigurationError } = useConfiguration(prebuild.configurationId); const { className: iconColorClass, label } = prebuildDisplayProps(prebuild); const PrebuildStatusIcon = prebuildStatusIconName(prebuild); @@ -29,7 +29,9 @@ export const RepositoryListItem: FC = ({ prebuild }) => {
    - {configuration?.name} + + {isConfigurationError ? "Unknown" : configuration?.name} + {prebuild.ref}
    From 6f2fbce7dbac2d5e0f519e3baa85cf7a219c2210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Wed, 31 Jan 2024 21:38:19 +0000 Subject: [PATCH 35/49] typo --- .../repositories/detail/general/RemoveConfigurationModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dashboard/src/repositories/detail/general/RemoveConfigurationModal.tsx b/components/dashboard/src/repositories/detail/general/RemoveConfigurationModal.tsx index 85ab0fbf0b6fc1..b539232aea131c 100644 --- a/components/dashboard/src/repositories/detail/general/RemoveConfigurationModal.tsx +++ b/components/dashboard/src/repositories/detail/general/RemoveConfigurationModal.tsx @@ -34,7 +34,7 @@ export const RemoveConfigurationModal: FunctionComponent Date: Thu, 1 Feb 2024 11:07:13 +0000 Subject: [PATCH 36/49] Better unknown inference --- .../dashboard/src/prebuilds/list/PrebuildListItem.tsx | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx index f280cb3cc3c783..b1f6e0ceaf2196 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx @@ -21,7 +21,11 @@ type Props = { }; export const RepositoryListItem: FC = ({ prebuild }) => { const created = dayjs(prebuild.status?.startTime?.toDate()).fromNow(); - const { data: configuration, isError: isConfigurationError } = useConfiguration(prebuild.configurationId); + const { + data: configuration, + isError: isConfigurationError, + isLoading: isConfigurationLoading, + } = useConfiguration(prebuild.configurationId); const { className: iconColorClass, label } = prebuildDisplayProps(prebuild); const PrebuildStatusIcon = prebuildStatusIconName(prebuild); @@ -30,7 +34,9 @@ export const RepositoryListItem: FC = ({ prebuild }) => {
    - {isConfigurationError ? "Unknown" : configuration?.name} + {!isConfigurationLoading && (isConfigurationError || configuration?.name) + ? "Unknown repository" + : configuration?.name} {prebuild.ref}
    From f255b96c0e7e5b80dfba8cf27a5e1ef740a8dda8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Thu, 1 Feb 2024 14:50:20 +0000 Subject: [PATCH 37/49] Add ConfigurationField component to display repository name and link --- .../src/prebuilds/list/PrebuildListItem.tsx | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx index b1f6e0ceaf2196..e703769b58a70c 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx @@ -15,6 +15,9 @@ import { prebuildDisplayProps, prebuildStatusIconName } from "../../projects/Pre import dayjs from "dayjs"; import { cn } from "@podkit/lib/cn"; import { shortCommitMessage } from "../../projects/render-utils"; +import { Link } from "react-router-dom"; +import { Configuration } from "@gitpod/public-api/lib/gitpod/v1/configuration_pb"; +import { LoadingState } from "@podkit/loading/LoadingState"; type Props = { prebuild: Prebuild; @@ -34,9 +37,11 @@ export const RepositoryListItem: FC = ({ prebuild }) => {
    - {!isConfigurationLoading && (isConfigurationError || configuration?.name) - ? "Unknown repository" - : configuration?.name} + {prebuild.ref}
    @@ -77,3 +82,20 @@ export const RepositoryListItem: FC = ({ prebuild }) => {
    ); }; + +type ConfigurationProps = { + configuration?: Configuration; + isLoading: boolean; + isError: boolean; +}; +const ConfigurationField = ({ configuration, isLoading, isError }: ConfigurationProps) => { + if (isLoading) { + return ; + } + + if (isError || !configuration?.name || !configuration.id) { + return Unknown repository; + } + + return {configuration.name}; +}; From bff57a8a42c3a9e83de7f6c5e5d3eeb7a2a90220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Thu, 1 Feb 2024 15:27:44 +0000 Subject: [PATCH 38/49] Do not retry configuration load --- .../configurations/configuration-queries.ts | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/components/dashboard/src/data/configurations/configuration-queries.ts b/components/dashboard/src/data/configurations/configuration-queries.ts index 141bed9e401494..db3015c13048d6 100644 --- a/components/dashboard/src/data/configurations/configuration-queries.ts +++ b/components/dashboard/src/data/configurations/configuration-queries.ts @@ -16,6 +16,7 @@ import { ConfigurationEnvironmentVariable, EnvironmentVariableAdmission, } from "@gitpod/public-api/lib/gitpod/v1/envvar_pb"; +import { ErrorCodes } from "@gitpod/gitpod-protocol/lib/messaging/error"; const BASE_KEY = "configurations"; @@ -83,13 +84,28 @@ export const getListConfigurationsVariablesQueryKey = (configurationId: string) }; export const useConfiguration = (configurationId: string) => { - return useQuery(getConfigurationQueryKey(configurationId), async () => { - const { configuration } = await configurationClient.getConfiguration({ - configurationId, - }); + return useQuery( + getConfigurationQueryKey(configurationId), + async () => { + const { configuration } = await configurationClient.getConfiguration({ + configurationId, + }); - return configuration; - }); + return configuration; + }, + { + retry: (failureCount, error) => { + if (failureCount > 3) { + return false; + } + + if (error && [ErrorCodes.NOT_FOUND, ErrorCodes.PERMISSION_DENIED].includes((error as any).code)) { + return false; + } + return true; + }, + }, + ); }; type DeleteConfigurationArgs = { From 9df7d1e1ea208f013206bc387f0dc335c469902a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Thu, 1 Feb 2024 16:06:03 +0000 Subject: [PATCH 39/49] Move prebuild utils --- .../src/prebuilds/list/PrebuildListItem.tsx | 2 +- .../dashboard/src/projects/Prebuilds.tsx | 106 +---------------- .../dashboard/src/projects/prebuild-utils.tsx | 112 ++++++++++++++++++ 3 files changed, 115 insertions(+), 105 deletions(-) create mode 100644 components/dashboard/src/projects/prebuild-utils.tsx diff --git a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx index e703769b58a70c..421033e8eb2df2 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx @@ -11,13 +11,13 @@ import { LinkButton } from "@podkit/buttons/LinkButton"; import { TableCell, TableRow } from "@podkit/tables/Table"; import type { Prebuild } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; import { useConfiguration } from "../../data/configurations/configuration-queries"; -import { prebuildDisplayProps, prebuildStatusIconName } from "../../projects/Prebuilds"; import dayjs from "dayjs"; import { cn } from "@podkit/lib/cn"; import { shortCommitMessage } from "../../projects/render-utils"; import { Link } from "react-router-dom"; import { Configuration } from "@gitpod/public-api/lib/gitpod/v1/configuration_pb"; import { LoadingState } from "@podkit/loading/LoadingState"; +import { prebuildDisplayProps, prebuildStatusIconName } from "../../projects/prebuild-utils"; type Props = { prebuild: Prebuild; diff --git a/components/dashboard/src/projects/Prebuilds.tsx b/components/dashboard/src/projects/Prebuilds.tsx index 0693e6119a2214..cb6b91816b23b6 100644 --- a/components/dashboard/src/projects/Prebuilds.tsx +++ b/components/dashboard/src/projects/Prebuilds.tsx @@ -6,16 +6,11 @@ import dayjs from "dayjs"; import { Project } from "@gitpod/gitpod-protocol"; -import { ForwardRefExoticComponent, useEffect, useState } from "react"; +import { useEffect, useState } from "react"; import Header from "../components/Header"; import DropDown, { DropDownEntry } from "../components/DropDown"; import { ItemsList, Item, ItemField } from "../components/ItemsList"; import Spinner from "../icons/Spinner.svg"; -import StatusDone from "../icons/StatusDone.svg"; -import StatusFailed from "../icons/StatusFailed.svg"; -import StatusCanceled from "../icons/StatusCanceled.svg"; -import StatusPaused from "../icons/StatusPaused.svg"; -import StatusRunning from "../icons/StatusRunning.svg"; import { shortCommitMessage } from "./render-utils"; import { Link, Redirect } from "react-router-dom"; import { useCurrentProject } from "./project-context"; @@ -25,7 +20,7 @@ import Tooltip from "../components/Tooltip"; import { prebuildClient, watchPrebuild } from "../service/public-api"; import { Prebuild, PrebuildPhase_Phase } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; import { Button } from "@podkit/buttons/Button"; -import { CheckCircle2, CircleSlash, Clock, HelpCircle, LucideProps, PauseCircle, XCircle } from "lucide-react"; +import { getPrebuildStatusDescription, prebuildStatusIcon, prebuildStatusLabel } from "./prebuild-utils"; export default function PrebuildsPage(props: { project?: Project; isAdminDashboard?: boolean }) { const currentProject = useCurrentProject(); @@ -285,103 +280,6 @@ export default function PrebuildsPage(props: { project?: Project; isAdminDashboa ); } -export const prebuildDisplayProps = (prebuild: Prebuild): { className: string; label: string } => { - switch (prebuild.status?.phase?.name) { - case PrebuildPhase_Phase.UNSPECIFIED: // Fall through - case PrebuildPhase_Phase.QUEUED: - return { className: "text-orange-500", label: "pending" }; - case PrebuildPhase_Phase.BUILDING: - return { className: "text-blue-500", label: "running" }; - case PrebuildPhase_Phase.ABORTED: - return { className: "text-gray-500", label: "cancelled" }; - case PrebuildPhase_Phase.FAILED: - return { className: "text-red-500", label: "system error" }; - case PrebuildPhase_Phase.TIMEOUT: - return { className: "text-red-500", label: "timed out" }; - case PrebuildPhase_Phase.AVAILABLE: - if (prebuild.status?.message) { - return { className: "text-red-500", label: "failed" }; - } - return { className: "text-green-500", label: "ready" }; - } - - return { className: "", label: "" }; -}; - -export function prebuildStatusLabel(prebuild: Prebuild): JSX.Element { - const { className, label } = prebuildDisplayProps(prebuild); - return {label}; -} - -export function prebuildStatusIconName(prebuild: Prebuild): ForwardRefExoticComponent { - switch (prebuild.status?.phase?.name) { - case PrebuildPhase_Phase.UNSPECIFIED: // Fall through - case PrebuildPhase_Phase.QUEUED: - return PauseCircle; - case PrebuildPhase_Phase.BUILDING: - return Clock; - case PrebuildPhase_Phase.ABORTED: - return CircleSlash; - case PrebuildPhase_Phase.TIMEOUT: - case PrebuildPhase_Phase.FAILED: - return XCircle; - case PrebuildPhase_Phase.AVAILABLE: - if (prebuild?.status?.message) { - return XCircle; - } - return CheckCircle2; - } - - return HelpCircle; -} - -export function prebuildStatusIcon(prebuild?: Prebuild) { - switch (prebuild?.status?.phase?.name) { - case PrebuildPhase_Phase.UNSPECIFIED: // Fall through - case PrebuildPhase_Phase.QUEUED: - return ; - case PrebuildPhase_Phase.BUILDING: - return ; - case PrebuildPhase_Phase.ABORTED: - return ; - case PrebuildPhase_Phase.FAILED: - return ; - case PrebuildPhase_Phase.TIMEOUT: - return ; - case PrebuildPhase_Phase.AVAILABLE: - if (prebuild?.status?.message) { - return ; - } - return ; - } -} - -function getPrebuildStatusDescription(prebuild: Prebuild): string { - switch (prebuild.status?.phase?.name) { - case PrebuildPhase_Phase.QUEUED: - return `Prebuild is queued and will be processed when there is execution capacity.`; - case PrebuildPhase_Phase.BUILDING: - return `Prebuild is currently in progress.`; - case PrebuildPhase_Phase.ABORTED: - return `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. ${ - prebuild.status?.message || "" - }`; - case PrebuildPhase_Phase.FAILED: - return `Prebuild failed for system reasons. Please contact support. ${prebuild.status?.message || ""}`; - case PrebuildPhase_Phase.TIMEOUT: - return `Prebuild timed out. Either the image, or the prebuild tasks took too long. ${ - prebuild.status?.message || "" - }`; - case PrebuildPhase_Phase.AVAILABLE: - if (prebuild.status?.message) { - return `The tasks executed in the prebuild returned a non-zero exit code. ${prebuild.status.message}`; - } - return `Prebuild completed successfully.`; - default: - return `Unknown prebuild status.`; - } -} - export function PrebuildStatus(props: { prebuild: Prebuild }) { const prebuild = props.prebuild; diff --git a/components/dashboard/src/projects/prebuild-utils.tsx b/components/dashboard/src/projects/prebuild-utils.tsx new file mode 100644 index 00000000000000..0680ddc5a543f4 --- /dev/null +++ b/components/dashboard/src/projects/prebuild-utils.tsx @@ -0,0 +1,112 @@ +/** + * Copyright (c) 2024 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License.AGPL.txt in the project root for license information. + */ + +import { Prebuild, PrebuildPhase_Phase } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; +import { PauseCircle, LucideProps, Clock, CircleSlash, CheckCircle2, HelpCircle, XCircle } from "lucide-react"; +import type { ForwardRefExoticComponent } from "react"; + +import StatusDone from "../icons/StatusDone.svg"; +import StatusFailed from "../icons/StatusFailed.svg"; +import StatusCanceled from "../icons/StatusCanceled.svg"; +import StatusPaused from "../icons/StatusPaused.svg"; +import StatusRunning from "../icons/StatusRunning.svg"; + +export const prebuildDisplayProps = (prebuild: Prebuild): { className: string; label: string } => { + switch (prebuild.status?.phase?.name) { + case PrebuildPhase_Phase.UNSPECIFIED: // Fall through + case PrebuildPhase_Phase.QUEUED: + return { className: "text-orange-500", label: "pending" }; + case PrebuildPhase_Phase.BUILDING: + return { className: "text-blue-500", label: "running" }; + case PrebuildPhase_Phase.ABORTED: + return { className: "text-gray-500", label: "cancelled" }; + case PrebuildPhase_Phase.FAILED: + return { className: "text-red-500", label: "system error" }; + case PrebuildPhase_Phase.TIMEOUT: + return { className: "text-red-500", label: "timed out" }; + case PrebuildPhase_Phase.AVAILABLE: + if (prebuild.status?.message) { + return { className: "text-red-500", label: "failed" }; + } + return { className: "text-green-500", label: "ready" }; + } + + return { className: "", label: "" }; +}; + +export const prebuildStatusLabel = (prebuild: Prebuild): JSX.Element => { + const { className, label } = prebuildDisplayProps(prebuild); + return {label}; +}; + +export const prebuildStatusIconName = (prebuild: Prebuild): ForwardRefExoticComponent => { + switch (prebuild.status?.phase?.name) { + case PrebuildPhase_Phase.UNSPECIFIED: // Fall through + case PrebuildPhase_Phase.QUEUED: + return PauseCircle; + case PrebuildPhase_Phase.BUILDING: + return Clock; + case PrebuildPhase_Phase.ABORTED: + return CircleSlash; + case PrebuildPhase_Phase.TIMEOUT: + case PrebuildPhase_Phase.FAILED: + return XCircle; + case PrebuildPhase_Phase.AVAILABLE: + if (prebuild?.status?.message) { + return XCircle; + } + return CheckCircle2; + } + + return HelpCircle; +}; + +export const prebuildStatusIcon = (prebuild?: Prebuild) => { + switch (prebuild?.status?.phase?.name) { + case PrebuildPhase_Phase.UNSPECIFIED: // Fall through + case PrebuildPhase_Phase.QUEUED: + return ; + case PrebuildPhase_Phase.BUILDING: + return ; + case PrebuildPhase_Phase.ABORTED: + return ; + case PrebuildPhase_Phase.FAILED: + return ; + case PrebuildPhase_Phase.TIMEOUT: + return ; + case PrebuildPhase_Phase.AVAILABLE: + if (prebuild?.status?.message) { + return ; + } + return ; + } +}; + +export const getPrebuildStatusDescription = (prebuild: Prebuild): string => { + switch (prebuild.status?.phase?.name) { + case PrebuildPhase_Phase.QUEUED: + return `Prebuild is queued and will be processed when there is execution capacity.`; + case PrebuildPhase_Phase.BUILDING: + return `Prebuild is currently in progress.`; + case PrebuildPhase_Phase.ABORTED: + return `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. ${ + prebuild.status?.message || "" + }`; + case PrebuildPhase_Phase.FAILED: + return `Prebuild failed for system reasons. Please contact support. ${prebuild.status?.message || ""}`; + case PrebuildPhase_Phase.TIMEOUT: + return `Prebuild timed out. Either the image, or the prebuild tasks took too long. ${ + prebuild.status?.message || "" + }`; + case PrebuildPhase_Phase.AVAILABLE: + if (prebuild.status?.message) { + return `The tasks executed in the prebuild returned a non-zero exit code. ${prebuild.status.message}`; + } + return `Prebuild completed successfully.`; + default: + return `Unknown prebuild status.`; + } +}; From d897c587e880f1504243cfb3cc9bcd3260ac13fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Thu, 1 Feb 2024 16:15:02 +0000 Subject: [PATCH 40/49] Unify sort types --- components/dashboard/src/prebuilds/list/PrebuildTable.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx index 2ba28c0711742a..1f20d27818a9f6 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx @@ -14,17 +14,14 @@ import { cn } from "@podkit/lib/cn"; import { LoadingState } from "@podkit/loading/LoadingState"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@podkit/select/Select"; import { Prebuild } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; -import { Filter, SortField, StatusOption } from "./PrebuildList"; +import { Filter, Sort, SortField, StatusOption } from "./PrebuildList"; import { SortCallback, SortableTableHead, TableSortOrder } from "@podkit/tables/SortableTable"; import ConfigurationDropdown from "./ConfigurationInput"; type Props = { prebuilds: Prebuild[]; filter?: Filter; - sort: { - sortBy: SortField; - sortOrder: TableSortOrder; - }; + sort: Sort; hasNextPage: boolean; hasMoreThanOnePage: boolean; isSearching: boolean; From bfdab82541acae35a6c956d0f57edd1ccf998eda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Thu, 1 Feb 2024 16:17:08 +0000 Subject: [PATCH 41/49] Refactor PrebuildTable to use arrow function syntax for mapping prebuilds --- components/dashboard/src/prebuilds/list/PrebuildTable.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx index 1f20d27818a9f6..ffac20526332dc 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx @@ -103,9 +103,9 @@ export const PrebuildsTable: FC = ({ - {prebuilds.map((configuration) => { - return ; - })} + {prebuilds.map((configuration) => ( + + ))} ) : ( From 9fabef697435cf47440cc52b71c09025f211408b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Thu, 1 Feb 2024 16:30:22 +0000 Subject: [PATCH 42/49] fix imports --- components/dashboard/src/projects/Project.tsx | 2 +- components/dashboard/src/projects/ProjectListItem.tsx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/dashboard/src/projects/Project.tsx b/components/dashboard/src/projects/Project.tsx index 4feac0d55b1b43..1a5e31fc7996cd 100644 --- a/components/dashboard/src/projects/Project.tsx +++ b/components/dashboard/src/projects/Project.tsx @@ -17,7 +17,6 @@ import NoAccess from "../icons/NoAccess.svg"; import { ReactComponent as Spinner } from "../icons/Spinner.svg"; import { openAuthorizeWindow } from "../provider-utils"; import { getGitpodService, gitpodHostUrl } from "../service/service"; -import { prebuildStatusIcon, prebuildStatusLabel } from "./Prebuilds"; import { useCurrentProject } from "./project-context"; import { getProjectTabs } from "./projects.routes"; import { shortCommitMessage, toRemoteURL } from "./render-utils"; @@ -26,6 +25,7 @@ import Tooltip from "../components/Tooltip"; import { prebuildClient } from "../service/public-api"; import { Prebuild, PrebuildPhase_Phase } from "@gitpod/public-api/lib/gitpod/v1/prebuild_pb"; import { Button } from "@podkit/buttons/Button"; +import { prebuildStatusIcon, prebuildStatusLabel } from "./prebuild-utils"; export default function ProjectsPage() { const history = useHistory(); diff --git a/components/dashboard/src/projects/ProjectListItem.tsx b/components/dashboard/src/projects/ProjectListItem.tsx index c763e350b6149d..03ce87eb11ab2f 100644 --- a/components/dashboard/src/projects/ProjectListItem.tsx +++ b/components/dashboard/src/projects/ProjectListItem.tsx @@ -10,12 +10,12 @@ import { Project } from "@gitpod/gitpod-protocol"; import { Link } from "react-router-dom"; import { RemoveProjectModal } from "./RemoveProjectModal"; import { toRemoteURL } from "./render-utils"; -import { prebuildStatusIcon } from "./Prebuilds"; import { gitpodHostUrl } from "../service/service"; import { useLatestProjectPrebuildQuery } from "../data/prebuilds/latest-project-prebuild-query"; import Tooltip from "../components/Tooltip"; import { DropdownActions } from "@podkit/dropdown/DropDownActions"; import { DropdownMenuItem } from "@podkit/dropdown/DropDown"; +import { prebuildStatusIcon } from "./prebuild-utils"; type ProjectListItemProps = { project: Project; From 4a13f771e1285bff8f2545908efd9f81b820027c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Thu, 1 Feb 2024 16:45:59 +0000 Subject: [PATCH 43/49] Widen triggered column --- components/dashboard/src/prebuilds/list/PrebuildTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx index ffac20526332dc..dd9ca81dbc841e 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx @@ -86,7 +86,7 @@ export const PrebuildsTable: FC = ({ columnName={sort.sortBy} sortOrder={sort.sortOrder} onSort={onSort as SortCallback} - className="w-32" + className="w-36" hideOnSmallScreen > Triggered From 2f514438eb9475f4a17afb4d9765fcadcfae9373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Thu, 1 Feb 2024 17:16:50 +0000 Subject: [PATCH 44/49] Widen even more --- components/dashboard/src/prebuilds/list/PrebuildTable.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx index dd9ca81dbc841e..0ea837dd83fd18 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx @@ -86,7 +86,7 @@ export const PrebuildsTable: FC = ({ columnName={sort.sortBy} sortOrder={sort.sortOrder} onSort={onSort as SortCallback} - className="w-36" + className="w-40" hideOnSmallScreen > Triggered From f9ae1954a4395fd9a20ddf1a53710eee33231318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Thu, 1 Feb 2024 20:33:28 +0000 Subject: [PATCH 45/49] Shorten status labels --- components/dashboard/src/projects/prebuild-utils.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/dashboard/src/projects/prebuild-utils.tsx b/components/dashboard/src/projects/prebuild-utils.tsx index 0680ddc5a543f4..beddd75101a065 100644 --- a/components/dashboard/src/projects/prebuild-utils.tsx +++ b/components/dashboard/src/projects/prebuild-utils.tsx @@ -24,9 +24,9 @@ export const prebuildDisplayProps = (prebuild: Prebuild): { className: string; l case PrebuildPhase_Phase.ABORTED: return { className: "text-gray-500", label: "cancelled" }; case PrebuildPhase_Phase.FAILED: - return { className: "text-red-500", label: "system error" }; + return { className: "text-red-500", label: "error" }; case PrebuildPhase_Phase.TIMEOUT: - return { className: "text-red-500", label: "timed out" }; + return { className: "text-red-500", label: "timeout" }; case PrebuildPhase_Phase.AVAILABLE: if (prebuild.status?.message) { return { className: "text-red-500", label: "failed" }; From 6a83afcde25096ce045f3b9b2c10dae8981b4787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 5 Feb 2024 16:17:34 +0000 Subject: [PATCH 46/49] Init ws db tests --- .../src/typeorm/workspace-db-impl.spec.db.ts | 179 ++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 components/gitpod-db/src/typeorm/workspace-db-impl.spec.db.ts diff --git a/components/gitpod-db/src/typeorm/workspace-db-impl.spec.db.ts b/components/gitpod-db/src/typeorm/workspace-db-impl.spec.db.ts new file mode 100644 index 00000000000000..72824070747210 --- /dev/null +++ b/components/gitpod-db/src/typeorm/workspace-db-impl.spec.db.ts @@ -0,0 +1,179 @@ +/** + * Copyright (c) 2024 Gitpod GmbH. All rights reserved. + * Licensed under the GNU Affero General Public License (AGPL). + * See License.AGPL.txt in the project root for license information. + */ + +import { suite, test, timeout } from "@testdeck/mocha"; +import { testContainer } from "../test-container"; +import { TypeORM } from "./typeorm"; +import * as chai from "chai"; +import { resetDB } from "../test/reset-db"; +import { WorkspaceDB } from "../workspace-db"; +import { randomUUID } from "crypto"; +import { PrebuiltWorkspaceState } from "@gitpod/gitpod-protocol"; +const expect = chai.expect; + +@suite(timeout(10000)) +export class WorkspaceSpec { + private readonly wsDB = testContainer.get(WorkspaceDB); + + readonly org = randomUUID(); + readonly strangerOrg = randomUUID(); + + async before() { + await this.wipeRepo(); + } + + async after() { + await this.wipeRepo(); + } + + async wipeRepo() { + const typeorm = testContainer.get(TypeORM); + await resetDB(typeorm); + } + + protected async setupPrebuilds() { + const today = new Date(); + const yesterday = new Date(today); + yesterday.setDate(yesterday.getDate() - 1); + const tomorrow = new Date(today); + tomorrow.setDate(tomorrow.getDate() + 1); + + const now = new Date().toISOString(); + + const states: PrebuiltWorkspaceState[] = [ + "queued", + "building", + "aborted", + "timeout", + "available", + "available", + "failed", + ]; + const errors = [undefined, undefined, undefined, undefined, "failed", undefined, undefined]; + + // Mock all possible states (including two possible states for "available" with and without an error value) + for (let i = 0; i < states.length; i++) { + const prebuildId = randomUUID(); + const workspaceId = randomUUID(); + const state = states[i]; + const error = errors[i]; + + const ws = await this.wsDB.store({ + id: workspaceId, + type: "prebuild", + creationTime: now, + organizationId: this.org, + contextURL: "https://github.com/gitpod-io/gitpod", + description: "Gitpod", + ownerId: randomUUID(), + projectId: randomUUID(), + context: { + title: "Gitpod", + }, + config: {}, + }); + + await this.wsDB.storePrebuiltWorkspace({ + id: prebuildId, + cloneURL: "https://github.com/gitpod-io/gitpod", + commit: "aeioufg", + buildWorkspaceId: ws.id, + creationTime: now, + state, + error, + statusVersion: 1, + }); + + await this.wsDB.storePrebuildInfo({ + teamId: this.org, + id: randomUUID(), + buildWorkspaceId: ws.id, + projectId: "gitpod", + projectName: "Gitpod", + cloneUrl: "https://github.com/gitpod-io/gitpod", + branch: "main", + startedAt: now, + startedBy: "me", + changeTitle: "Change this", + changeDate: now, + changeAuthor: "me again", + changeHash: "aeioufg", + }); + } + } + + @test() + async testPrebuildLookupByOrg(): Promise { + await this.setupPrebuilds(); + + const orgLookup = await this.wsDB.findPrebuiltWorkspacesByOrganization( + this.org, + { limit: 10, offset: 0 }, + {}, + { field: "creationTime", order: "ASC" }, + ); + expect(orgLookup).length(7); + + const strangerOrgLookup = await this.wsDB.findPrebuiltWorkspacesByOrganization( + this.strangerOrg, + { limit: 10, offset: 0 }, + {}, + { field: "creationTime", order: "ASC" }, + ); + expect(strangerOrgLookup).length(0); + } + + @test() + async testPrebuildLookupByOrgWithFilters(): Promise { + await this.setupPrebuilds(); + + const stateUnfinished = await this.wsDB.findPrebuiltWorkspacesByOrganization( + this.org, + { limit: 10, offset: 0 }, + { state: "unfinished" }, + { field: "creationTime", order: "ASC" }, + ); + expect(stateUnfinished).length(2); + + const stateFailed = await this.wsDB.findPrebuiltWorkspacesByOrganization( + this.org, + { limit: 10, offset: 0 }, + { state: "failed" }, + { field: "creationTime", order: "ASC" }, + ); + expect(stateFailed).length(4); + + const stateSucceeded = await this.wsDB.findPrebuiltWorkspacesByOrganization( + this.org, + { limit: 10, offset: 0 }, + { state: "succeeded" }, + { field: "creationTime", order: "ASC" }, + ); + expect(stateSucceeded).length(1); + } + + @test() + async testPrebuildLookupByOrgPagination(): Promise { + await this.setupPrebuilds(); + + const firstPage = await this.wsDB.findPrebuiltWorkspacesByOrganization( + this.org, + { limit: 3, offset: 0 }, + {}, + { field: "creationTime", order: "ASC" }, + ); + expect(firstPage).length(3); + + const secondPage = await this.wsDB.findPrebuiltWorkspacesByOrganization( + this.org, + { limit: 3, offset: 3 }, + {}, + { field: "creationTime", order: "ASC" }, + ); + expect(secondPage).length(3); + expect(secondPage[0].id).not.eq(firstPage[0].id); + } +} From 92ede9a0b5c8a01a82552b07613f25f9e3e87465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 5 Feb 2024 17:17:14 +0000 Subject: [PATCH 47/49] Rename list item comp accordingly T'was an oopsie doopsie --- components/dashboard/src/prebuilds/list/PrebuildListItem.tsx | 2 +- components/dashboard/src/prebuilds/list/PrebuildTable.tsx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx index 421033e8eb2df2..7125725a68fefb 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildListItem.tsx @@ -22,7 +22,7 @@ import { prebuildDisplayProps, prebuildStatusIconName } from "../../projects/pre type Props = { prebuild: Prebuild; }; -export const RepositoryListItem: FC = ({ prebuild }) => { +export const PrebuildListItem: FC = ({ prebuild }) => { const created = dayjs(prebuild.status?.startTime?.toDate()).fromNow(); const { data: configuration, diff --git a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx index 0ea837dd83fd18..4233fb7476d69e 100644 --- a/components/dashboard/src/prebuilds/list/PrebuildTable.tsx +++ b/components/dashboard/src/prebuilds/list/PrebuildTable.tsx @@ -6,7 +6,7 @@ import { FC } from "react"; import { Table, TableBody, TableHead, TableHeader, TableRow } from "@podkit/tables/Table"; -import { RepositoryListItem } from "./PrebuildListItem"; +import { PrebuildListItem } from "./PrebuildListItem"; import { LoadingButton } from "@podkit/buttons/LoadingButton"; import { TextMuted } from "@podkit/typography/TextMuted"; import { Subheading } from "@podkit/typography/Headings"; @@ -104,7 +104,7 @@ export const PrebuildsTable: FC = ({ {prebuilds.map((configuration) => ( - + ))} From e607d8d73194aa491ecb587b86771170af857264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 5 Feb 2024 18:08:09 +0000 Subject: [PATCH 48/49] Test configuration ids and branches filtering --- .../src/typeorm/workspace-db-impl.spec.db.ts | 94 ++++++++++++++----- 1 file changed, 72 insertions(+), 22 deletions(-) diff --git a/components/gitpod-db/src/typeorm/workspace-db-impl.spec.db.ts b/components/gitpod-db/src/typeorm/workspace-db-impl.spec.db.ts index 72824070747210..fa70e35baed804 100644 --- a/components/gitpod-db/src/typeorm/workspace-db-impl.spec.db.ts +++ b/components/gitpod-db/src/typeorm/workspace-db-impl.spec.db.ts @@ -21,6 +21,16 @@ export class WorkspaceSpec { readonly org = randomUUID(); readonly strangerOrg = randomUUID(); + readonly configuration = { + cloneUrl: "https://github.com/gitpod-io/gitpod", + id: randomUUID(), + branch: "main", + commit: "3fedc3251be3f917d9e44f5f3d785e21153e067e", + }; + + readonly defaultSorting = { field: "creationTime", order: "ASC" } as const; + readonly defaultPagination = { limit: 10, offset: 0 }; + async before() { await this.wipeRepo(); } @@ -66,22 +76,25 @@ export class WorkspaceSpec { type: "prebuild", creationTime: now, organizationId: this.org, - contextURL: "https://github.com/gitpod-io/gitpod", + contextURL: this.configuration.cloneUrl, description: "Gitpod", ownerId: randomUUID(), - projectId: randomUUID(), + projectId: this.configuration.id, context: { title: "Gitpod", + ref: this.configuration.branch, }, config: {}, }); await this.wsDB.storePrebuiltWorkspace({ id: prebuildId, - cloneURL: "https://github.com/gitpod-io/gitpod", - commit: "aeioufg", + cloneURL: this.configuration.cloneUrl, + commit: this.configuration.commit, + projectId: this.configuration.id, buildWorkspaceId: ws.id, creationTime: now, + branch: this.configuration.branch, state, error, statusVersion: 1, @@ -91,16 +104,16 @@ export class WorkspaceSpec { teamId: this.org, id: randomUUID(), buildWorkspaceId: ws.id, - projectId: "gitpod", - projectName: "Gitpod", - cloneUrl: "https://github.com/gitpod-io/gitpod", - branch: "main", + projectId: this.configuration.id, + projectName: "gitpod", + cloneUrl: this.configuration.cloneUrl, + branch: this.configuration.branch, startedAt: now, startedBy: "me", changeTitle: "Change this", changeDate: now, changeAuthor: "me again", - changeHash: "aeioufg", + changeHash: this.configuration.commit, }); } } @@ -111,50 +124,87 @@ export class WorkspaceSpec { const orgLookup = await this.wsDB.findPrebuiltWorkspacesByOrganization( this.org, - { limit: 10, offset: 0 }, + this.defaultPagination, {}, - { field: "creationTime", order: "ASC" }, + this.defaultSorting, ); expect(orgLookup).length(7); const strangerOrgLookup = await this.wsDB.findPrebuiltWorkspacesByOrganization( this.strangerOrg, - { limit: 10, offset: 0 }, + this.defaultPagination, {}, - { field: "creationTime", order: "ASC" }, + this.defaultSorting, ); expect(strangerOrgLookup).length(0); } @test() - async testPrebuildLookupByOrgWithFilters(): Promise { + async testPrebuildLookupByOrgWithStateFilters(): Promise { await this.setupPrebuilds(); const stateUnfinished = await this.wsDB.findPrebuiltWorkspacesByOrganization( this.org, - { limit: 10, offset: 0 }, + this.defaultPagination, { state: "unfinished" }, - { field: "creationTime", order: "ASC" }, + this.defaultSorting, ); expect(stateUnfinished).length(2); const stateFailed = await this.wsDB.findPrebuiltWorkspacesByOrganization( this.org, - { limit: 10, offset: 0 }, + this.defaultPagination, { state: "failed" }, - { field: "creationTime", order: "ASC" }, + this.defaultSorting, ); expect(stateFailed).length(4); const stateSucceeded = await this.wsDB.findPrebuiltWorkspacesByOrganization( this.org, - { limit: 10, offset: 0 }, + this.defaultPagination, { state: "succeeded" }, - { field: "creationTime", order: "ASC" }, + this.defaultSorting, ); expect(stateSucceeded).length(1); } + @test() + async testPrebuildLookupByOrgWithConfigurationFilter(): Promise { + await this.setupPrebuilds(); + + const filtered = await this.wsDB.findPrebuiltWorkspacesByOrganization( + this.org, + this.defaultPagination, + { configuration: { id: this.configuration.id } }, + this.defaultSorting, + ); + expect(filtered).length(7); + + const filteredNonExistent = await this.wsDB.findPrebuiltWorkspacesByOrganization( + this.org, + this.defaultPagination, + { configuration: { id: "nonexistent" } }, + this.defaultSorting, + ); + expect(filteredNonExistent).length(0); + + const filteredBranch = await this.wsDB.findPrebuiltWorkspacesByOrganization( + this.org, + this.defaultPagination, + { configuration: { id: this.configuration.id, branch: this.configuration.branch } }, + this.defaultSorting, + ); + expect(filteredBranch).length(7); + + const filteredBranchNonExistent = await this.wsDB.findPrebuiltWorkspacesByOrganization( + this.org, + this.defaultPagination, + { configuration: { id: this.configuration.id, branch: "nonexistent" } }, + this.defaultSorting, + ); + expect(filteredBranchNonExistent).length(0); + } + @test() async testPrebuildLookupByOrgPagination(): Promise { await this.setupPrebuilds(); @@ -163,7 +213,7 @@ export class WorkspaceSpec { this.org, { limit: 3, offset: 0 }, {}, - { field: "creationTime", order: "ASC" }, + this.defaultSorting, ); expect(firstPage).length(3); @@ -171,7 +221,7 @@ export class WorkspaceSpec { this.org, { limit: 3, offset: 3 }, {}, - { field: "creationTime", order: "ASC" }, + this.defaultSorting, ); expect(secondPage).length(3); expect(secondPage[0].id).not.eq(firstPage[0].id); From 4279aae0ead7998aebafabb1e9f5b868eabf84cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Tue, 6 Feb 2024 22:19:47 +0000 Subject: [PATCH 49/49] Remove projects from nav depending on ff --- components/dashboard/src/menu/Menu.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/components/dashboard/src/menu/Menu.tsx b/components/dashboard/src/menu/Menu.tsx index 44c28c01c11881..98e5999abe630b 100644 --- a/components/dashboard/src/menu/Menu.tsx +++ b/components/dashboard/src/menu/Menu.tsx @@ -23,6 +23,7 @@ import { User, RoleOrPermission } from "@gitpod/public-api/lib/gitpod/v1/user_pb import { getPrimaryEmail } from "@gitpod/public-api-common/lib/user-utils"; import { useHasRolePermission } from "../data/organizations/members-query"; import { OrganizationRole } from "@gitpod/public-api/lib/gitpod/v1/organization_pb"; +import { useHasConfigurationsAndPrebuildsEnabled } from "../data/featureflag-query"; interface Entry { title: string; @@ -130,6 +131,7 @@ type OrgPagesNavProps = { const OrgPagesNav: FC = ({ className }) => { const location = useLocation(); const hasMemberPermission = useHasRolePermission(OrganizationRole.MEMBER); + const configurationsEnabled = useHasConfigurationsAndPrebuildsEnabled(); const leftMenu: Entry[] = useMemo(() => { const menus = [ @@ -139,8 +141,8 @@ const OrgPagesNav: FC = ({ className }) => { alternatives: ["/"], }, ]; - // collaborator can't access projects - if (hasMemberPermission) { + // collaborators can't access projects + if (hasMemberPermission && !configurationsEnabled) { menus.push({ title: "Projects", link: `/projects`, @@ -148,7 +150,7 @@ const OrgPagesNav: FC = ({ className }) => { }); } return menus; - }, [hasMemberPermission]); + }, [configurationsEnabled, hasMemberPermission]); return (