Skip to content

Commit

Permalink
feat: improve circleci builds table
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewthauer committed Nov 23, 2020
1 parent eeda19c commit a8de7f5
Show file tree
Hide file tree
Showing 10 changed files with 263 additions and 28 deletions.
6 changes: 6 additions & 0 deletions .changeset/mighty-cycles-impress.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'example-app': patch
'@backstage/plugin-circleci': patch
---

Improved CircleCI builds table to show more information and relevant links
4 changes: 2 additions & 2 deletions packages/app/src/components/catalog/EntityPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,10 @@ export const CICDSwitcher = ({ entity }: { entity: Entity }) => {
return <JenkinsRouter entity={entity} />;
case isBuildkiteAvailable(entity):
return <BuildkiteRouter entity={entity} />;
case isGitHubActionsAvailable(entity):
return <GitHubActionsRouter entity={entity} />;
case isCircleCIAvailable(entity):
return <CircleCIRouter entity={entity} />;
case isGitHubActionsAvailable(entity):
return <GitHubActionsRouter entity={entity} />;
case isCloudbuildAvailable(entity):
return <CloudbuildRouter entity={entity} />;
case isTravisCIAvailable(entity):
Expand Down
2 changes: 2 additions & 0 deletions plugins/circleci/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "4.0.0-alpha.45",
"circleci-api": "^4.0.0",
"dayjs": "^1.9.4",
"lodash": "^4.17.15",
"moment": "^2.25.3",
"react": "^16.13.1",
"react-dom": "^16.13.1",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { FC, useEffect } from 'react';

import React, { useEffect } from 'react';
import { useParams } from 'react-router-dom';
import { InfoCard, Progress, Link } from '@backstage/core';
import { BuildWithSteps, BuildStepAction } from '../../api';
Expand All @@ -31,14 +32,16 @@ import LaunchIcon from '@material-ui/icons/Launch';
import { useBuildWithSteps } from '../../state/useBuildWithSteps';

const IconLink = (IconButton as any) as typeof MaterialLink;
const BuildName: FC<{ build?: BuildWithSteps }> = ({ build }) => (

const BuildName = ({ build }: { build?: BuildWithSteps }) => (
<Box display="flex" alignItems="center">
#{build?.build_num} - {build?.subject}
<IconLink href={build?.build_url} target="_blank">
<LaunchIcon />
</IconLink>
</Box>
);

const useStyles = makeStyles(theme => ({
neutral: {},
failed: {
Expand Down Expand Up @@ -96,7 +99,7 @@ const pickClassName = (
return classes.neutral;
};

const BuildsList: FC<{ build?: BuildWithSteps }> = ({ build }) => (
const BuildsList = ({ build }: { build?: BuildWithSteps }) => (
<Box>
{build &&
build.steps &&
Expand All @@ -108,8 +111,11 @@ const BuildsList: FC<{ build?: BuildWithSteps }> = ({ build }) => (
</Box>
);

const ActionsList: FC<{ actions: BuildStepAction[]; name: string }> = ({
const ActionsList = ({
actions,
}: {
actions: BuildStepAction[];
name: string;
}) => {
const classes = useStyles();
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { FC } from 'react';
import React from 'react';
import { CITable } from '../CITable';
import { useBuilds } from '../../../../state';

export const Builds: FC<{}> = () => {
export const Builds = () => {
const [
{ total, loading, value, projectName, page, pageSize },
{ setPage, retry, setPageSize },
Expand Down
128 changes: 116 additions & 12 deletions plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,19 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { FC } from 'react';
import { Link, Typography, Box, IconButton } from '@material-ui/core';

import React from 'react';
import {
Avatar,
Link,
Typography,
Box,
IconButton,
makeStyles,
} from '@material-ui/core';
import RetryIcon from '@material-ui/icons/Replay';
import GitHubIcon from '@material-ui/icons/GitHub';
import LaunchIcon from '@material-ui/icons/Launch';
import { Link as RouterLink, generatePath } from 'react-router-dom';
import {
StatusError,
Expand All @@ -27,17 +36,22 @@ import {
Table,
TableColumn,
} from '@backstage/core';
import { durationHumanized, relativeTimeTo } from '../../../../util';
import { circleCIBuildRouteRef } from '../../../../route-refs';

export type CITableBuildInfo = {
id: string;
buildName: string;
buildUrl?: string;
startTime?: string;
stopTime?: string;
source: {
branchName: string;
commit: {
hash: string;
shortHash: string;
url: string;
committerName?: string;
};
};
status: string;
Expand All @@ -48,6 +62,18 @@ export type CITableBuildInfo = {
failed: number;
testUrl: string; // fixme better name
};
workflow: {
id: string;
url: string;
name?: string;
jobName?: string;
};
user: {
isUser: boolean;
login: string;
name?: string;
avatarUrl?: string;
};
onRestartClick: () => void;
};

Expand All @@ -69,6 +95,43 @@ const getStatusComponent = (status: string | undefined = '') => {
}
};

const useStyles = makeStyles(theme => ({
root: {
display: 'flex',
'& > *': {
margin: theme.spacing(1),
verticalAlign: 'center',
},
},
small: {
width: theme.spacing(3),
height: theme.spacing(3),
},
}));

const SourceInfo = ({ build }: { build: CITableBuildInfo }) => {
const classes = useStyles();
const { user, source } = build;

return (
<Box display="flex" alignItems="center" className={classes.root}>
<Avatar alt={user.name} src={user.avatarUrl} className={classes.small} />
<Box>
<Typography variant="button">{source?.branchName}</Typography>
<Typography variant="body1">
{source?.commit?.url !== undefined ? (
<Link href={source?.commit?.url} target="_blank">
{source?.commit.shortHash}
</Link>
) : (
source?.commit.shortHash
)}
</Typography>
</Box>
</Box>
);
};

const generatedColumns: TableColumn[] = [
{
title: 'ID',
Expand All @@ -80,26 +143,43 @@ const generatedColumns: TableColumn[] = [
title: 'Build',
field: 'buildName',
highlight: true,
width: '20%',
render: (row: Partial<CITableBuildInfo>) => (
<Link
component={RouterLink}
to={`${generatePath(circleCIBuildRouteRef.path, { buildId: row.id! })}`}
to={`${generatePath(circleCIBuildRouteRef.path, {
buildId: row.id!,
})}`}
>
{row.buildName}
{row.buildName ? row.buildName : row?.workflow?.name}
</Link>
),
},
{
title: 'Job',
field: 'buildName',
highlight: true,
render: (row: Partial<CITableBuildInfo>) => (
<Link href={row?.buildUrl} target="_blank">
<Box display="flex" alignItems="center">
<LaunchIcon fontSize="small" color="disabled" />
<Box mr={1} />
{row?.workflow?.jobName}
</Box>
</Link>
),
},
{
title: 'Source',
field: 'source.commit.hash',
highlight: true,
render: (row: Partial<CITableBuildInfo>) => (
<>
<p>{row.source?.branchName}</p>
<p>{row.source?.commit.hash}</p>
</>
<SourceInfo build={row as any} />
),
},
{
title: 'Status',
field: 'status',
render: (row: Partial<CITableBuildInfo>) => (
<Box display="flex" alignItems="center">
{getStatusComponent(row.status)}
Expand All @@ -108,14 +188,32 @@ const generatedColumns: TableColumn[] = [
</Box>
),
},
{
title: 'Time',
field: 'startTime',
render: (row: Partial<CITableBuildInfo>) => (
<>
<Typography variant="body2">
run {relativeTimeTo(row?.startTime)}
</Typography>
<Typography variant="body2">
took {durationHumanized(row?.startTime, row?.stopTime)}
</Typography>
</>
),
},
{
title: 'Workflow',
field: 'workflow.name',
},
{
title: 'Actions',
width: '10%',
render: (row: Partial<CITableBuildInfo>) => (
<IconButton onClick={row.onRestartClick}>
<RetryIcon />
</IconButton>
),
width: '10%',
},
];

Expand All @@ -130,7 +228,8 @@ type Props = {
pageSize: number;
onChangePageSize: (pageSize: number) => void;
};
export const CITable: FC<Props> = ({

export const CITable = ({
projectName,
loading,
pageSize,
Expand All @@ -140,11 +239,16 @@ export const CITable: FC<Props> = ({
onChangePage,
onChangePageSize,
total,
}) => {
}: Props) => {
return (
<Table
isLoading={loading}
options={{ paging: true, pageSize }}
options={{
paging: true,
pageSize,
padding: 'dense',
pageSizeOptions: [10, 20, 50],
}}
totalCount={total}
page={page}
actions={[
Expand Down

0 comments on commit a8de7f5

Please sign in to comment.