Adding Azure DevOps frontend plugin
Signed-off-by: Andre Wanlin <awanlin@rapidrtc.com>
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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 { RepoBuild } from './types';
|
||||
import { createApiRef } from '@backstage/core-plugin-api';
|
||||
|
||||
export const azureDevOpsApiRef = createApiRef<AzureDevOpsApi>({
|
||||
id: 'plugin.azure-devops.service',
|
||||
description:
|
||||
'Used by the Azure DevOps plugin to make requests to accompanying backend',
|
||||
});
|
||||
|
||||
export interface AzureDevOpsApi {
|
||||
getRepoBuilds(
|
||||
projectName: string,
|
||||
repoName: string,
|
||||
top: number,
|
||||
): Promise<RepoBuild[]>;
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 { AzureDevOpsApi } from './AzureDevOpsApi';
|
||||
import { RepoBuild } from './types';
|
||||
import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api';
|
||||
|
||||
export class AzureDevOpsClient implements AzureDevOpsApi {
|
||||
private readonly discoveryApi: DiscoveryApi;
|
||||
private readonly identityApi: IdentityApi;
|
||||
|
||||
constructor(options: {
|
||||
discoveryApi: DiscoveryApi;
|
||||
identityApi: IdentityApi;
|
||||
}) {
|
||||
this.discoveryApi = options.discoveryApi;
|
||||
this.identityApi = options.identityApi;
|
||||
}
|
||||
|
||||
async getRepoBuilds(
|
||||
projectName: string,
|
||||
repoName: string,
|
||||
top: number,
|
||||
): Promise<RepoBuild[]> {
|
||||
return await this.get(`/repo-builds/${projectName}/${repoName}?top=${top}`);
|
||||
}
|
||||
|
||||
private async get(path: string): Promise<any> {
|
||||
const url = `${await this.discoveryApi.getBaseUrl('azure-devops')}${path}`;
|
||||
const idToken = await this.identityApi.getIdToken();
|
||||
const response = await fetch(url, {
|
||||
headers: idToken ? { Authorization: `Bearer ${idToken}` } : {},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const payload = await response.text();
|
||||
const message = `Request failed with ${response.status} ${response.statusText}, ${payload}`;
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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 * from './AzureDevOpsApi';
|
||||
export * from './AzureDevOpsClient';
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 {
|
||||
BuildResult,
|
||||
BuildStatus,
|
||||
} from 'azure-devops-node-api/interfaces/BuildInterfaces';
|
||||
|
||||
export type RepoBuild = {
|
||||
id?: number;
|
||||
title: string;
|
||||
link: string;
|
||||
status?: BuildStatus;
|
||||
result?: BuildResult;
|
||||
queueTime?: Date;
|
||||
source: string;
|
||||
};
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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 moment from 'moment';
|
||||
import {
|
||||
Table,
|
||||
TableColumn,
|
||||
StatusError,
|
||||
StatusOK,
|
||||
StatusWarning,
|
||||
StatusAborted,
|
||||
} from '@backstage/core-components';
|
||||
import { Link, Box, Typography } from '@material-ui/core';
|
||||
import Alert from '@material-ui/lab/Alert';
|
||||
import { RepoBuild } from '../../api/types';
|
||||
import {
|
||||
BuildResult,
|
||||
BuildStatus,
|
||||
} from 'azure-devops-node-api/interfaces/BuildInterfaces';
|
||||
|
||||
const getBuildResultComponent = (result: number | undefined = 0) => {
|
||||
switch (result) {
|
||||
case 0: // None
|
||||
return <StatusError />;
|
||||
case 2: // Succeeded
|
||||
return <StatusOK />;
|
||||
case 4: // PartiallySucceeded
|
||||
return <StatusWarning />;
|
||||
case 8: // Failed
|
||||
return <StatusError />;
|
||||
case 32: // Canceled
|
||||
return <StatusAborted />;
|
||||
default:
|
||||
return <StatusWarning />;
|
||||
}
|
||||
};
|
||||
|
||||
const columns: TableColumn[] = [
|
||||
{
|
||||
title: 'ID',
|
||||
field: 'id',
|
||||
highlight: false,
|
||||
width: '80px',
|
||||
},
|
||||
{
|
||||
title: 'Build',
|
||||
field: 'title',
|
||||
render: (row: Partial<RepoBuild>) => (
|
||||
<Link href={row.link} target="_blank">
|
||||
{row.title}
|
||||
</Link>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Source',
|
||||
field: 'source',
|
||||
},
|
||||
{
|
||||
title: 'Status',
|
||||
field: 'status',
|
||||
render: (row: Partial<RepoBuild>) => (
|
||||
<Box display="flex" alignItems="center">
|
||||
<Box mr={1} />
|
||||
<Typography variant="button">{BuildStatus[row.status || 0]}</Typography>
|
||||
</Box>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Result',
|
||||
field: 'result',
|
||||
render: (row: Partial<RepoBuild>) => (
|
||||
<Box display="flex" alignItems="center">
|
||||
{getBuildResultComponent(row.result)}
|
||||
<Box mr={1} />
|
||||
<Typography variant="button">{BuildResult[row.result || 0]}</Typography>
|
||||
</Box>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: 'Date',
|
||||
field: 'queueTime',
|
||||
render: (row: Partial<RepoBuild>) => moment(row.queueTime).fromNow(),
|
||||
},
|
||||
];
|
||||
|
||||
type Props = {
|
||||
items: RepoBuild[];
|
||||
loading: boolean;
|
||||
error?: any;
|
||||
};
|
||||
|
||||
export const BuildTable = ({ items, loading, error }: Props) => {
|
||||
if (error) {
|
||||
return (
|
||||
<div>
|
||||
<Alert severity="error">
|
||||
Error encountered while fetching Azure DevOps builds.{' '}
|
||||
{error.toString()}
|
||||
</Alert>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Table
|
||||
isLoading={loading}
|
||||
columns={columns}
|
||||
options={{
|
||||
search: true,
|
||||
paging: true,
|
||||
pageSize: 5,
|
||||
showEmptyDataSourceMessage: !loading,
|
||||
}}
|
||||
title={`Builds (${(items && items.length) || 0})`}
|
||||
data={items}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -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 { BuildTable } from './BuildTable';
|
||||
@@ -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 { Entity } from '@backstage/catalog-model';
|
||||
import { useEntity } from '@backstage/plugin-catalog-react';
|
||||
import React from 'react';
|
||||
import { useRepoBuilds } from '../../hooks/useRepoBuilds';
|
||||
import { BuildTable } from '../BuildTable/BuildTable';
|
||||
|
||||
type Props = {
|
||||
/** @deprecated The entity is now grabbed from context instead */
|
||||
entity?: Entity;
|
||||
};
|
||||
|
||||
export const EntityPageAzureDevOps = (_props: Props) => {
|
||||
const { entity } = useEntity();
|
||||
const { items, loading, error } = useRepoBuilds(entity);
|
||||
|
||||
return <BuildTable items={items || []} loading={loading} error={error} />;
|
||||
};
|
||||
@@ -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 { EntityPageAzureDevOps } from './EntityPageAzureDevOps';
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 { Routes, Route } from 'react-router';
|
||||
import { azureDevOpsRouteRef } from '../routes';
|
||||
import { EntityPageAzureDevOps } from './EntityPageAzureDevOps';
|
||||
import { AZURE_DEVOPS_ANNOTATION } from '../constants';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { useEntity } from '@backstage/plugin-catalog-react';
|
||||
import { MissingAnnotationEmptyState } from '@backstage/core-components';
|
||||
|
||||
export const isAzureDevOpsAvailable = (entity: Entity) =>
|
||||
Boolean(entity.metadata.annotations?.[AZURE_DEVOPS_ANNOTATION]);
|
||||
|
||||
type Props = {
|
||||
/** @deprecated The entity is now grabbed from context instead */
|
||||
entity?: Entity;
|
||||
};
|
||||
|
||||
export const Router = (_props: Props) => {
|
||||
const { entity } = useEntity();
|
||||
|
||||
if (!isAzureDevOpsAvailable(entity)) {
|
||||
return <MissingAnnotationEmptyState annotation={AZURE_DEVOPS_ANNOTATION} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Routes>
|
||||
<Route
|
||||
path={`/${azureDevOpsRouteRef.path}`}
|
||||
element={<EntityPageAzureDevOps />}
|
||||
/>
|
||||
</Routes>
|
||||
);
|
||||
};
|
||||
@@ -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 const AZURE_DEVOPS_ANNOTATION = 'dev.azure.com/project-repo';
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { AZURE_DEVOPS_ANNOTATION } from '../constants';
|
||||
|
||||
export function useProjectRepoFromEntity(entity: Entity) {
|
||||
const [project, repo] = (
|
||||
entity.metadata.annotations?.[AZURE_DEVOPS_ANNOTATION] ?? ''
|
||||
).split('/');
|
||||
return { project, repo };
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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 { useAsync } from 'react-use';
|
||||
import { Entity } from '@backstage/catalog-model';
|
||||
import { useApi, configApiRef } from '@backstage/core-plugin-api';
|
||||
import { azureDevOpsApiRef } from '../api';
|
||||
import { RepoBuild } from '../api/types';
|
||||
import { useProjectRepoFromEntity } from './useProjectRepoFromEntity';
|
||||
|
||||
const DEFAULT_TOP: number = 10;
|
||||
|
||||
export function useRepoBuilds(entity: Entity) {
|
||||
const config = useApi(configApiRef);
|
||||
const top = config.getOptionalNumber('azureDevOps.top') ?? DEFAULT_TOP;
|
||||
const api = useApi(azureDevOpsApiRef);
|
||||
const { project, repo } = useProjectRepoFromEntity(entity);
|
||||
const { value, loading, error } = useAsync(() => {
|
||||
return api.getRepoBuilds(project, repo, top);
|
||||
}, [api, project, repo, entity]);
|
||||
|
||||
return {
|
||||
items: value as RepoBuild[],
|
||||
loading,
|
||||
error,
|
||||
};
|
||||
}
|
||||
@@ -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 { azureDevOpsPlugin, EntityAzureDevOpsContent } from './plugin';
|
||||
export { isAzureDevOpsAvailable } from './components/Router';
|
||||
@@ -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 { azureDevOpsPlugin } from './plugin';
|
||||
|
||||
describe('azure-devops', () => {
|
||||
it('should export plugin', () => {
|
||||
expect(azureDevOpsPlugin).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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 { azureDevOpsApiRef } from './api/AzureDevOpsApi';
|
||||
import { AzureDevOpsClient } from './api/AzureDevOpsClient';
|
||||
import {
|
||||
createApiFactory,
|
||||
createPlugin,
|
||||
createRoutableExtension,
|
||||
createRouteRef,
|
||||
discoveryApiRef,
|
||||
identityApiRef,
|
||||
} from '@backstage/core-plugin-api';
|
||||
|
||||
export const rootRouteRef = createRouteRef({
|
||||
path: '',
|
||||
title: 'AzureDevOps',
|
||||
});
|
||||
|
||||
export const azureDevOpsPlugin = createPlugin({
|
||||
id: 'azureDevOps',
|
||||
apis: [
|
||||
createApiFactory({
|
||||
api: azureDevOpsApiRef,
|
||||
deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef },
|
||||
factory: ({ discoveryApi, identityApi }) =>
|
||||
new AzureDevOpsClient({ discoveryApi, identityApi }),
|
||||
}),
|
||||
],
|
||||
routes: {
|
||||
entityContent: rootRouteRef,
|
||||
},
|
||||
});
|
||||
|
||||
export const EntityAzureDevOpsContent = azureDevOpsPlugin.provide(
|
||||
createRoutableExtension({
|
||||
name: 'EntityAzureDevOpsContent',
|
||||
component: () => import('./components/Router').then(m => m.Router),
|
||||
mountPoint: rootRouteRef,
|
||||
}),
|
||||
);
|
||||
@@ -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 azureDevOpsRouteRef = createRouteRef({
|
||||
title: 'azure-devops',
|
||||
});
|
||||
@@ -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';
|
||||
Reference in New Issue
Block a user