diff --git a/packages/app/src/components/catalog/EntityPage.tsx b/packages/app/src/components/catalog/EntityPage.tsx
index b79bd2c4aa..4147874e65 100644
--- a/packages/app/src/components/catalog/EntityPage.tsx
+++ b/packages/app/src/components/catalog/EntityPage.tsx
@@ -34,7 +34,7 @@ import {
EntityProvidingComponentsCard,
} from '@backstage/plugin-api-docs';
import {
- EntityAzureDevOpsContent,
+ EntityAzurePipelinesContent,
isAzureDevOpsAvailable,
} from '@backstage/plugin-azure-devops';
import { EntityBadgesDialog } from '@backstage/plugin-badges';
@@ -188,7 +188,7 @@ export const cicdContent = (
-
+
diff --git a/plugins/azure-devops/README.md b/plugins/azure-devops/README.md
index 376a630873..97a415d8d0 100644
--- a/plugins/azure-devops/README.md
+++ b/plugins/azure-devops/README.md
@@ -2,7 +2,7 @@
Website: [https://dev.azure.com/](https://dev.azure.com/)
-
+
## Setup
diff --git a/plugins/azure-devops/config.d.ts b/plugins/azure-devops/config.d.ts
index 827e64d5bd..62b1488e49 100644
--- a/plugins/azure-devops/config.d.ts
+++ b/plugins/azure-devops/config.d.ts
@@ -1,5 +1,5 @@
/*
- * Copyright 2020 The Backstage Authors
+ * 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.
diff --git a/plugins/azure-devops/doc/azure-devops-builds.png b/plugins/azure-devops/docs/azure-devops-builds.png
similarity index 100%
rename from plugins/azure-devops/doc/azure-devops-builds.png
rename to plugins/azure-devops/docs/azure-devops-builds.png
diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json
index c823924c9d..16e8f35991 100644
--- a/plugins/azure-devops/package.json
+++ b/plugins/azure-devops/package.json
@@ -27,8 +27,8 @@
},
"dependencies": {
"@backstage/catalog-model": "^0.9.3",
- "@backstage/core-components": "^0.6.0",
- "@backstage/core-plugin-api": "^0.1.9",
+ "@backstage/core-components": "^0.6.1",
+ "@backstage/core-plugin-api": "^0.1.10",
"@backstage/plugin-catalog-react": "^0.5.1",
"@backstage/theme": "^0.2.10",
"@material-ui/core": "^4.12.2",
@@ -42,10 +42,10 @@
"react-use": "^17.2.4"
},
"devDependencies": {
- "@backstage/cli": "^0.7.14",
- "@backstage/core-app-api": "^0.1.15",
+ "@backstage/cli": "^0.7.15",
+ "@backstage/core-app-api": "^0.1.16",
"@backstage/dev-utils": "^0.2.11",
- "@backstage/test-utils": "^0.1.17",
+ "@backstage/test-utils": "^0.1.18",
"@testing-library/jest-dom": "^5.10.1",
"@testing-library/react": "^11.2.5",
"@testing-library/user-event": "^13.1.8",
diff --git a/plugins/azure-devops/src/api/AzureDevOpsClient.ts b/plugins/azure-devops/src/api/AzureDevOpsClient.ts
index c9e44109aa..32a563f429 100644
--- a/plugins/azure-devops/src/api/AzureDevOpsClient.ts
+++ b/plugins/azure-devops/src/api/AzureDevOpsClient.ts
@@ -17,6 +17,7 @@
import { AzureDevOpsApi } from './AzureDevOpsApi';
import { RepoBuild } from './types';
import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api';
+import { AzureDevOpsClientError } from './AzureDevOpsClientError';
export class AzureDevOpsClient implements AzureDevOpsApi {
private readonly discoveryApi: DiscoveryApi;
@@ -39,7 +40,9 @@ export class AzureDevOpsClient implements AzureDevOpsApi {
}
private async get(path: string): Promise {
- const url = `${await this.discoveryApi.getBaseUrl('azure-devops')}${path}`;
+ const baseUrl = await this.discoveryApi.getBaseUrl('azure-devops');
+ const url = `${baseUrl}/${path}`;
+
const idToken = await this.identityApi.getIdToken();
const response = await fetch(url, {
headers: idToken ? { Authorization: `Bearer ${idToken}` } : {},
@@ -47,8 +50,7 @@ export class AzureDevOpsClient implements AzureDevOpsApi {
if (!response.ok) {
const payload = await response.text();
- const message = `Request failed with ${response.status} ${response.statusText}, ${payload}`;
- throw new Error(message);
+ throw new AzureDevOpsClientError(response, payload);
}
return await response.json();
diff --git a/plugins/azure-devops/src/api/AzureDevOpsClientError.ts b/plugins/azure-devops/src/api/AzureDevOpsClientError.ts
new file mode 100644
index 0000000000..f9a2f37b41
--- /dev/null
+++ b/plugins/azure-devops/src/api/AzureDevOpsClientError.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 class AzureDevOpsClientError extends Error {
+ public constructor({ status, statusText }: Response, payload: string) {
+ super(`Request failed with ${status} ${statusText}, ${payload}`);
+ }
+}
diff --git a/plugins/azure-devops/src/api/types.ts b/plugins/azure-devops/src/api/types.ts
index 35d4e38ae1..b3562f76c6 100644
--- a/plugins/azure-devops/src/api/types.ts
+++ b/plugins/azure-devops/src/api/types.ts
@@ -22,7 +22,7 @@ import {
export type RepoBuild = {
id?: number;
title: string;
- link: string;
+ link?: string;
status?: BuildStatus;
result?: BuildResult;
queueTime?: Date;
diff --git a/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx b/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx
index 26f365c5e9..e853662fbf 100644
--- a/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx
+++ b/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx
@@ -32,17 +32,19 @@ import {
BuildStatus,
} from 'azure-devops-node-api/interfaces/BuildInterfaces';
-const getBuildResultComponent = (result: number | undefined = 0) => {
+const getBuildResultComponent = (
+ result: number | undefined = BuildResult.None,
+) => {
switch (result) {
- case 0: // None
+ case BuildResult.None:
return ;
- case 2: // Succeeded
+ case BuildResult.Succeeded:
return ;
- case 4: // PartiallySucceeded
+ case BuildResult.PartiallySucceeded:
return ;
- case 8: // Failed
+ case BuildResult.Failed:
return ;
- case 32: // Canceled
+ case BuildResult.Canceled:
return ;
default:
return ;
@@ -75,7 +77,9 @@ const columns: TableColumn[] = [
render: (row: Partial) => (
- {BuildStatus[row.status || 0]}
+
+ {BuildStatus[row.status || BuildStatus.None]}
+
),
},
@@ -86,7 +90,9 @@ const columns: TableColumn[] = [
{getBuildResultComponent(row.result)}
- {BuildResult[row.result || 0]}
+
+ {BuildResult[row.result || BuildResult.None]}
+
),
},
@@ -98,7 +104,7 @@ const columns: TableColumn[] = [
];
type Props = {
- items: RepoBuild[];
+ items?: RepoBuild[];
loading: boolean;
error?: any;
};
@@ -125,8 +131,8 @@ export const BuildTable = ({ items, loading, error }: Props) => {
pageSize: 5,
showEmptyDataSourceMessage: !loading,
}}
- title={`Builds (${(items && items.length) || 0})`}
- data={items}
+ title={`Builds (${items ? items.length : 0})`}
+ data={items || []}
/>
);
};
diff --git a/plugins/azure-devops/src/components/EntityPageAzureDevOps/EntityPageAzureDevOps.tsx b/plugins/azure-devops/src/components/EntityPageAzureDevOps/EntityPageAzureDevOps.tsx
index fbeac53569..8e102e647d 100644
--- a/plugins/azure-devops/src/components/EntityPageAzureDevOps/EntityPageAzureDevOps.tsx
+++ b/plugins/azure-devops/src/components/EntityPageAzureDevOps/EntityPageAzureDevOps.tsx
@@ -29,5 +29,5 @@ export const EntityPageAzureDevOps = (_props: Props) => {
const { entity } = useEntity();
const { items, loading, error } = useRepoBuilds(entity);
- return ;
+ return ;
};
diff --git a/plugins/azure-devops/src/constants.ts b/plugins/azure-devops/src/constants.ts
index 6abc6449e9..d6e67ff7ed 100644
--- a/plugins/azure-devops/src/constants.ts
+++ b/plugins/azure-devops/src/constants.ts
@@ -15,3 +15,4 @@
*/
export const AZURE_DEVOPS_ANNOTATION = 'dev.azure.com/project-repo';
+export const AZURE_DEVOPS_DEFAULT_TOP: number = 10;
diff --git a/plugins/azure-devops/src/hooks/useProjectRepoFromEntity.ts b/plugins/azure-devops/src/hooks/useProjectRepoFromEntity.ts
index 721fa52781..dfbee81d62 100644
--- a/plugins/azure-devops/src/hooks/useProjectRepoFromEntity.ts
+++ b/plugins/azure-devops/src/hooks/useProjectRepoFromEntity.ts
@@ -17,7 +17,10 @@
import { Entity } from '@backstage/catalog-model';
import { AZURE_DEVOPS_ANNOTATION } from '../constants';
-export function useProjectRepoFromEntity(entity: Entity) {
+export function useProjectRepoFromEntity(entity: Entity): {
+ project: string;
+ repo: string;
+} {
const [project, repo] = (
entity.metadata.annotations?.[AZURE_DEVOPS_ANNOTATION] ?? ''
).split('/');
diff --git a/plugins/azure-devops/src/hooks/useRepoBuilds.ts b/plugins/azure-devops/src/hooks/useRepoBuilds.ts
index e6d2964770..1e68490ea6 100644
--- a/plugins/azure-devops/src/hooks/useRepoBuilds.ts
+++ b/plugins/azure-devops/src/hooks/useRepoBuilds.ts
@@ -20,12 +20,16 @@ import { useApi, configApiRef } from '@backstage/core-plugin-api';
import { azureDevOpsApiRef } from '../api';
import { RepoBuild } from '../api/types';
import { useProjectRepoFromEntity } from './useProjectRepoFromEntity';
+import { AZURE_DEVOPS_DEFAULT_TOP } from '../constants';
-const DEFAULT_TOP: number = 10;
-
-export function useRepoBuilds(entity: Entity) {
+export function useRepoBuilds(entity: Entity): {
+ items: RepoBuild[];
+ loading: boolean;
+ error: any;
+} {
const config = useApi(configApiRef);
- const top = config.getOptionalNumber('azureDevOps.top') ?? DEFAULT_TOP;
+ const top =
+ config.getOptionalNumber('azureDevOps.top') ?? AZURE_DEVOPS_DEFAULT_TOP;
const api = useApi(azureDevOpsApiRef);
const { project, repo } = useProjectRepoFromEntity(entity);
const { value, loading, error } = useAsync(() => {
diff --git a/plugins/azure-devops/src/index.ts b/plugins/azure-devops/src/index.ts
index b654aebab7..9a90d6ed6a 100644
--- a/plugins/azure-devops/src/index.ts
+++ b/plugins/azure-devops/src/index.ts
@@ -13,5 +13,5 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-export { azureDevOpsPlugin, EntityAzureDevOpsContent } from './plugin';
+export { azureDevOpsPlugin, EntityAzurePipelinesContent } from './plugin';
export { isAzureDevOpsAvailable } from './components/Router';
diff --git a/plugins/azure-devops/src/plugin.ts b/plugins/azure-devops/src/plugin.ts
index f37fab6d62..9ec5ebbb09 100644
--- a/plugins/azure-devops/src/plugin.ts
+++ b/plugins/azure-devops/src/plugin.ts
@@ -20,15 +20,10 @@ import {
createApiFactory,
createPlugin,
createRoutableExtension,
- createRouteRef,
discoveryApiRef,
identityApiRef,
} from '@backstage/core-plugin-api';
-
-export const rootRouteRef = createRouteRef({
- path: '',
- title: 'AzureDevOps',
-});
+import { azureDevOpsRouteRef } from './routes';
export const azureDevOpsPlugin = createPlugin({
id: 'azureDevOps',
@@ -41,14 +36,14 @@ export const azureDevOpsPlugin = createPlugin({
}),
],
routes: {
- entityContent: rootRouteRef,
+ entityContent: azureDevOpsRouteRef,
},
});
-export const EntityAzureDevOpsContent = azureDevOpsPlugin.provide(
+export const EntityAzurePipelinesContent = azureDevOpsPlugin.provide(
createRoutableExtension({
name: 'EntityAzureDevOpsContent',
component: () => import('./components/Router').then(m => m.Router),
- mountPoint: rootRouteRef,
+ mountPoint: azureDevOpsRouteRef,
}),
);