From 3671ae9bcd98d1e02ad566ca426f17d8c7bfa6e3 Mon Sep 17 00:00:00 2001 From: Julio Zynger Date: Thu, 23 Dec 2021 16:35:33 +0100 Subject: [PATCH] Add GoCD plugin Signed-off-by: Julio Zynger --- plugins/gocd/.eslintrc.js | 3 + plugins/gocd/README.md | 53 ++++ plugins/gocd/config.d.ts | 25 ++ plugins/gocd/dev/index.tsx | 19 ++ plugins/gocd/package.json | 66 +++++ plugins/gocd/src/api/gocdApi.client.ts | 33 +++ plugins/gocd/src/api/gocdApi.model.ts | 119 ++++++++ plugins/gocd/src/api/gocdApi.ts | 22 ++ .../GoCdBuildsComponent.test.tsx | 53 ++++ .../GoCdBuildsComponent.tsx | 118 ++++++++ .../components/GoCdBuildsComponent/index.ts | 20 ++ .../GoCdBuildsTable/GoCdBuildsTable.tsx | 264 ++++++++++++++++++ plugins/gocd/src/components/Select/Select.tsx | 82 ++++++ plugins/gocd/src/components/Select/index.ts | 17 ++ plugins/gocd/src/extensions.ts | 29 ++ plugins/gocd/src/index.ts | 21 ++ plugins/gocd/src/plugin.test.ts | 22 ++ plugins/gocd/src/plugin.ts | 41 +++ plugins/gocd/src/routes.ts | 20 ++ plugins/gocd/src/setupTests.ts | 17 ++ 20 files changed, 1044 insertions(+) create mode 100644 plugins/gocd/.eslintrc.js create mode 100644 plugins/gocd/README.md create mode 100644 plugins/gocd/config.d.ts create mode 100644 plugins/gocd/dev/index.tsx create mode 100644 plugins/gocd/package.json create mode 100644 plugins/gocd/src/api/gocdApi.client.ts create mode 100644 plugins/gocd/src/api/gocdApi.model.ts create mode 100644 plugins/gocd/src/api/gocdApi.ts create mode 100644 plugins/gocd/src/components/GoCdBuildsComponent/GoCdBuildsComponent.test.tsx create mode 100644 plugins/gocd/src/components/GoCdBuildsComponent/GoCdBuildsComponent.tsx create mode 100644 plugins/gocd/src/components/GoCdBuildsComponent/index.ts create mode 100644 plugins/gocd/src/components/GoCdBuildsTable/GoCdBuildsTable.tsx create mode 100644 plugins/gocd/src/components/Select/Select.tsx create mode 100644 plugins/gocd/src/components/Select/index.ts create mode 100644 plugins/gocd/src/extensions.ts create mode 100644 plugins/gocd/src/index.ts create mode 100644 plugins/gocd/src/plugin.test.ts create mode 100644 plugins/gocd/src/plugin.ts create mode 100644 plugins/gocd/src/routes.ts create mode 100644 plugins/gocd/src/setupTests.ts diff --git a/plugins/gocd/.eslintrc.js b/plugins/gocd/.eslintrc.js new file mode 100644 index 0000000000..13573efa9c --- /dev/null +++ b/plugins/gocd/.eslintrc.js @@ -0,0 +1,3 @@ +module.exports = { + extends: [require.resolve('@backstage/cli/config/eslint')], +}; diff --git a/plugins/gocd/README.md b/plugins/gocd/README.md new file mode 100644 index 0000000000..9dcf23705d --- /dev/null +++ b/plugins/gocd/README.md @@ -0,0 +1,53 @@ +# GoCD + +Welcome to the GoCD plugin! + +- View recent GoCD Builds + +## Installation + +GoCD Plugin exposes an entity tab component named `EntityGoCdContent`. You can include it in the +[`EntityPage.tsx`](https://github.com/backstage/backstage/blob/master/packages/app/src/components/catalog/EntityPage.tsx)`: + +```tsx +// At the top imports +import { EntityGoCdContent } from '@backstage/plugin-gocd'; + +// Farther down at the component declaration +const componentEntityPage = ( + + {/* Place the following section where you want the tab to appear */} + + + +``` + +Now your plugin should be visible as a tab at the top of the entity pages, +specifically for components that are of the type `component`. +However, it warns of a missing `gocd.org/pipelines` annotation. + +Add the annotation to your component [catalog-info.yaml](https://github.com/backstage/backstage/blob/master/catalog-info.yaml). You can refer to multiple GoCD pipelines by defining their names separated by commas, as shown in the highlighted example below: + +```yaml +metadata: + annotations: + gocd.org/pipelines: '[,]' +``` + +The plugin requires to configure a GoCD API proxy with a `GOCD_AUTH_TOKEN` for authentication in the [app-config.yaml](https://github.com/backstage/backstage/blob/master/app-config.yaml): + +```yaml +proxy: + '/gocd': + target: '/go/api' + allowedMethods: ['GET'] + headers: + Authorization: ${GOCD_AUTH_TOKEN} +``` + +You should also include the `gocd` section to allow for the plugin to redirect back to GoCD pipelines in your deployed instance: + +```yaml +gocd: + baseUrl: +``` diff --git a/plugins/gocd/config.d.ts b/plugins/gocd/config.d.ts new file mode 100644 index 0000000000..6f4f4f3dc3 --- /dev/null +++ b/plugins/gocd/config.d.ts @@ -0,0 +1,25 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 interface Config { + /** Configurations for the GoCD plugin */ + gocd: { + /** + * The base url of the GoCD installation. + * @visibility frontend + */ + baseUrl: string; + }; +} diff --git a/plugins/gocd/dev/index.tsx b/plugins/gocd/dev/index.tsx new file mode 100644 index 0000000000..e821173774 --- /dev/null +++ b/plugins/gocd/dev/index.tsx @@ -0,0 +1,19 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { createDevApp } from '@backstage/dev-utils'; +import { gocdPlugin } from '../src/plugin'; + +createDevApp().registerPlugin(gocdPlugin).render(); diff --git a/plugins/gocd/package.json b/plugins/gocd/package.json new file mode 100644 index 0000000000..f94dcf6790 --- /dev/null +++ b/plugins/gocd/package.json @@ -0,0 +1,66 @@ +{ + "name": "@backstage/plugin-gocd", + "description": "A Backstage plugin that integrates towards GoCD", + "version": "0.1.0", + "main": "src/index.ts", + "types": "src/index.ts", + "license": "Apache-2.0", + "private": false, + "publishConfig": { + "access": "public", + "main": "dist/index.esm.js", + "types": "dist/index.d.ts" + }, + "homepage": "https://backstage.io", + "repository": { + "type": "git", + "url": "https://github.com/backstage/backstage", + "directory": "plugins/gocd" + }, + "scripts": { + "build": "backstage-cli plugin:build", + "start": "backstage-cli plugin:serve", + "lint": "backstage-cli lint", + "test": "backstage-cli test", + "diff": "backstage-cli plugin:diff", + "prepack": "backstage-cli prepack", + "postpack": "backstage-cli postpack", + "clean": "backstage-cli clean" + }, + "dependencies": { + "@backstage/catalog-model": "^0.9.1", + "@backstage/core-components": "^0.8.0", + "@backstage/core-plugin-api": "^0.3.0", + "@backstage/plugin-catalog-react": "^0.6.0", + "@backstage/theme": "^0.2.10", + "@material-ui/core": "^4.12.2", + "@material-ui/icons": "^4.9.1", + "@material-ui/lab": "4.0.0-alpha.57", + "@types/lodash": "^4.14.173", + "@types/luxon": "^2.0.4", + "lodash": "^4.17.21", + "luxon": "^2.0.2", + "qs": "^6.10.1", + "react": "^16.13.1", + "react-dom": "^16.13.1", + "react-use": "^17.2.4" + }, + "devDependencies": { + "@backstage/cli": "^0.10.0", + "@backstage/core-app-api": "^0.2.0", + "@backstage/dev-utils": "^0.2.14", + "@backstage/test-utils": "^0.1.23", + "@testing-library/jest-dom": "^5.10.1", + "@testing-library/react": "^11.2.5", + "@testing-library/user-event": "^13.1.8", + "@types/jest": "^26.0.7", + "@types/node": "^14.14.32", + "cross-fetch": "^3.0.6", + "msw": "^0.35.0" + }, + "files": [ + "dist", + "config.d.ts" + ], + "configSchema": "config.d.ts" +} diff --git a/plugins/gocd/src/api/gocdApi.client.ts b/plugins/gocd/src/api/gocdApi.client.ts new file mode 100644 index 0000000000..3907281ff4 --- /dev/null +++ b/plugins/gocd/src/api/gocdApi.client.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { GoCdApi } from './gocdApi'; +import { GoCdApiError, PipelineHistory } from './gocdApi.model'; +import { DiscoveryApi } from '@backstage/core-plugin-api'; + +export class GoCdClientApi implements GoCdApi { + constructor(private readonly discoveryApi: DiscoveryApi) {} + + async getPipelineHistory( + pipelineName: string, + ): Promise { + const baseUrl = await this.discoveryApi.getBaseUrl('proxy'); + const pipelineHistoryResponse = await fetch( + `${baseUrl}/gocd/pipelines/${pipelineName}/history`, + ); + + return await pipelineHistoryResponse.json(); + } +} diff --git a/plugins/gocd/src/api/gocdApi.model.ts b/plugins/gocd/src/api/gocdApi.model.ts new file mode 100644 index 0000000000..8bb9a481e6 --- /dev/null +++ b/plugins/gocd/src/api/gocdApi.model.ts @@ -0,0 +1,119 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 interface GoCdApiError { + message: string; +} + +export interface PipelineHistory { + _links: Links; + pipelines: Pipeline[]; +} + +export interface Links { + next: Next; +} + +export interface Next { + href: string; +} + +export interface Pipeline { + name: string; + counter: number; + label: string; + natural_order?: number; + can_run?: boolean; + preparing_to_schedule?: boolean; + comment: string | null; + scheduled_date?: number; + build_cause?: BuildCause; + stages: Stage[]; +} + +export interface BuildCause { + trigger_message: string; + trigger_forced: boolean; + approver: string; + material_revisions: MaterialRevision[]; +} + +export interface MaterialRevision { + changed: boolean; + material: Material; + modifications: Modification[]; +} + +export interface Material { + name: string; + fingerprint: string; + type: string; + description: string; +} + +export interface Modification { + revision: string; + modified_time: number; + user_name: string; + comment: string | null; + email_address: string | null; +} + +export interface Stage { + result?: string; + status: string; + rerun_of_counter?: number | null; + name: string; + counter: string; + scheduled: boolean; + approval_type?: string | null; + approved_by?: string | null; + operate_permission?: boolean; + can_run?: boolean; + jobs: Job[]; +} + +export interface Job { + name: string; + scheduled_date?: number; + state: string; + result: string; +} + +export enum GoCdBuildResultStatus { + running, + successful, + warning, + aborted, + error, + pending, +} + +export interface GoCdBuildStageResult { + status: GoCdBuildResultStatus; + text: string; +} + +export interface GoCdBuildResult { + id: number; + source: string; + stages: GoCdBuildStageResult[]; + buildSlug: string; + message: string; + pipeline: string; + author: string | undefined; + commitHash: string; + triggerTime: number | undefined; +} diff --git a/plugins/gocd/src/api/gocdApi.ts b/plugins/gocd/src/api/gocdApi.ts new file mode 100644 index 0000000000..a9883a0c66 --- /dev/null +++ b/plugins/gocd/src/api/gocdApi.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { GoCdApiError, PipelineHistory } from './gocdApi.model'; + +export interface GoCdApi { + getPipelineHistory( + pipelineName: string, + ): Promise; +} diff --git a/plugins/gocd/src/components/GoCdBuildsComponent/GoCdBuildsComponent.test.tsx b/plugins/gocd/src/components/GoCdBuildsComponent/GoCdBuildsComponent.test.tsx new file mode 100644 index 0000000000..f35155d6ae --- /dev/null +++ b/plugins/gocd/src/components/GoCdBuildsComponent/GoCdBuildsComponent.test.tsx @@ -0,0 +1,53 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { render } from '@testing-library/react'; +import { GoCdBuildsComponent } from './GoCdBuildsComponent'; +import { GoCdApi } from '../../api/gocdApi'; + +let entityValue: { + entity: { metadata: { annotations?: { [key: string]: string } } }; +}; + +const mockApiClient: GoCdApi = { + getPipelineHistory: jest.fn(async () => ({ + _links: { next: { href: 'some-href' } }, + pipelines: [], + })), +}; + +jest.mock('@backstage/plugin-catalog-react', () => ({ + useEntity: () => { + return entityValue; + }, +})); + +jest.mock('@backstage/core-plugin-api', () => ({ + ...jest.requireActual('@backstage/core-plugin-api'), + useApi: () => mockApiClient, +})); + +describe('GoCdArtifactsComponent', () => { + entityValue = { entity: { metadata: {} } }; + + const renderComponent = () => render(); + + it('should display an empty state if an app annotation is missing', async () => { + const rendered = renderComponent(); + + expect(await rendered.findByText('Missing Annotation')).toBeInTheDocument(); + }); +}); diff --git a/plugins/gocd/src/components/GoCdBuildsComponent/GoCdBuildsComponent.tsx b/plugins/gocd/src/components/GoCdBuildsComponent/GoCdBuildsComponent.tsx new file mode 100644 index 0000000000..a12af86bfd --- /dev/null +++ b/plugins/gocd/src/components/GoCdBuildsComponent/GoCdBuildsComponent.tsx @@ -0,0 +1,118 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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, { useState } from 'react'; +import { Entity } from '@backstage/catalog-model'; +import { useEntity } from '@backstage/plugin-catalog-react'; +import { + Content, + ContentHeader, + MissingAnnotationEmptyState, + EmptyState, + Page, +} from '@backstage/core-components'; +import { useApi, configApiRef } from '@backstage/core-plugin-api'; +import { useAsync } from 'react-use'; +import { gocdApiRef } from '../../plugin'; +import { GoCdBuildsTable } from '../GoCdBuildsTable/GoCdBuildsTable'; +import { GoCdApiError, PipelineHistory } from '../../api/gocdApi.model'; +import { Item, Select } from '../Select'; + +export const GOCD_APP_ANNOTATION = 'gocd.org/pipelines'; + +export const isGoCdAvailable = (entity: Entity): boolean => + Boolean(entity.metadata.annotations?.[GOCD_APP_ANNOTATION]); + +export const GoCdBuildsComponent = (): JSX.Element => { + const { entity } = useEntity(); + const config = useApi(configApiRef); + const rawPipelines: string[] | undefined = ( + entity.metadata.annotations?.[GOCD_APP_ANNOTATION] as string | undefined + ) + ?.split(',') + .map(p => p.trim()); + const gocdApi = useApi(gocdApiRef); + + const [selectedPipeline, setSelectedPipeline] = useState( + rawPipelines ? rawPipelines[0] : '', + ); + + const { + value: pipelineHistory, + loading, + error, + } = useAsync(async (): Promise => { + return await gocdApi.getPipelineHistory(selectedPipeline); + }, [selectedPipeline]); + + const onSelectedPipelineChanged = (pipeline: string) => { + setSelectedPipeline(pipeline); + }; + + const getSelectionItems = (pipelines: string[]): Item[] => { + return pipelines.map(p => ({ label: p, value: p })); + }; + + function isError( + apiResult: PipelineHistory | GoCdApiError | undefined, + ): apiResult is GoCdApiError { + return (apiResult as GoCdApiError)?.message !== undefined; + } + + if (!rawPipelines) { + return ; + } + + if (isError(pipelineHistory)) { + return ( + + ); + } + + if (!loading && !pipelineHistory) { + return ( + + ); + } + + return ( + + + + + {renderItems(items)} + + + ); +}; diff --git a/plugins/gocd/src/components/Select/index.ts b/plugins/gocd/src/components/Select/index.ts new file mode 100644 index 0000000000..1503c54cdf --- /dev/null +++ b/plugins/gocd/src/components/Select/index.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { SelectComponent as Select } from './Select'; +export type { Item } from './Select'; diff --git a/plugins/gocd/src/extensions.ts b/plugins/gocd/src/extensions.ts new file mode 100644 index 0000000000..8b005a9c38 --- /dev/null +++ b/plugins/gocd/src/extensions.ts @@ -0,0 +1,29 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { gocdPlugin } from './plugin'; +import { createComponentExtension } from '@backstage/core-plugin-api'; + +export const EntityGoCdContent = gocdPlugin.provide( + createComponentExtension({ + name: 'EntityGoCdContent', + component: { + lazy: () => + import('./components/GoCdBuildsComponent').then( + m => m.GoCdBuildsComponent, + ), + }, + }), +); diff --git a/plugins/gocd/src/index.ts b/plugins/gocd/src/index.ts new file mode 100644 index 0000000000..97b0fb6e80 --- /dev/null +++ b/plugins/gocd/src/index.ts @@ -0,0 +1,21 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { gocdPlugin } from './plugin'; +export { EntityGoCdContent } from './extensions'; +export { + GOCD_APP_ANNOTATION, + isGoCdAvailable, +} from './components/GoCdBuildsComponent'; diff --git a/plugins/gocd/src/plugin.test.ts b/plugins/gocd/src/plugin.test.ts new file mode 100644 index 0000000000..02b52a00b6 --- /dev/null +++ b/plugins/gocd/src/plugin.test.ts @@ -0,0 +1,22 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { gocdPlugin } from './plugin'; + +describe('gocd', () => { + it('should export plugin', () => { + expect(gocdPlugin).toBeDefined(); + }); +}); diff --git a/plugins/gocd/src/plugin.ts b/plugins/gocd/src/plugin.ts new file mode 100644 index 0000000000..91d229a5ab --- /dev/null +++ b/plugins/gocd/src/plugin.ts @@ -0,0 +1,41 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { GoCdClientApi } from './api/gocdApi.client'; +import { GoCdApi } from './api/gocdApi'; +import { + discoveryApiRef, + createApiRef, + createApiFactory, + createPlugin, +} from '@backstage/core-plugin-api'; + +export const gocdApiRef = createApiRef({ + id: 'plugin.gocd.service', + description: 'Used by the GoCD plugin to retrieve information about builds.', +}); + +export const gocdPlugin = createPlugin({ + id: 'gocd', + apis: [ + createApiFactory({ + api: gocdApiRef, + deps: { discoveryApi: discoveryApiRef }, + factory: ({ discoveryApi }) => { + return new GoCdClientApi(discoveryApi); + }, + }), + ], +}); diff --git a/plugins/gocd/src/routes.ts b/plugins/gocd/src/routes.ts new file mode 100644 index 0000000000..06513e0aa7 --- /dev/null +++ b/plugins/gocd/src/routes.ts @@ -0,0 +1,20 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { createRouteRef } from '@backstage/core-plugin-api'; + +export const rootRouteRef = createRouteRef({ + title: 'gocd', +}); diff --git a/plugins/gocd/src/setupTests.ts b/plugins/gocd/src/setupTests.ts new file mode 100644 index 0000000000..fc6dbd98f8 --- /dev/null +++ b/plugins/gocd/src/setupTests.ts @@ -0,0 +1,17 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 '@testing-library/jest-dom'; +import 'cross-fetch/polyfill';