From 308b0eef3c9c860c0d37b94dc07ae419900ebc5b Mon Sep 17 00:00:00 2001 From: David Roberts Date: Wed, 7 Feb 2024 11:43:08 +0000 Subject: [PATCH] Ability to fetch the README file from a different AZD path, using an annotation on the entity Signed-off-by: David Roberts --- .../azure-devops-backend/src/api/AzureDevOpsApi.ts | 3 ++- plugins/azure-devops-backend/src/service/router.ts | 2 ++ plugins/azure-devops-common/src/constants.ts | 2 ++ plugins/azure-devops-common/src/types.ts | 1 + plugins/azure-devops/src/api/AzureDevOpsClient.ts | 3 +++ plugins/azure-devops/src/hooks/useReadme.ts | 11 +++++++++-- .../src/utils/getAnnotationValuesFromEntity.ts | 7 +++++++ 7 files changed, 26 insertions(+), 3 deletions(-) diff --git a/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts b/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts index d50888006b..cc5cad92b7 100644 --- a/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts +++ b/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts @@ -527,11 +527,12 @@ export class AzureDevOpsApi { org: string, project: string, repo: string, + path: string, ): Promise<{ url: string; content: string; }> { - const url = buildEncodedUrl(host, org, project, repo, 'README.md'); + const url = buildEncodedUrl(host, org, project, repo, path); const response = await this.urlReader.readUrl(url); const buffer = await response.buffer(); const content = await replaceReadme( diff --git a/plugins/azure-devops-backend/src/service/router.ts b/plugins/azure-devops-backend/src/service/router.ts index 9a71c8f03d..a00b0ce910 100644 --- a/plugins/azure-devops-backend/src/service/router.ts +++ b/plugins/azure-devops-backend/src/service/router.ts @@ -216,12 +216,14 @@ export async function createRouter( req.query.host?.toString() ?? config.getString('azureDevOps.host'); const org = req.query.org?.toString() ?? config.getString('azureDevOps.organization'); + const path = req.query.path?.toString() ?? 'README.md'; const { projectName, repoName } = req.params; const readme = await azureDevOpsApi.getReadme( host, org, projectName, repoName, + path, ); res.status(200).json(readme); }); diff --git a/plugins/azure-devops-common/src/constants.ts b/plugins/azure-devops-common/src/constants.ts index 5cc6b54592..05eb430cc9 100644 --- a/plugins/azure-devops-common/src/constants.ts +++ b/plugins/azure-devops-common/src/constants.ts @@ -22,6 +22,8 @@ export const AZURE_DEVOPS_HOST_ORG_ANNOTATION = 'dev.azure.com/host-org'; /** @public */ export const AZURE_DEVOPS_PROJECT_ANNOTATION = 'dev.azure.com/project'; /** @public */ +export const AZURE_DEVOPS_README_ANNOTATION = 'dev.azure.com/readme-path'; +/** @public */ export const AZURE_DEVOPS_REPO_ANNOTATION = 'dev.azure.com/project-repo'; /** @public */ export const AZURE_DEVOPS_DEFAULT_TOP: number = 10; diff --git a/plugins/azure-devops-common/src/types.ts b/plugins/azure-devops-common/src/types.ts index afb6083867..0390bb1f6e 100644 --- a/plugins/azure-devops-common/src/types.ts +++ b/plugins/azure-devops-common/src/types.ts @@ -212,6 +212,7 @@ export interface ReadmeConfig { repo: string; host?: string; org?: string; + path?: string; } /** @public */ diff --git a/plugins/azure-devops/src/api/AzureDevOpsClient.ts b/plugins/azure-devops/src/api/AzureDevOpsClient.ts index 76e38b064c..a10b10ff14 100644 --- a/plugins/azure-devops/src/api/AzureDevOpsClient.ts +++ b/plugins/azure-devops/src/api/AzureDevOpsClient.ts @@ -189,6 +189,9 @@ export class AzureDevOpsClient implements AzureDevOpsApi { if (opts.org) { queryString.append('org', opts.org); } + if (opts.path) { + queryString.append('path', opts.path); + } return await this.get( `readme/${encodeURIComponent(opts.project)}/${encodeURIComponent( opts.repo, diff --git a/plugins/azure-devops/src/hooks/useReadme.ts b/plugins/azure-devops/src/hooks/useReadme.ts index 348b4219f0..9aa376e0bd 100644 --- a/plugins/azure-devops/src/hooks/useReadme.ts +++ b/plugins/azure-devops/src/hooks/useReadme.ts @@ -30,8 +30,15 @@ export function useReadme(entity: Entity): { const api = useApi(azureDevOpsApiRef); const { value, loading, error } = useAsync(() => { - const { project, repo, host, org } = getAnnotationValuesFromEntity(entity); - return api.getReadme({ project, repo: repo as string, host, org }); + const { project, repo, host, org, readmePath } = + getAnnotationValuesFromEntity(entity); + return api.getReadme({ + project, + repo: repo as string, + host, + org, + path: readmePath, + }); }, [api]); return { diff --git a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts index 7533c473ed..fb38a531e1 100644 --- a/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts +++ b/plugins/azure-devops/src/utils/getAnnotationValuesFromEntity.ts @@ -18,6 +18,7 @@ import { Entity } from '@backstage/catalog-model'; import { AZURE_DEVOPS_PROJECT_ANNOTATION, AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION, + AZURE_DEVOPS_README_ANNOTATION, AZURE_DEVOPS_REPO_ANNOTATION, AZURE_DEVOPS_HOST_ORG_ANNOTATION, } from '@backstage/plugin-azure-devops-common'; @@ -28,6 +29,7 @@ export function getAnnotationValuesFromEntity(entity: Entity): { definition?: string; host?: string; org?: string; + readmePath?: string; } { const hostOrg = getHostOrg(entity.metadata.annotations); const projectRepo = getProjectRepo(entity.metadata.annotations); @@ -35,12 +37,15 @@ export function getAnnotationValuesFromEntity(entity: Entity): { entity.metadata.annotations?.[AZURE_DEVOPS_PROJECT_ANNOTATION]; const definition = entity.metadata.annotations?.[AZURE_DEVOPS_BUILD_DEFINITION_ANNOTATION]; + const readmePath = + entity.metadata.annotations?.[AZURE_DEVOPS_README_ANNOTATION]; if (definition) { if (project) { return { project, definition, + readmePath: readmePath, ...hostOrg, }; } @@ -49,6 +54,7 @@ export function getAnnotationValuesFromEntity(entity: Entity): { project: projectRepo.project, repo: projectRepo.repo, definition, + readmePath: readmePath, ...hostOrg, }; } @@ -60,6 +66,7 @@ export function getAnnotationValuesFromEntity(entity: Entity): { return { project: projectRepo.project, repo: projectRepo.repo, + readmePath: readmePath, ...hostOrg, }; }