Skip to content

feat(site): Display workspace build error + option to retry in debug mode #6903

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Mar 31, 2023
Prev Previous commit
Next Next commit
feat(site): Display build error
  • Loading branch information
BrunoQuaresma committed Mar 30, 2023
commit bebc6aac0c6450b5f1d0747b32156509a6db385c
16 changes: 12 additions & 4 deletions site/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -489,15 +489,23 @@ export const postWorkspaceBuild = async (
export const startWorkspace = (
workspaceId: string,
templateVersionID: string,
debug = false,
) =>
postWorkspaceBuild(workspaceId, {
transition: "start",
template_version_id: templateVersionID,
log_level: debug ? "debug" : undefined,
})
export const stopWorkspace = (workspaceId: string, debug = false) =>
postWorkspaceBuild(workspaceId, {
transition: "stop",
log_level: debug ? "debug" : undefined,
})
export const deleteWorkspace = (workspaceId: string, debug = false) =>
postWorkspaceBuild(workspaceId, {
transition: "delete",
log_level: debug ? "debug" : undefined,
})
export const stopWorkspace = (workspaceId: string) =>
postWorkspaceBuild(workspaceId, { transition: "stop" })
export const deleteWorkspace = (workspaceId: string) =>
postWorkspaceBuild(workspaceId, { transition: "delete" })

export const cancelWorkspaceBuild = async (
workspaceBuildId: TypesGen.WorkspaceBuild["id"],
Expand Down
17 changes: 13 additions & 4 deletions site/src/components/AlertBanner/AlertBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,14 @@ export const AlertBanner: FC<React.PropsWithChildren<AlertBannerProps>> = ({
spacing={0}
justifyContent="space-between"
>
<Stack direction="row" alignItems="center" spacing={1}>
<Stack
direction="row"
alignItems="center"
spacing={2}
className={classes.fullWidth}
>
{severityConstants[severity].icon}
<Stack spacing={0}>
<Stack spacing={0} className={classes.fullWidth}>
{children}
{alertMessage}
{detail && (
Expand Down Expand Up @@ -94,11 +99,11 @@ const useStyles = makeStyles<Theme, StyleProps>((theme) => ({
borderColor: severityConstants[props.severity].color,
border: `1px solid ${colors.orange[7]}`,
borderRadius: theme.shape.borderRadius,
padding: `${theme.spacing(1)}px ${theme.spacing(2)}px`,
padding: theme.spacing(2),
backgroundColor: `${colors.gray[16]}`,
textAlign: "left",

"& span": {
"& > span": {
paddingTop: `${theme.spacing(0.25)}px`,
},

Expand All @@ -108,4 +113,8 @@ const useStyles = makeStyles<Theme, StyleProps>((theme) => ({
marginRight: `${theme.spacing(1)}px`,
},
}),

fullWidth: {
width: "100%",
},
}))
10 changes: 3 additions & 7 deletions site/src/components/AlertBanner/severityConstants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,20 @@ export const severityConstants: Record<
color: colors.orange[7],
icon: (
<ReportProblemOutlinedIcon
fontSize="small"
style={{ color: colors.orange[7] }}
style={{ color: colors.orange[7], fontSize: 16 }}
/>
),
},
error: {
color: colors.red[7],
icon: (
<ErrorOutlineOutlinedIcon
fontSize="small"
style={{ color: colors.red[7] }}
style={{ color: colors.red[7], fontSize: 16 }}
/>
),
},
info: {
color: colors.blue[7],
icon: (
<InfoOutlinedIcon fontSize="small" style={{ color: colors.blue[7] }} />
),
icon: <InfoOutlinedIcon style={{ color: colors.blue[7], fontSize: 16 }} />,
},
}
4 changes: 2 additions & 2 deletions site/src/components/Logs/Logs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ const useStyles = makeStyles<
background: theme.palette.background.default,
},
scrollWrapper: {
width: "fit-content",
minWidth: "fit-content",
},
line: {
wordBreak: "break-all",
Expand All @@ -109,7 +109,7 @@ const useStyles = makeStyles<
},

"&.debug": {
backgroundColor: theme.palette.grey[900],
backgroundColor: theme.palette.background.paperLight,
},

"&.warn": {
Expand Down
52 changes: 46 additions & 6 deletions site/src/components/Workspace/Workspace.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import Button from "@material-ui/core/Button"
import { makeStyles } from "@material-ui/core/styles"
import RefreshOutlined from "@material-ui/icons/RefreshOutlined"
import { Avatar } from "components/Avatar/Avatar"
import { AgentRow } from "components/Resources/AgentRow"
import { WorkspaceBuildLogs } from "components/WorkspaceBuildLogs/WorkspaceBuildLogs"
import {
ActiveTransition,
WorkspaceBuildProgress,
Expand Down Expand Up @@ -55,6 +58,8 @@ export interface WorkspaceProps {
applicationsHost?: string
template?: TypesGen.Template
quota_budget?: number
failedBuildLogs: TypesGen.ProvisionerJobLog[] | undefined
handleBuildRetry: () => void
}

/**
Expand All @@ -80,6 +85,8 @@ export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
applicationsHost,
template,
quota_budget,
failedBuildLogs,
handleBuildRetry,
}) => {
const styles = useStyles()
const navigate = useNavigate()
Expand Down Expand Up @@ -177,12 +184,36 @@ export const Workspace: FC<React.PropsWithChildren<WorkspaceProps>> = ({
handleUpdate={handleUpdate}
/>

{workspace.latest_build.job.error && (
<div>
<div>
The build failed. See the logs below for more information.
</div>
</div>
{failedBuildLogs && (
<Stack>
<AlertBanner severity="error">
<Stack
className={styles.fullWidth}
direction="row"
alignItems="center"
justifyContent="space-between"
>
<Stack spacing={0}>
<span>Workspace build failed</span>
<span className={styles.errorDetails}>
{workspace.latest_build.job.error}
</span>
</Stack>

<div>
<Button
onClick={handleBuildRetry}
startIcon={<RefreshOutlined />}
size="small"
variant="outlined"
>
Try again in debug mode
</Button>
</div>
</Stack>
</AlertBanner>
<WorkspaceBuildLogs logs={failedBuildLogs} />
</Stack>
)}

{transitionStats !== undefined && (
Expand Down Expand Up @@ -260,5 +291,14 @@ export const useStyles = makeStyles((theme) => {
logs: {
border: `1px solid ${theme.palette.divider}`,
},

errorDetails: {
color: theme.palette.text.secondary,
fontSize: 12,
},

fullWidth: {
width: "100%",
},
}
})
6 changes: 6 additions & 0 deletions site/src/components/WorkspaceBuildLogs/WorkspaceBuildLogs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ const useStyles = makeStyles<
padding: theme.spacing(2),
paddingLeft: theme.spacing(3),
paddingRight: theme.spacing(3),
borderTop: `1px solid ${theme.palette.divider}`,
borderBottom: `1px solid ${theme.palette.divider}`,
backgroundColor: theme.palette.background.paper,
display: "flex",
Expand All @@ -113,6 +114,7 @@ const useStyles = makeStyles<
"&:first-child": {
borderTopLeftRadius: theme.shape.borderRadius,
borderTopRightRadius: theme.shape.borderRadius,
borderTop: 0,
},

"&:last-child": {
Expand All @@ -121,6 +123,10 @@ const useStyles = makeStyles<
borderBottomLeftRadius: theme.shape.borderRadius,
borderBottomRightRadius: theme.shape.borderRadius,
},

"& + $header": {
borderTop: 0,
},
},

duration: {
Expand Down
24 changes: 23 additions & 1 deletion site/src/pages/WorkspacePage/WorkspacePage.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,34 @@
import { makeStyles } from "@material-ui/core/styles"
import { useQuery } from "@tanstack/react-query"
import { useMachine } from "@xstate/react"
import { getWorkspaceBuildLogs } from "api/api"
import { Workspace } from "api/typesGenerated"
import { AlertBanner } from "components/AlertBanner/AlertBanner"
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne"
import { Loader } from "components/Loader/Loader"
import { FC } from "react"
import { FC, useRef } from "react"
import { useParams } from "react-router-dom"
import { quotaMachine } from "xServices/quotas/quotasXService"
import { workspaceMachine } from "xServices/workspace/workspaceXService"
import { WorkspaceReadyPage } from "./WorkspaceReadyPage"

const useFailedBuildLogs = (workspace: Workspace | undefined) => {
const now = useRef(new Date())
return useQuery({
queryKey: ["logs", workspace?.latest_build.id],
queryFn: () => {
if (!workspace) {
throw new Error(
`Build log query being called before workspace is defined`,
)
}

return getWorkspaceBuildLogs(workspace.latest_build.id, now.current)
},
enabled: workspace?.latest_build.job.error !== undefined,
})
}

export const WorkspacePage: FC = () => {
const { username, workspace: workspaceName } = useParams() as {
username: string
Expand All @@ -30,6 +50,7 @@ export const WorkspacePage: FC = () => {
const [quotaState] = useMachine(quotaMachine, { context: { username } })
const { getQuotaError } = quotaState.context
const styles = useStyles()
const failedBuildLogs = useFailedBuildLogs(workspace)

return (
<ChooseOne>
Expand Down Expand Up @@ -66,6 +87,7 @@ export const WorkspacePage: FC = () => {
workspaceState={workspaceState}
quotaState={quotaState}
workspaceSend={workspaceSend}
failedBuildLogs={failedBuildLogs.data}
/>
</Cond>
<Cond>
Expand Down
5 changes: 5 additions & 0 deletions site/src/pages/WorkspacePage/WorkspaceReadyPage.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { useActor } from "@xstate/react"
import { ProvisionerJobLog } from "api/typesGenerated"
import { useDashboard } from "components/Dashboard/DashboardProvider"
import dayjs from "dayjs"
import { useFeatureVisibility } from "hooks/useFeatureVisibility"
Expand Down Expand Up @@ -31,11 +32,13 @@ interface WorkspaceReadyPageProps {
workspaceState: StateFrom<typeof workspaceMachine>
quotaState: StateFrom<typeof quotaMachine>
workspaceSend: (event: WorkspaceEvent) => void
failedBuildLogs: ProvisionerJobLog[] | undefined
}

export const WorkspaceReadyPage = ({
workspaceState,
quotaState,
failedBuildLogs,
workspaceSend,
}: WorkspaceReadyPageProps): JSX.Element => {
const [_, bannerSend] = useActor(
Expand Down Expand Up @@ -85,6 +88,7 @@ export const WorkspaceReadyPage = ({
</Helmet>

<Workspace
failedBuildLogs={failedBuildLogs}
scheduleProps={{
onDeadlineMinus: (hours: number) => {
bannerSend({
Expand Down Expand Up @@ -112,6 +116,7 @@ export const WorkspaceReadyPage = ({
handleUpdate={() => workspaceSend({ type: "UPDATE" })}
handleCancel={() => workspaceSend({ type: "CANCEL" })}
handleSettings={() => navigate("settings")}
handleBuildRetry={() => workspaceSend({ type: "RETRY_BUILD" })}
resources={workspace.latest_build.resources}
builds={builds}
canUpdateWorkspace={canUpdateWorkspace}
Expand Down
Loading