Skip to content

feat(site): display build logs history in the build log page #9150

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 6 commits into from
Aug 17, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions site/src/api/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ export function waitForBuild(build: TypesGen.WorkspaceBuild) {
const { job } = await getWorkspaceBuildByNumber(
build.workspace_owner_name,
build.workspace_name,
String(build.build_number),
build.build_number,
)
latestJobInfo = job

Expand Down Expand Up @@ -772,7 +772,7 @@ export const getWorkspaceBuilds = async (
export const getWorkspaceBuildByNumber = async (
username = "me",
workspaceName: string,
buildNumber: string,
buildNumber: number,
): Promise<TypesGen.WorkspaceBuild> => {
const response = await axios.get<TypesGen.WorkspaceBuild>(
`/api/v2/users/${username}/workspace/${workspaceName}/builds/${buildNumber}`,
Expand Down
22 changes: 22 additions & 0 deletions site/src/components/BuildIcon/BuildIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import PlayArrowOutlined from "@mui/icons-material/PlayArrowOutlined"
import StopOutlined from "@mui/icons-material/StopOutlined"
import DeleteOutlined from "@mui/icons-material/DeleteOutlined"
import { WorkspaceTransition } from "api/typesGenerated"
import { ComponentProps } from "react"

type SVGIcon = typeof PlayArrowOutlined

type SVGIconProps = ComponentProps<SVGIcon>

const iconByTransition: Record<WorkspaceTransition, SVGIcon> = {
start: PlayArrowOutlined,
stop: StopOutlined,
delete: DeleteOutlined,
}

export const BuildIcon = (
props: SVGIconProps & { transition: WorkspaceTransition },
) => {
const Icon = iconByTransition[props.transition]
return <Icon {...props} />
}
14 changes: 3 additions & 11 deletions site/src/components/BuildsTable/BuildAvatar.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
import Badge from "@mui/material/Badge"
import { useTheme, withStyles } from "@mui/styles"
import { FC } from "react"
import PlayArrowOutlined from "@mui/icons-material/PlayArrowOutlined"
import PauseOutlined from "@mui/icons-material/PauseOutlined"
import DeleteOutlined from "@mui/icons-material/DeleteOutlined"
import { WorkspaceBuild, WorkspaceTransition } from "api/typesGenerated"
import { WorkspaceBuild } from "api/typesGenerated"
import { getDisplayWorkspaceBuildStatus } from "utils/workspace"
import { Avatar, AvatarProps } from "components/Avatar/Avatar"
import { PaletteIndex } from "theme/theme"
import { Theme } from "@mui/material/styles"
import { BuildIcon } from "components/BuildIcon/BuildIcon"

interface StylesBadgeProps {
type: PaletteIndex
Expand All @@ -31,12 +29,6 @@ export interface BuildAvatarProps {
size?: AvatarProps["size"]
}

const iconByTransition: Record<WorkspaceTransition, JSX.Element> = {
start: <PlayArrowOutlined />,
stop: <PauseOutlined />,
delete: <DeleteOutlined />,
}

export const BuildAvatar: FC<BuildAvatarProps> = ({ build, size }) => {
const theme = useTheme<Theme>()
const displayBuildStatus = getDisplayWorkspaceBuildStatus(theme, build)
Expand All @@ -55,7 +47,7 @@ export const BuildAvatar: FC<BuildAvatarProps> = ({ build, size }) => {
badgeContent={<div></div>}
>
<Avatar size={size} colorScheme="darken">
{iconByTransition[build.transition]}
<BuildIcon transition={build.transition} />
</Avatar>
</StyledBadge>
)
Expand Down
44 changes: 44 additions & 0 deletions site/src/components/Sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import Box, { BoxProps } from "@mui/material/Box"
import { styled } from "@mui/styles"
import { colors } from "theme/colors"

export const Sidebar = styled((props: BoxProps) => (
<Box {...props} component="nav" />
))(({ theme }) => ({
width: theme.spacing(32),
flexShrink: 0,
borderRight: `1px solid ${theme.palette.divider}`,
height: "100%",
overflowY: "auto",
}))

export const SidebarItem = styled(
({ active, ...props }: BoxProps & { active?: boolean }) => (
<Box component="button" {...props} />
),
)(({ theme, active }) => ({
background: active ? colors.gray[13] : "none",
border: "none",
fontSize: 14,
width: "100%",
textAlign: "left",
padding: theme.spacing(0, 3),
cursor: "pointer",
pointerEvents: active ? "none" : "auto",
color: active ? theme.palette.text.primary : theme.palette.text.secondary,
"&:hover": {
background: theme.palette.action.hover,
color: theme.palette.text.primary,
},
paddingTop: theme.spacing(1.25),
paddingBottom: theme.spacing(1.25),
}))

export const SidebarCaption = styled(Box)(({ theme }) => ({
fontSize: 10,
textTransform: "uppercase",
fontWeight: 500,
color: theme.palette.text.secondary,
padding: theme.spacing(1.5, 3),
letterSpacing: "0.5px",
}))

This file was deleted.

38 changes: 0 additions & 38 deletions site/src/components/WorkspaceBuildStats/WorkspaceBuildStats.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ describe("WorkspaceBuildPage", () => {
expect(getWorkspaceBuildSpy).toBeCalledWith(
MockWorkspace.owner_name,
MockWorkspace.name,
`${MockWorkspaceBuild.build_number}`,
MockWorkspaceBuild.build_number,
),
)
})
Expand Down
30 changes: 26 additions & 4 deletions site/src/pages/WorkspaceBuildPage/WorkspaceBuildPage.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { useMachine } from "@xstate/react"
import { FC } from "react"
import { FC, useEffect } from "react"
import { Helmet } from "react-helmet-async"
import { useParams } from "react-router-dom"
import { pageTitle } from "../../utils/page"
import { workspaceBuildMachine } from "../../xServices/workspaceBuild/workspaceBuildXService"
import { WorkspaceBuildPageView } from "./WorkspaceBuildPageView"
import { useQuery } from "@tanstack/react-query"
import { getWorkspaceBuilds } from "api/api"
import dayjs from "dayjs"

export const WorkspaceBuildPage: FC = () => {
const params = useParams() as {
Expand All @@ -13,12 +16,26 @@ export const WorkspaceBuildPage: FC = () => {
buildNumber: string
}
const workspaceName = params.workspace
const buildNumber = params.buildNumber
const buildNumber = Number(params.buildNumber)
const username = params.username.replace("@", "")
const [buildState] = useMachine(workspaceBuildMachine, {
const [buildState, send] = useMachine(workspaceBuildMachine, {
context: { username, workspaceName, buildNumber, timeCursor: new Date() },
})
const { logs, build } = buildState.context
const { data: builds } = useQuery({
queryKey: ["builds", username, build?.workspace_id],
queryFn: () => {
return getWorkspaceBuilds(
build?.workspace_id ?? "",
dayjs().add(-30, "day").toDate(),
)
},
enabled: Boolean(build),
})

useEffect(() => {
send("RESET", { buildNumber, timeCursor: new Date() })
}, [buildNumber, send])

return (
<>
Expand All @@ -32,7 +49,12 @@ export const WorkspaceBuildPage: FC = () => {
</title>
</Helmet>

<WorkspaceBuildPageView logs={logs} build={build} />
<WorkspaceBuildPageView
logs={logs}
build={build}
builds={builds}
activeBuildNumber={buildNumber}
/>
</>
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,31 +1,48 @@
import { ComponentMeta, Story } from "@storybook/react"
import { Meta, StoryObj } from "@storybook/react"
import {
MockFailedWorkspaceBuild,
MockWorkspaceBuild,
MockWorkspaceBuildLogs,
} from "../../testHelpers/entities"
import {
WorkspaceBuildPageView,
WorkspaceBuildPageViewProps,
} from "./WorkspaceBuildPageView"
import { WorkspaceBuildPageView } from "./WorkspaceBuildPageView"

const defaultBuilds = [...Array(15).keys()].map((i) => ({
...MockWorkspaceBuild,
id: `${i}`,
build_number: i,
}))

export default {
title: "pages/WorkspaceBuildPageView",
const meta: Meta<typeof WorkspaceBuildPageView> = {
title: "components/WorkspaceBuildPageView",
component: WorkspaceBuildPageView,
} as ComponentMeta<typeof WorkspaceBuildPageView>
args: {
build: MockWorkspaceBuild,
logs: MockWorkspaceBuildLogs,
builds: defaultBuilds,
activeBuildNumber: defaultBuilds[0].build_number,
},
}

const Template: Story<WorkspaceBuildPageViewProps> = (args) => (
<WorkspaceBuildPageView {...args} />
)
export default meta
type Story = StoryObj<typeof WorkspaceBuildPageView>

export const Loaded: Story = {}

export const LoadingBuildLogs: Story = {
args: {
builds: undefined,
},
}

export const Example = Template.bind({})
Example.args = {
build: MockWorkspaceBuild,
logs: MockWorkspaceBuildLogs,
const failedBuild = {
...MockFailedWorkspaceBuild("delete"),
build_number: new Date().getDate(),
}

export const FailedDelete = Template.bind({})
FailedDelete.args = {
build: MockFailedWorkspaceBuild("delete"),
logs: MockWorkspaceBuildLogs,
export const FailedDelete: Story = {
args: {
build: failedBuild,
builds: [failedBuild, ...defaultBuilds],
activeBuildNumber: failedBuild.build_number,
},
}
Loading