Merge pull request #5191 from anderoo/anderoo/cuatom-columns-on-deployments-plugin

Custom columns for GithubDeploymentsPlugin
This commit is contained in:
Fredrik Adelöw
2021-04-16 15:17:11 +02:00
committed by GitHub
10 changed files with 236 additions and 65 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-github-deployments': patch
---
Adds extraColumns field to GitHub Deployments card
@@ -24,6 +24,10 @@ export type GithubDeployment = {
abbreviatedOid: string;
commitUrl: string;
};
creator: {
login: string;
};
payload: string;
};
export interface GithubDeploymentsApi {
@@ -55,6 +59,10 @@ query deployments($owner: String!, $repo: String!, $last: Int) {
abbreviatedOid
commitUrl
}
creator {
login
}
payload
}
}
}
@@ -26,7 +26,11 @@ import {
import { fireEvent } from '@testing-library/react';
import { msw, renderInTestApp } from '@backstage/test-utils';
import { GithubDeploymentsApiClient, githubDeploymentsApiRef } from '../api';
import {
GithubDeployment,
GithubDeploymentsApiClient,
githubDeploymentsApiRef,
} from '../api';
import { githubDeploymentsPlugin } from '../plugin';
import { GithubDeploymentsCard } from './GithubDeploymentsCard';
@@ -39,6 +43,8 @@ import {
import { setupServer } from 'msw/node';
import { graphql } from 'msw';
import { GithubDeploymentsTable } from './GithubDeploymentsTable';
import { Box } from '@material-ui/core';
jest.mock('@backstage/plugin-catalog-react', () => ({
useEntity: () => {
@@ -159,5 +165,39 @@ describe('github-deployments', () => {
).toBeInTheDocument();
expect(await rendered.findByText('failure')).toBeInTheDocument();
});
it('should display extra columns', async () => {
worker.use(
graphql.query('deployments', (_, res, ctx) =>
res(ctx.data(responseStub)),
),
);
const renderTargetFromPayload = (payload: string) => {
const parsedPayload = JSON.parse(payload);
return parsedPayload?.target || 'unknown';
};
const extraColumn = {
title: 'Target',
render: (row: GithubDeployment): JSX.Element => (
<Box>{renderTargetFromPayload(row.payload)}</Box>
),
};
const columns = [
...GithubDeploymentsTable.defaultDeploymentColumns,
extraColumn,
];
const rendered = await renderInTestApp(
<ApiProvider apis={apis}>
<GithubDeploymentsCard columns={columns} />
</ApiProvider>,
);
expect(await rendered.findByText('moon')).toBeInTheDocument();
expect(await rendered.findByText('sun')).toBeInTheDocument();
});
});
});
@@ -17,23 +17,26 @@ import React from 'react';
import {
MissingAnnotationEmptyState,
ResponseErrorPanel,
TableColumn,
useApi,
} from '@backstage/core';
import { useAsyncRetry } from 'react-use';
import { githubDeploymentsApiRef } from '../api';
import { GithubDeployment, githubDeploymentsApiRef } from '../api';
import { useEntity } from '@backstage/plugin-catalog-react';
import {
GITHUB_PROJECT_SLUG_ANNOTATION,
isGithubDeploymentsAvailable,
} from '../Router';
import GithubDeploymentsTable from './GithubDeploymentsTable/GithubDeploymentsTable';
import { GithubDeploymentsTable } from './GithubDeploymentsTable/GithubDeploymentsTable';
const GithubDeploymentsComponent = ({
projectSlug,
last,
columns,
}: {
projectSlug: string;
last: number;
columns: TableColumn<GithubDeployment>[];
}) => {
const api = useApi(githubDeploymentsApiRef);
const [owner, repo] = projectSlug.split('/');
@@ -51,11 +54,18 @@ const GithubDeploymentsComponent = ({
deployments={value || []}
isLoading={loading}
reload={reload}
columns={columns}
/>
);
};
export const GithubDeploymentsCard = ({ last }: { last?: number }) => {
export const GithubDeploymentsCard = ({
last,
columns,
}: {
last?: number;
columns?: TableColumn<GithubDeployment>[];
}) => {
const { entity } = useEntity();
return !isGithubDeploymentsAvailable(entity) ? (
@@ -66,6 +76,7 @@ export const GithubDeploymentsCard = ({ last }: { last?: number }) => {
entity?.metadata.annotations?.[GITHUB_PROJECT_SLUG_ANNOTATION] || ''
}
last={last || 10}
columns={columns || GithubDeploymentsTable.defaultDeploymentColumns}
/>
);
};
@@ -14,19 +14,12 @@
* limitations under the License.
*/
import React from 'react';
import {
StatusPending,
StatusRunning,
StatusOK,
Table,
TableColumn,
StatusAborted,
StatusError,
} from '@backstage/core';
import { Table, TableColumn } from '@backstage/core';
import { GithubDeployment } from '../../api';
import { DateTime } from 'luxon';
import { Box, Typography, Link, makeStyles } from '@material-ui/core';
import { Typography, makeStyles } from '@material-ui/core';
import SyncIcon from '@material-ui/icons/Sync';
import * as columnFactories from './columns';
import { defaultDeploymentColumns } from './presets';
const useStyles = makeStyles(theme => ({
empty: {
@@ -36,63 +29,19 @@ const useStyles = makeStyles(theme => ({
},
}));
const statusIndicator = (value: string): React.ReactNode => {
switch (value) {
case 'PENDING':
return <StatusPending />;
case 'IN_PROGRESS':
return <StatusRunning />;
case 'ACTIVE':
return <StatusOK />;
case 'ERROR':
case 'FAILURE':
return <StatusError />;
default:
return <StatusAborted />;
}
};
const columns: TableColumn<GithubDeployment>[] = [
{
title: 'Environment',
field: 'environment',
highlight: true,
},
{
title: 'Status',
render: (row: GithubDeployment): React.ReactNode => (
<Box display="flex" alignItems="center">
{statusIndicator(row.state)}
<Typography variant="caption">{row.state}</Typography>
</Box>
),
},
{
title: 'Commit',
render: (row: GithubDeployment): React.ReactNode => (
<Link href={row.commit.commitUrl} target="_blank" rel="noopener">
{row.commit.abbreviatedOid}
</Link>
),
},
{
title: 'Last Updated',
render: (row: GithubDeployment): React.ReactNode =>
DateTime.fromISO(row.updatedAt).toRelative({ locale: 'en' }),
},
];
type GithubDeploymentsTableProps = {
deployments: GithubDeployment[];
isLoading: boolean;
reload: () => void;
columns: TableColumn<GithubDeployment>[];
};
const GithubDeploymentsTable = ({
export function GithubDeploymentsTable({
deployments,
isLoading,
reload,
}: GithubDeploymentsTableProps) => {
columns,
}: GithubDeploymentsTableProps) {
const classes = useStyles();
return (
@@ -119,6 +68,8 @@ const GithubDeploymentsTable = ({
}
/>
);
};
}
export default GithubDeploymentsTable;
GithubDeploymentsTable.columns = columnFactories;
GithubDeploymentsTable.defaultDeploymentColumns = defaultDeploymentColumns;
@@ -0,0 +1,91 @@
/*
* Copyright 2021 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
import {
StatusPending,
StatusRunning,
StatusOK,
TableColumn,
StatusAborted,
StatusError,
Link,
} from '@backstage/core';
import { GithubDeployment } from '../../api';
import { DateTime } from 'luxon';
import { Box, Typography } from '@material-ui/core';
export const GithubStateIndicator = ({ state }: { state: string }) => {
switch (state) {
case 'PENDING':
return <StatusPending />;
case 'IN_PROGRESS':
return <StatusRunning />;
case 'ACTIVE':
return <StatusOK />;
case 'ERROR':
case 'FAILURE':
return <StatusError />;
default:
return <StatusAborted />;
}
};
export function createEnvironmentColumn(): TableColumn<GithubDeployment> {
return {
title: 'Environment',
field: 'environment',
highlight: true,
};
}
export function createStatusColumn(): TableColumn<GithubDeployment> {
return {
title: 'Status',
render: (row: GithubDeployment): JSX.Element => (
<Box display="flex" alignItems="center">
<GithubStateIndicator state={row.state} />
<Typography variant="caption">{row.state}</Typography>
</Box>
),
};
}
export function createCommitColumn(): TableColumn<GithubDeployment> {
return {
title: 'Commit',
render: (row: GithubDeployment): JSX.Element => (
<Link to={row.commit.commitUrl} target="_blank" rel="noopener">
{row.commit.abbreviatedOid}
</Link>
),
};
}
export function createCreatorColumn(): TableColumn<GithubDeployment> {
return {
title: 'Creator',
field: 'creator.login',
};
}
export function createLastUpdatedColumn(): TableColumn<GithubDeployment> {
return {
title: 'Last Updated',
render: (row: GithubDeployment): JSX.Element => (
<Box>{DateTime.fromISO(row.updatedAt).toRelative({ locale: 'en' })}</Box>
),
};
}
@@ -0,0 +1,16 @@
/*
* Copyright 2021 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export { GithubDeploymentsTable } from './GithubDeploymentsTable';
@@ -0,0 +1,32 @@
/*
* Copyright 2021 Spotify AB
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { TableColumn } from '@backstage/core';
import { GithubDeployment } from '../../api';
import {
createEnvironmentColumn,
createStatusColumn,
createCommitColumn,
createLastUpdatedColumn,
createCreatorColumn,
} from './columns';
export const defaultDeploymentColumns: TableColumn<GithubDeployment>[] = [
createEnvironmentColumn(),
createStatusColumn(),
createCommitColumn(),
createCreatorColumn(),
createLastUpdatedColumn(),
];
+1
View File
@@ -14,4 +14,5 @@
* limitations under the License.
*/
export { githubDeploymentsPlugin, EntityGithubDeploymentsCard } from './plugin';
export { GithubDeploymentsTable } from './components/GithubDeploymentsTable';
export { isGithubDeploymentsAvailable } from './Router';
@@ -49,6 +49,10 @@ export const responseStub: QueryResponse = {
commitUrl: 'https://exampleapi.com/123456789',
abbreviatedOid: '12345',
},
creator: {
login: 'robot-user-001',
},
payload: '{"target":"moon"}',
},
{
state: 'pending',
@@ -58,6 +62,10 @@ export const responseStub: QueryResponse = {
commitUrl: 'https://exampleapi.com/543212345',
abbreviatedOid: '54321',
},
creator: {
login: 'robot-user-002',
},
payload: '{"target":"sun"}',
},
],
},
@@ -76,6 +84,10 @@ export const refreshedResponseStub: QueryResponse = {
commitUrl: 'https://exampleapi.com/123456789',
abbreviatedOid: '12345',
},
creator: {
login: 'robot-user-001',
},
payload: '',
},
{
state: 'failure',
@@ -85,6 +97,10 @@ export const refreshedResponseStub: QueryResponse = {
commitUrl: 'https://exampleapi.com/543212345',
abbreviatedOid: '54321',
},
creator: {
login: 'robot-user-002',
},
payload: '',
},
],
},