diff --git a/.changeset/dry-elephants-doubt.md b/.changeset/dry-elephants-doubt.md new file mode 100644 index 0000000000..7a9ccc9892 --- /dev/null +++ b/.changeset/dry-elephants-doubt.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-github-deployments': patch +--- + +Adds extraColumns field to GitHub Deployments card diff --git a/plugins/github-deployments/src/api/index.ts b/plugins/github-deployments/src/api/index.ts index ca69ac3853..7496370bc9 100644 --- a/plugins/github-deployments/src/api/index.ts +++ b/plugins/github-deployments/src/api/index.ts @@ -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 } } } diff --git a/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx b/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx index e20183f1d6..f128e6274b 100644 --- a/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx +++ b/plugins/github-deployments/src/components/GithubDeploymentsCard.test.tsx @@ -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 => ( + {renderTargetFromPayload(row.payload)} + ), + }; + + const columns = [ + ...GithubDeploymentsTable.defaultDeploymentColumns, + extraColumn, + ]; + + const rendered = await renderInTestApp( + + + , + ); + + expect(await rendered.findByText('moon')).toBeInTheDocument(); + expect(await rendered.findByText('sun')).toBeInTheDocument(); + }); }); }); diff --git a/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx b/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx index 99dfba560a..073f78af2e 100644 --- a/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx +++ b/plugins/github-deployments/src/components/GithubDeploymentsCard.tsx @@ -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[]; }) => { 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[]; +}) => { 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} /> ); }; diff --git a/plugins/github-deployments/src/components/GithubDeploymentsTable/GithubDeploymentsTable.tsx b/plugins/github-deployments/src/components/GithubDeploymentsTable/GithubDeploymentsTable.tsx index 91f91b919e..e13b8aeb18 100644 --- a/plugins/github-deployments/src/components/GithubDeploymentsTable/GithubDeploymentsTable.tsx +++ b/plugins/github-deployments/src/components/GithubDeploymentsTable/GithubDeploymentsTable.tsx @@ -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 ; - case 'IN_PROGRESS': - return ; - case 'ACTIVE': - return ; - case 'ERROR': - case 'FAILURE': - return ; - default: - return ; - } -}; - -const columns: TableColumn[] = [ - { - title: 'Environment', - field: 'environment', - highlight: true, - }, - { - title: 'Status', - render: (row: GithubDeployment): React.ReactNode => ( - - {statusIndicator(row.state)} - {row.state} - - ), - }, - { - title: 'Commit', - render: (row: GithubDeployment): React.ReactNode => ( - - {row.commit.abbreviatedOid} - - ), - }, - { - 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[]; }; -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; diff --git a/plugins/github-deployments/src/components/GithubDeploymentsTable/columns.tsx b/plugins/github-deployments/src/components/GithubDeploymentsTable/columns.tsx new file mode 100644 index 0000000000..f050af836c --- /dev/null +++ b/plugins/github-deployments/src/components/GithubDeploymentsTable/columns.tsx @@ -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 ; + case 'IN_PROGRESS': + return ; + case 'ACTIVE': + return ; + case 'ERROR': + case 'FAILURE': + return ; + default: + return ; + } +}; + +export function createEnvironmentColumn(): TableColumn { + return { + title: 'Environment', + field: 'environment', + highlight: true, + }; +} + +export function createStatusColumn(): TableColumn { + return { + title: 'Status', + render: (row: GithubDeployment): JSX.Element => ( + + + {row.state} + + ), + }; +} + +export function createCommitColumn(): TableColumn { + return { + title: 'Commit', + render: (row: GithubDeployment): JSX.Element => ( + + {row.commit.abbreviatedOid} + + ), + }; +} + +export function createCreatorColumn(): TableColumn { + return { + title: 'Creator', + field: 'creator.login', + }; +} + +export function createLastUpdatedColumn(): TableColumn { + return { + title: 'Last Updated', + render: (row: GithubDeployment): JSX.Element => ( + {DateTime.fromISO(row.updatedAt).toRelative({ locale: 'en' })} + ), + }; +} diff --git a/plugins/github-deployments/src/components/GithubDeploymentsTable/index.ts b/plugins/github-deployments/src/components/GithubDeploymentsTable/index.ts new file mode 100644 index 0000000000..e622d559cb --- /dev/null +++ b/plugins/github-deployments/src/components/GithubDeploymentsTable/index.ts @@ -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'; diff --git a/plugins/github-deployments/src/components/GithubDeploymentsTable/presets.ts b/plugins/github-deployments/src/components/GithubDeploymentsTable/presets.ts new file mode 100644 index 0000000000..b50e11dcb6 --- /dev/null +++ b/plugins/github-deployments/src/components/GithubDeploymentsTable/presets.ts @@ -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[] = [ + createEnvironmentColumn(), + createStatusColumn(), + createCommitColumn(), + createCreatorColumn(), + createLastUpdatedColumn(), +]; diff --git a/plugins/github-deployments/src/index.ts b/plugins/github-deployments/src/index.ts index 2ee681332a..06eed2a2a2 100644 --- a/plugins/github-deployments/src/index.ts +++ b/plugins/github-deployments/src/index.ts @@ -14,4 +14,5 @@ * limitations under the License. */ export { githubDeploymentsPlugin, EntityGithubDeploymentsCard } from './plugin'; +export { GithubDeploymentsTable } from './components/GithubDeploymentsTable'; export { isGithubDeploymentsAvailable } from './Router'; diff --git a/plugins/github-deployments/src/mocks/mocks.ts b/plugins/github-deployments/src/mocks/mocks.ts index f636a08558..c0afb325db 100644 --- a/plugins/github-deployments/src/mocks/mocks.ts +++ b/plugins/github-deployments/src/mocks/mocks.ts @@ -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: '', }, ], },