diff --git a/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts b/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts index 89e32aa2f3..1a80a3d42b 100644 --- a/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts +++ b/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts @@ -14,42 +14,47 @@ * limitations under the License. */ -import { Logger } from 'winston'; -import { WebApi } from 'azure-devops-node-api'; import { Build, BuildResult, BuildStatus, -} from 'azure-devops-node-api/interfaces/BuildInterfaces'; -import { GitPullRequest, GitPullRequestSearchCriteria, -} from 'azure-devops-node-api/interfaces/GitInterfaces'; -import { PullRequest, PullRequestOptions, RepoBuild } from './types'; + GitRepository, + PullRequest, + PullRequestOptions, + RepoBuild, +} from './types'; + +import { Logger } from 'winston'; +import { WebApi } from 'azure-devops-node-api'; export class AzureDevOpsApi { - constructor( + public constructor( private readonly logger: Logger, private readonly webApi: WebApi, ) {} - async getGitRepository(projectName: string, repoName: string) { - if (this.logger) { - this.logger.debug( - `Calling Azure DevOps REST API, getting Repository ${repoName} for Project ${projectName}`, - ); - } + public async getGitRepository( + projectName: string, + repoName: string, + ): Promise { + this.logger?.debug( + `Calling Azure DevOps REST API, getting Repository ${repoName} for Project ${projectName}`, + ); const client = await this.webApi.getGitApi(); return client.getRepository(repoName, projectName); } - async getBuildList(projectName: string, repoId: string, top: number) { - if (this.logger) { - this.logger.debug( - `Calling Azure DevOps REST API, getting up to ${top} Builds for Repository Id ${repoId} for Project ${projectName}`, - ); - } + public async getBuildList( + projectName: string, + repoId: string, + top: number, + ): Promise { + this.logger?.debug( + `Calling Azure DevOps REST API, getting up to ${top} Builds for Repository Id ${repoId} for Project ${projectName}`, + ); const client = await this.webApi.getBuildApi(); return client.getBuilds( @@ -77,12 +82,14 @@ export class AzureDevOpsApi { ); } - async getRepoBuilds(projectName: string, repoName: string, top: number) { - if (this.logger) { - this.logger.debug( - `Calling Azure DevOps REST API, getting up to ${top} Builds for Repository ${repoName} for Project ${projectName}`, - ); - } + public async getRepoBuilds( + projectName: string, + repoName: string, + top: number, + ) { + this.logger?.debug( + `Calling Azure DevOps REST API, getting up to ${top} Builds for Repository ${repoName} for Project ${projectName}`, + ); const gitRepository = await this.getGitRepository(projectName, repoName); const buildList = await this.getBuildList( @@ -98,16 +105,14 @@ export class AzureDevOpsApi { return repoBuilds; } - async getPullRequests( + public async getPullRequests( projectName: string, repoName: string, options: PullRequestOptions, - ) { - if (this.logger) { - this.logger.debug( - `Calling Azure DevOps REST API, getting up to ${top} Pull Requests for Repository ${repoName} for Project ${projectName}`, - ); - } + ): Promise { + this.logger?.debug( + `Calling Azure DevOps REST API, getting up to ${top} Pull Requests for Repository ${repoName} for Project ${projectName}`, + ); const gitRepository = await this.getGitRepository(projectName, repoName); const client = await this.webApi.getGitApi(); @@ -133,7 +138,7 @@ export class AzureDevOpsApi { } } -export function mappedRepoBuild(build: Build) { +export function mappedRepoBuild(build: Build): RepoBuild { return { id: build.id, title: [build.definition?.name, build.buildNumber] @@ -150,7 +155,7 @@ export function mappedRepoBuild(build: Build) { export function mappedPullRequest( pullRequest: GitPullRequest, linkBaseUrl: string, -) { +): PullRequest { return { pullRequestId: pullRequest.pullRequestId, repoName: pullRequest.repository?.name, diff --git a/plugins/azure-devops-backend/src/api/index.ts b/plugins/azure-devops-backend/src/api/index.ts index 893f0f4f2c..97c48cb0bf 100644 --- a/plugins/azure-devops-backend/src/api/index.ts +++ b/plugins/azure-devops-backend/src/api/index.ts @@ -15,4 +15,5 @@ */ export { AzureDevOpsApi } from './AzureDevOpsApi'; +export { BuildResult, BuildStatus } from './types'; export type { RepoBuild, PullRequest } from './types'; diff --git a/plugins/azure-devops-backend/src/api/types.ts b/plugins/azure-devops-backend/src/api/types.ts index a53f501f26..724a65b986 100644 --- a/plugins/azure-devops-backend/src/api/types.ts +++ b/plugins/azure-devops-backend/src/api/types.ts @@ -15,10 +15,25 @@ */ import { + Build, BuildResult, BuildStatus, } from 'azure-devops-node-api/interfaces/BuildInterfaces'; -import { PullRequestStatus } from 'azure-devops-node-api/interfaces/GitInterfaces'; +import { + GitPullRequest, + GitPullRequestSearchCriteria, + GitRepository, + PullRequestStatus, +} from 'azure-devops-node-api/interfaces/GitInterfaces'; + +export { BuildResult, BuildStatus }; +export type { + Build, + GitPullRequest, + GitPullRequestSearchCriteria, + GitRepository, + PullRequestStatus, +}; export type RepoBuild = { id?: number; diff --git a/plugins/azure-devops-backend/src/index.ts b/plugins/azure-devops-backend/src/index.ts index ff4d3973bf..7a2a347b65 100644 --- a/plugins/azure-devops-backend/src/index.ts +++ b/plugins/azure-devops-backend/src/index.ts @@ -13,6 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -export { AzureDevOpsApi } from './api'; +export { AzureDevOpsApi, BuildResult, BuildStatus } from './api'; export type { RepoBuild, PullRequest } from './api'; export * from './service/router'; diff --git a/plugins/azure-devops-backend/src/service/router.ts b/plugins/azure-devops-backend/src/service/router.ts index 0929d5cde9..b3505eae1c 100644 --- a/plugins/azure-devops-backend/src/service/router.ts +++ b/plugins/azure-devops-backend/src/service/router.ts @@ -14,15 +14,15 @@ * limitations under the License. */ +import { PullRequestOptions, PullRequestStatus } from '../api/types'; +import { WebApi, getPersonalAccessTokenHandler } from 'azure-devops-node-api'; + +import { AzureDevOpsApi } from '../api'; +import { Config } from '@backstage/config'; +import { Logger } from 'winston'; +import Router from 'express-promise-router'; import { errorHandler } from '@backstage/backend-common'; import express from 'express'; -import Router from 'express-promise-router'; -import { Logger } from 'winston'; -import { Config } from '@backstage/config'; -import { getPersonalAccessTokenHandler, WebApi } from 'azure-devops-node-api'; -import { AzureDevOpsApi } from '../api'; -import { PullRequestStatus } from 'azure-devops-node-api/interfaces/GitInterfaces'; -import { PullRequestOptions } from '../api/types'; const DEFAULT_TOP: number = 10; diff --git a/plugins/azure-devops/package.json b/plugins/azure-devops/package.json index c4aea032d2..f9dff7229c 100644 --- a/plugins/azure-devops/package.json +++ b/plugins/azure-devops/package.json @@ -31,12 +31,12 @@ "@backstage/core-components": "^0.7.0", "@backstage/core-plugin-api": "^0.1.10", "@backstage/errors": "^0.1.2", + "@backstage/plugin-azure-devops-backend": "^0.1.2", "@backstage/plugin-catalog-react": "^0.6.0", "@backstage/theme": "^0.2.11", "@material-ui/core": "^4.12.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "4.0.0-alpha.57", - "azure-devops-node-api": "^11.0.1", "luxon": "^2.0.2", "react": "^16.13.1", "react-dom": "^16.13.1", diff --git a/plugins/azure-devops/src/api/types.ts b/plugins/azure-devops/src/api/types.ts index 1fbc34231e..46a9212aca 100644 --- a/plugins/azure-devops/src/api/types.ts +++ b/plugins/azure-devops/src/api/types.ts @@ -17,7 +17,7 @@ import { BuildResult, BuildStatus, -} from 'azure-devops-node-api/interfaces/BuildInterfaces'; +} from '@backstage/plugin-azure-devops-backend'; export type RepoBuild = { id?: number; diff --git a/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx b/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx index bead424ffb..983f4959b4 100644 --- a/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx +++ b/plugins/azure-devops/src/components/BuildTable/BuildTable.tsx @@ -14,26 +14,27 @@ * limitations under the License. */ -import React from 'react'; -import { DateTime } from 'luxon'; -import { - Link, - Table, - TableColumn, - StatusError, - StatusOK, - StatusWarning, - StatusAborted, - StatusRunning, - StatusPending, - ResponseErrorPanel, -} from '@backstage/core-components'; import { Box, Typography } from '@material-ui/core'; -import { RepoBuild } from '../../api/types'; import { BuildResult, BuildStatus, -} from 'azure-devops-node-api/interfaces/BuildInterfaces'; +} from '@backstage/plugin-azure-devops-backend'; +import { + Link, + ResponseErrorPanel, + StatusAborted, + StatusError, + StatusOK, + StatusPending, + StatusRunning, + StatusWarning, + Table, + TableColumn, +} from '@backstage/core-components'; + +import { DateTime } from 'luxon'; +import React from 'react'; +import { RepoBuild } from '../../api/types'; const getBuildResultComponent = (result: number | undefined) => { switch (result) { @@ -154,13 +155,13 @@ const columns: TableColumn[] = [ }, ]; -type Props = { - items?: RepoBuild[]; +type BuildTableProps = { + items: RepoBuild[] | null; loading: boolean; - error?: any; + error: Error | null; }; -export const BuildTable = ({ items, loading, error }: Props) => { +export const BuildTable = ({ items, loading, error }: BuildTableProps) => { if (error) { return (
@@ -180,7 +181,7 @@ export const BuildTable = ({ items, loading, error }: Props) => { showEmptyDataSourceMessage: !loading, }} title={`Builds (${items ? items.length : 0})`} - data={items || []} + data={items ?? []} /> ); }; diff --git a/plugins/azure-devops/src/hooks/useRepoBuilds.ts b/plugins/azure-devops/src/hooks/useRepoBuilds.ts index 14a8a79428..56528f84a0 100644 --- a/plugins/azure-devops/src/hooks/useRepoBuilds.ts +++ b/plugins/azure-devops/src/hooks/useRepoBuilds.ts @@ -14,35 +14,38 @@ * limitations under the License. */ -import { useAsync } from 'react-use'; -import { Entity } from '@backstage/catalog-model'; -import { useApi } from '@backstage/core-plugin-api'; -import { azureDevOpsApiRef } from '../api'; import { RepoBuild, RepoBuildOptions } from '../api/types'; -import { useProjectRepoFromEntity } from './useProjectRepoFromEntity'; + import { AZURE_DEVOPS_DEFAULT_TOP } from '../constants'; +import { Entity } from '@backstage/catalog-model'; +import { azureDevOpsApiRef } from '../api'; +import { useApi } from '@backstage/core-plugin-api'; +import { useAsync } from 'react-use'; +import { useProjectRepoFromEntity } from './useProjectRepoFromEntity'; export function useRepoBuilds( entity: Entity, defaultLimit?: number, ): { - items: RepoBuild[] | undefined; + items: RepoBuild[] | null; loading: boolean; - error: any; + error: Error | null; } { const top = defaultLimit ?? 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, options); }, [api, project, repo, entity]); return { - items: value?.items, + items: value?.items ?? null, loading, - error, + error: error ?? null, }; }