Skip to content

Commit

Permalink
Fix incorrect redirects to newer prebuilds (#20047)
Browse files Browse the repository at this point in the history
  • Loading branch information
filiptronicek authored Jul 18, 2024
1 parent 7fea3a2 commit 8df5d2f
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 56 deletions.
15 changes: 4 additions & 11 deletions components/dashboard/src/data/prebuilds/prebuild-queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,21 +64,14 @@ export function useCancelPrebuildMutation() {
});
}

export function useTriggerPrebuildQuery(configurationId?: string, gitRef?: string) {
// we use useQuery instead of useMutation so that we can get data (prebuildId) directly outside
return useQuery<string, Error, string>(
["prebuild-trigger", configurationId, gitRef],
async () => {
export function useTriggerPrebuildMutation(configurationId?: string, gitRef?: string) {
return useMutation({
mutationFn: async () => {
if (!configurationId) {
throw new ApplicationError(ErrorCodes.BAD_REQUEST, "prebuild configurationId is missing");
}

return prebuildClient.startPrebuild({ configurationId, gitRef }).then((resp) => resp.prebuildId);
},
{
enabled: false,
cacheTime: 0,
retry: false,
},
);
});
}
56 changes: 33 additions & 23 deletions components/dashboard/src/prebuilds/detail/PrebuildDetailPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import { Prebuild, PrebuildPhase_Phase, TaskLog } from "@gitpod/public-api/lib/g
import { BreadcrumbNav } from "@podkit/breadcrumbs/BreadcrumbNav";
import { Button } from "@podkit/buttons/Button";
import { FC, useCallback, useEffect, useMemo, useState } from "react";
import { Redirect, useHistory, useParams } from "react-router";
import { useHistory, useParams } from "react-router";
import dayjs from "dayjs";
import { useToast } from "../../components/toasts/Toasts";
import {
isPrebuildDone,
useCancelPrebuildMutation,
usePrebuildQuery,
useTriggerPrebuildQuery,
useTriggerPrebuildMutation,
watchPrebuild,
} from "../../data/prebuilds/prebuild-queries";
import { LinkButton } from "@podkit/buttons/LinkButton";
Expand Down Expand Up @@ -83,16 +83,35 @@ export const PrebuildDetailPage: FC = () => {
return selectedTaskId ?? prebuild?.status?.taskLogs.filter((f) => f.logUrl)[0]?.taskId ?? undefined;
}, [isImageBuild, prebuild, selectedTaskId]);

const {
isFetching: isTriggeringPrebuild,
refetch: triggerPrebuild,
isError: isTriggerError,
error: triggerError,
isRefetching: isTriggeringRefetch,
data: newPrebuildID,
} = useTriggerPrebuildQuery(prebuild?.configurationId, prebuild?.ref);
const triggerPrebuildMutation = useTriggerPrebuildMutation(prebuild?.configurationId, prebuild?.ref);
const cancelPrebuildMutation = useCancelPrebuildMutation();

const [isTriggeringNewPrebuild, setTriggeringNewPrebuild] = useState(false);
const triggerPrebuild = useCallback(async () => {
if (!prebuild) {
return;
}

try {
setTriggeringNewPrebuild(true);
await triggerPrebuildMutation.mutateAsync(undefined, {
onSuccess: (newPrebuildId) => {
history.push(repositoriesRoutes.PrebuildDetail(newPrebuildId));
},
onError: (error) => {
if (error instanceof ApplicationError) {
toast("Failed to trigger prebuild: " + error.message);
}
},
onSettled: () => {
setTriggeringNewPrebuild(false);
},
});
} catch (error) {
console.error("Could not trigger prebuild", error);
}
}, [history, prebuild, toast, triggerPrebuildMutation]);

const triggeredDate = useMemo(() => dayjs(prebuild?.status?.startTime?.toDate()), [prebuild?.status?.startTime]);
const triggeredString = useMemo(() => formatDate(triggeredDate), [triggeredDate]);
const stopDate = useMemo(() => {
Expand Down Expand Up @@ -160,12 +179,6 @@ export const PrebuildDetailPage: FC = () => {

const notFoundError = error instanceof ApplicationError && error.code === ErrorCodes.NOT_FOUND;

useEffect(() => {
if (isTriggerError && triggerError?.message) {
toast("Failed to trigger prebuild: " + triggerError.message);
}
}, [isTriggerError, triggerError, toast]);

const cancelPrebuild = useCallback(async () => {
if (!prebuild) {
return;
Expand All @@ -178,11 +191,6 @@ export const PrebuildDetailPage: FC = () => {
}
}, [prebuild, cancelPrebuildMutation]);

// For some reason, we sometimes hit a case where the newPrebuildID is actually set without us triggering the query.
if (newPrebuildID && prebuild?.id !== newPrebuildID) {
return <Redirect to={repositoriesRoutes.PrebuildDetail(newPrebuildID)} />;
}

return (
<div className="w-full">
<BreadcrumbNav
Expand Down Expand Up @@ -334,9 +342,11 @@ export const PrebuildDetailPage: FC = () => {
</LoadingButton>
) : (
<LoadingButton
loading={isTriggeringRefetch}
loading={isTriggeringNewPrebuild}
disabled={
isTriggeringPrebuild || !prebuild.configurationId || !prebuild.commit?.sha
isTriggeringNewPrebuild ||
!prebuild.configurationId ||
!prebuild.commit?.sha
}
onClick={() => triggerPrebuild()}
>{`Rerun Prebuild (${prebuild.ref})`}</LoadingButton>
Expand Down
53 changes: 31 additions & 22 deletions components/dashboard/src/prebuilds/list/RunPrebuildModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ import { InputField } from "../../components/forms/InputField";
import { AuthorizeGit, useNeedsGitAuthorization } from "../../components/AuthorizeGit";
import { LoadingButton } from "@podkit/buttons/LoadingButton";
import { Button } from "@podkit/buttons/Button";
import { useTriggerPrebuildQuery } from "../../data/prebuilds/prebuild-queries";
import { useTriggerPrebuildMutation } from "../../data/prebuilds/prebuild-queries";
import { SuggestedRepository } from "@gitpod/public-api/lib/gitpod/v1/scm_pb";
import { useConfiguration } from "../../data/configurations/configuration-queries";
import { Link } from "react-router-dom";
import { repositoriesRoutes } from "../../repositories/repositories.routes";
import { TextInputField } from "../../components/forms/TextInputField";
import { ApplicationError } from "@gitpod/gitpod-protocol/lib/messaging/error";

type Props = {
defaultRepositoryId?: string;
Expand All @@ -34,14 +35,29 @@ export const RunPrebuildModal: FC<Props> = ({ defaultRepositoryId: defaultConfig
[defaultConfigurationId, selectedRepo?.configurationId],
);

const {
isFetching,
refetch: startPrebuild,
isError,
error,
isRefetching,
data: prebuildId,
} = useTriggerPrebuildQuery(configurationId, branchName);
const triggerPrebuildMutation = useTriggerPrebuildMutation(configurationId, branchName);
const [isTriggeringNewPrebuild, setTriggeringNewPrebuild] = useState(false);
const triggerPrebuild = useCallback(async () => {
try {
setTriggeringNewPrebuild(true);
await triggerPrebuildMutation.mutateAsync(undefined, {
onSuccess: (newPrebuildId) => {
onRun(newPrebuildId);
onClose();
},
onError: (error) => {
if (error instanceof ApplicationError) {
setCreateErrorMsg(<>Failed to trigger prebuild: {error.message}</>);
}
},
onSettled: () => {
setTriggeringNewPrebuild(false);
},
});
} catch (error) {
console.error("Could not trigger prebuild", error);
}
}, [onClose, onRun, triggerPrebuildMutation]);

const { data: configuration } = useConfiguration(configurationId);

Expand All @@ -65,15 +81,8 @@ export const RunPrebuildModal: FC<Props> = ({ defaultRepositoryId: defaultConfig
return;
}

startPrebuild();
}, [configuration, configurationId, startPrebuild]);

const errorMessage = createErrorMsg || (isError && (error?.message ?? "There was a problem running the prebuild"));

if (prebuildId) {
onRun(prebuildId);
onClose();
}
triggerPrebuild();
}, [configuration, configurationId, triggerPrebuild]);

return (
<Modal visible onClose={onClose} onSubmit={handleSubmit}>
Expand Down Expand Up @@ -102,25 +111,25 @@ export const RunPrebuildModal: FC<Props> = ({ defaultRepositoryId: defaultConfig
}
value={branchName}
onChange={setBranchName}
disabled={isFetching || isRefetching}
disabled={isTriggeringNewPrebuild}
/>
</>
)}
</div>
</ModalBody>
<ModalFooter
alert={
errorMessage && (
createErrorMsg && (
<ModalFooterAlert type="danger" onClose={() => setCreateErrorMsg(undefined)}>
{errorMessage}
{createErrorMsg}
</ModalFooterAlert>
)
}
>
<Button variant="secondary" onClick={onClose}>
Cancel
</Button>
<LoadingButton type="submit" loading={isFetching || isRefetching}>
<LoadingButton type="submit" loading={isTriggeringNewPrebuild}>
Run prebuild
</LoadingButton>
</ModalFooter>
Expand Down

0 comments on commit 8df5d2f

Please sign in to comment.