More improvements

Signed-off-by: Andre Wanlin <awanlin@rapidrtc.com>
This commit is contained in:
Andre Wanlin
2021-10-11 16:48:10 -05:00
parent eed36accea
commit 148d9d22c8
11 changed files with 40 additions and 68 deletions
+1 -1
View File
@@ -32,7 +32,7 @@ Configuration Details:
Here's how to get the backend up and running:
1. First we need to add the @backstage/plugin-azure-devops-backend package to your backend:
1. First we need to add the `@backstage/plugin-azure-devops-backend` package to your backend:
```sh
# From the Backstage root directory
+1 -3
View File
@@ -22,9 +22,7 @@ export const azureDevOpsPlugin: BackstagePlugin<
// Warning: (ae-missing-release-tag) "EntityAzurePipelinesContent" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export const EntityAzurePipelinesContent: (_props: {
entity?: Entity | undefined;
}) => JSX.Element;
export const EntityAzurePipelinesContent: () => JSX.Element;
// Warning: (ae-missing-release-tag) "isAzureDevOpsAvailable" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
+4 -2
View File
@@ -4,6 +4,7 @@
"main": "src/index.ts",
"types": "src/index.ts",
"license": "Apache-2.0",
"private": false,
"publishConfig": {
"access": "public",
"main": "dist/index.esm.js",
@@ -29,6 +30,7 @@
"@backstage/catalog-model": "^0.9.3",
"@backstage/core-components": "^0.6.1",
"@backstage/core-plugin-api": "^0.1.10",
"@backstage/errors": "^0.1.2",
"@backstage/plugin-catalog-react": "^0.5.1",
"@backstage/theme": "^0.2.10",
"@material-ui/core": "^4.12.2",
@@ -51,8 +53,8 @@
"@testing-library/user-event": "^13.1.8",
"@types/jest": "^26.0.7",
"@types/node": "^14.14.32",
"msw": "^0.29.0",
"cross-fetch": "^3.0.6"
"cross-fetch": "^3.0.6",
"msw": "^0.29.0"
},
"files": [
"dist",
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import { RepoBuild } from './types';
import { RepoBuild, RepoBuildOptions } from './types';
import { createApiRef } from '@backstage/core-plugin-api';
export const azureDevOpsApiRef = createApiRef<AzureDevOpsApi>({
@@ -27,6 +27,6 @@ export interface AzureDevOpsApi {
getRepoBuilds(
projectName: string,
repoName: string,
top: number,
): Promise<RepoBuild[]>;
options?: RepoBuildOptions,
): Promise<{ items: RepoBuild[] }>;
}
@@ -15,9 +15,9 @@
*/
import { AzureDevOpsApi } from './AzureDevOpsApi';
import { RepoBuild } from './types';
import { RepoBuild, RepoBuildOptions } from './types';
import { DiscoveryApi, IdentityApi } from '@backstage/core-plugin-api';
import { AzureDevOpsClientError } from './AzureDevOpsClientError';
import { ResponseError } from '@backstage/errors';
export class AzureDevOpsClient implements AzureDevOpsApi {
private readonly discoveryApi: DiscoveryApi;
@@ -34,12 +34,14 @@ export class AzureDevOpsClient implements AzureDevOpsApi {
getRepoBuilds(
projectName: string,
repoName: string,
top: number,
): Promise<RepoBuild[]> {
return this.get(`repo-builds/${projectName}/${repoName}?top=${top}`);
options?: RepoBuildOptions,
): Promise<{ items: RepoBuild[] }> {
return this.get(
`repo-builds/${projectName}/${repoName}?top=${options?.top}`,
);
}
private async get(path: string): Promise<any> {
private async get(path: string): Promise<{ items: any }> {
const baseUrl = `${await this.discoveryApi.getBaseUrl('azure-devops')}/`;
const url = new URL(path, baseUrl);
@@ -49,10 +51,9 @@ export class AzureDevOpsClient implements AzureDevOpsApi {
});
if (!response.ok) {
const payload = await response.text();
throw new AzureDevOpsClientError(response, payload);
throw await ResponseError.fromResponse(response);
}
return response.json() as Promise<any>;
return response.json() as Promise<{ items: any }>;
}
}
@@ -1,21 +0,0 @@
/*
* 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}`);
}
}
+4
View File
@@ -28,3 +28,7 @@ export type RepoBuild = {
queueTime?: Date;
source: string;
};
export type RepoBuildOptions = {
top?: number;
};
@@ -17,6 +17,7 @@
import React from 'react';
import { DateTime } from 'luxon';
import {
Link,
Table,
TableColumn,
StatusError,
@@ -25,9 +26,9 @@ import {
StatusAborted,
StatusRunning,
StatusPending,
ResponseErrorPanel,
} from '@backstage/core-components';
import { Link, Box, Typography } from '@material-ui/core';
import Alert from '@material-ui/lab/Alert';
import { Box, Typography } from '@material-ui/core';
import { RepoBuild } from '../../api/types';
import {
BuildResult,
@@ -39,25 +40,25 @@ const getBuildResultComponent = (result: number | undefined) => {
case BuildResult.Succeeded:
return (
<span>
<StatusOK /> Succeeded{' '}
<StatusOK /> Succeeded
</span>
);
case BuildResult.PartiallySucceeded:
return (
<span>
<StatusWarning /> Partially Succeeded{' '}
<StatusWarning /> Partially Succeeded
</span>
);
case BuildResult.Failed:
return (
<span>
<StatusError /> Failed{' '}
<StatusError /> Failed
</span>
);
case BuildResult.Canceled:
return (
<span>
<StatusAborted /> Canceled{' '}
<StatusAborted /> Canceled
</span>
);
case BuildResult.None:
@@ -123,9 +124,7 @@ const columns: TableColumn[] = [
field: 'title',
width: 'auto',
render: (row: Partial<RepoBuild>) => (
<Link href={row.link} target="_blank">
{row.title}
</Link>
<Link to={row.link || ''}>{row.title}</Link>
),
},
{
@@ -165,10 +164,7 @@ export const BuildTable = ({ items, loading, error }: Props) => {
if (error) {
return (
<div>
<Alert severity="error">
Error encountered while fetching Azure DevOps builds.{' '}
{error.toString()}
</Alert>
<ResponseErrorPanel error={error} />
</div>
);
}
@@ -14,18 +14,12 @@
* 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 EntityPageAzurePipelines = (_props: Props) => {
export const EntityPageAzurePipelines = () => {
const { entity } = useEntity();
const { items, loading, error } = useRepoBuilds(entity);
@@ -25,12 +25,7 @@ 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) => {
export const Router = () => {
const { entity } = useEntity();
if (!isAzureDevOpsAvailable(entity)) {
@@ -18,7 +18,7 @@ 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 { RepoBuild, RepoBuildOptions } from '../api/types';
import { useProjectRepoFromEntity } from './useProjectRepoFromEntity';
import { AZURE_DEVOPS_DEFAULT_TOP } from '../constants';
@@ -31,14 +31,17 @@ export function useRepoBuilds(entity: Entity): {
const top =
config.getOptionalNumber('azureDevOps.azurePipelines.top') ??
AZURE_DEVOPS_DEFAULT_TOP;
const options: RepoBuildOptions = {
top: top,
};
const api = useApi(azureDevOpsApiRef);
const { project, repo } = useProjectRepoFromEntity(entity);
const { value, loading, error } = useAsync(() => {
return api.getRepoBuilds(project, repo, top);
return api.getRepoBuilds(project, repo, options);
}, [api, project, repo, entity]);
return {
items: value as RepoBuild[],
items: value?.items as RepoBuild[],
loading,
error,
};