diff --git a/.changeset/khaki-singers-film.md b/.changeset/khaki-singers-film.md new file mode 100644 index 0000000000..0dd34f9c49 --- /dev/null +++ b/.changeset/khaki-singers-film.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-azure-devops-backend': patch +'@backstage/plugin-azure-devops-common': patch +'@backstage/plugin-azure-devops': patch +--- + +Added multi-org support diff --git a/plugins/azure-devops-backend/README.md b/plugins/azure-devops-backend/README.md index 6810112bdb..2fe62c90eb 100644 --- a/plugins/azure-devops-backend/README.md +++ b/plugins/azure-devops-backend/README.md @@ -8,7 +8,7 @@ The following sections will help you get the Azure DevOps Backend plugin setup a ### Configuration -The Azure DevOps plugin requires the following YAML to be added to your app-config.yaml: +The Azure DevOps plugin requires the following YAML to be added to your `app-config.yaml`: ```yaml azureDevOps: @@ -23,6 +23,12 @@ Configuration Details: - `AZURE_TOKEN` environment variable must be set to a [Personal Access Token](https://docs.microsoft.com/en-us/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate?view=azure-devops&tabs=preview-page) with read access to both Code and Build - `organization` is your Azure DevOps Services (cloud) Organization name or for Azure DevOps Server (on-premise) this will be your Collection name +#### Multi Organization + +To support cases where you have multiple Azure DevOps organizations you will want to make sure to configure them in the `integrations.azure` section of your `app-config.yaml` as detailed in the [Azure DevOps Locations](https://backstage.io/docs/integrations/azure/locations) documentation. + +**Note:** You will still need to define the [configuration above](#configuration). + ### Up and Running Here's how to get the backend up and running: @@ -112,6 +118,39 @@ The Azure DevOps backend plugin includes the `AzureDevOpsAnnotatorProcessor` whi } ``` +To use this with the New Backend System you'll want to create a [backend module extension for the Catalog](https://backstage.io/docs/backend-system/building-backends/migrating#other-catalog-extensions) if you haven't already. Here's a basic example of this assuming you are only adding the `AzureDevOpsAnnotatorProcessor`, this would go in your `packages/backend/index.ts`: + +```diff + import { createBackend } from '@backstage/backend-defaults'; ++ import { catalogProcessingExtensionPoint } from '@backstage/plugin-catalog-node/alpha'; ++ import { coreServices, createBackendModule } from '@backstage/backend-plugin-api'; ++ import { AzureDevOpsAnnotatorProcessor } from '@backstage/plugin-azure-devops-backend'; + ++ const catalogModuleCustomExtensions = createBackendModule({ ++ pluginId: 'catalog', // name of the plugin that the module is targeting ++ moduleId: 'custom-extensions', ++ register(env) { ++ env.registerInit({ ++ deps: { ++ catalog: catalogProcessingExtensionPoint, ++ config: coreServices.rootConfig, ++ }, ++ async init({ catalog, config }) { ++ catalog.addProcessor(AzureDevOpsAnnotatorProcessor.fromConfig(config)); ++ }, ++ }); ++ }, ++ }); + + const backend = createBackend(); + + // ... other feature additions + ++ backend.add(catalogModuleCustomExtensions()); + + backend.start(); +``` + ## Links - [Frontend part of the plugin](https://github.com/backstage/backstage/tree/master/plugins/azure-devops) diff --git a/plugins/azure-devops-backend/api-report.md b/plugins/azure-devops-backend/api-report.md index ac12f85131..6dead7f11b 100644 --- a/plugins/azure-devops-backend/api-report.md +++ b/plugins/azure-devops-backend/api-report.md @@ -60,12 +60,16 @@ export class AzureDevOpsApi { getBuildDefinitions( projectName: string, definitionName: string, + host?: string, + org?: string, ): Promise; // (undocumented) getBuildList( projectName: string, repoId: string, top: number, + host?: string, + org?: string, ): Promise; // (undocumented) getBuildRuns( @@ -73,6 +77,8 @@ export class AzureDevOpsApi { top: number, repoName?: string, definitionName?: string, + host?: string, + org?: string, ): Promise; // (undocumented) getBuilds( @@ -80,6 +86,8 @@ export class AzureDevOpsApi { top: number, repoId?: string, definitions?: number[], + host?: string, + org?: string, ): Promise; // (undocumented) getDashboardPullRequests( @@ -90,16 +98,25 @@ export class AzureDevOpsApi { getGitRepository( projectName: string, repoName: string, + host?: string, + org?: string, ): Promise; // (undocumented) - getGitTags(projectName: string, repoName: string): Promise; + getGitTags( + projectName: string, + repoName: string, + host?: string, + org?: string, + ): Promise; // (undocumented) - getProjects(): Promise; + getProjects(host?: string, org?: string): Promise; // (undocumented) getPullRequests( projectName: string, repoName: string, options: PullRequestOptions, + host?: string, + org?: string, ): Promise; // (undocumented) getReadme( @@ -116,6 +133,8 @@ export class AzureDevOpsApi { projectName: string, repoName: string, top: number, + host?: string, + org?: string, ): Promise; // (undocumented) getTeamMembers(options: { diff --git a/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts b/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts index 6765b54c05..3900882940 100644 --- a/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts +++ b/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts @@ -130,8 +130,8 @@ export class AzureDevOpsApi { return webApi; } - public async getProjects(): Promise { - const webApi = await this.getWebApi(); + public async getProjects(host?: string, org?: string): Promise { + const webApi = await this.getWebApi(host, org); const client = await webApi.getCoreApi(); const projectList: TeamProjectReference[] = await client.getProjects(); @@ -149,12 +149,14 @@ export class AzureDevOpsApi { public async getGitRepository( projectName: string, repoName: string, + host?: string, + org?: string, ): Promise { this.logger?.debug( `Calling Azure DevOps REST API, getting Repository ${repoName} for Project ${projectName}`, ); - const webApi = await this.getWebApi(); + const webApi = await this.getWebApi(host, org); const client = await webApi.getGitApi(); return client.getRepository(repoName, projectName); } @@ -163,12 +165,14 @@ export class AzureDevOpsApi { projectName: string, repoId: string, top: number, + host?: string, + org?: string, ): Promise { this.logger?.debug( `Calling Azure DevOps REST API, getting up to ${top} Builds for Repository Id ${repoId} for Project ${projectName}`, ); - const webApi = await this.getWebApi(); + const webApi = await this.getWebApi(host, org); const client = await webApi.getBuildApi(); return client.getBuilds( projectName, @@ -199,16 +203,25 @@ export class AzureDevOpsApi { projectName: string, repoName: string, top: number, + host?: string, + org?: string, ) { 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 gitRepository = await this.getGitRepository( + projectName, + repoName, + host, + org, + ); const buildList = await this.getBuildList( projectName, gitRepository.id as string, top, + host, + org, ); const repoBuilds: RepoBuild[] = buildList.map(build => { @@ -221,13 +234,20 @@ export class AzureDevOpsApi { public async getGitTags( projectName: string, repoName: string, + host?: string, + org?: string, ): Promise { this.logger?.debug( `Calling Azure DevOps REST API, getting Git Tags for Repository ${repoName} for Project ${projectName}`, ); - const gitRepository = await this.getGitRepository(projectName, repoName); - const webApi = await this.getWebApi(); + const gitRepository = await this.getGitRepository( + projectName, + repoName, + host, + org, + ); + const webApi = await this.getWebApi(host, org); const client = await webApi.getGitApi(); const tagRefs: GitRef[] = await client.getRefs( gitRepository.id as string, @@ -256,13 +276,20 @@ export class AzureDevOpsApi { projectName: string, repoName: string, options: PullRequestOptions, + host?: string, + org?: string, ): Promise { this.logger?.debug( `Calling Azure DevOps REST API, getting up to ${options.top} Pull Requests for Repository ${repoName} for Project ${projectName}`, ); - const gitRepository = await this.getGitRepository(projectName, repoName); - const webApi = await this.getWebApi(); + const gitRepository = await this.getGitRepository( + projectName, + repoName, + host, + org, + ); + const webApi = await this.getWebApi(host, org); const client = await webApi.getGitApi(); const searchCriteria: GitPullRequestSearchCriteria = { status: options.status, @@ -397,12 +424,14 @@ export class AzureDevOpsApi { public async getBuildDefinitions( projectName: string, definitionName: string, + host?: string, + org?: string, ): Promise { this.logger?.debug( `Calling Azure DevOps REST API, getting Build Definitions for ${definitionName} in Project ${projectName}`, ); - const webApi = await this.getWebApi(); + const webApi = await this.getWebApi(host, org); const client = await webApi.getBuildApi(); return client.getDefinitions(projectName, definitionName); } @@ -412,12 +441,14 @@ export class AzureDevOpsApi { top: number, repoId?: string, definitions?: number[], + host?: string, + org?: string, ): Promise { this.logger?.debug( `Calling Azure DevOps REST API, getting up to ${top} Builds for Repository Id ${repoId} for Project ${projectName}`, ); - const webApi = await this.getWebApi(); + const webApi = await this.getWebApi(host, org); const client = await webApi.getBuildApi(); return client.getBuilds( projectName, @@ -449,12 +480,19 @@ export class AzureDevOpsApi { top: number, repoName?: string, definitionName?: string, + host?: string, + org?: string, ) { let repoId: string | undefined; let definitions: number[] | undefined; if (repoName) { - const gitRepository = await this.getGitRepository(projectName, repoName); + const gitRepository = await this.getGitRepository( + projectName, + repoName, + host, + org, + ); repoId = gitRepository.id; } @@ -462,13 +500,22 @@ export class AzureDevOpsApi { const buildDefinitions = await this.getBuildDefinitions( projectName, definitionName, + host, + org, ); definitions = buildDefinitions .map(bd => bd.id) .filter((bd): bd is number => Boolean(bd)); } - const builds = await this.getBuilds(projectName, top, repoId, definitions); + const builds = await this.getBuilds( + projectName, + top, + repoId, + definitions, + host, + org, + ); const buildRuns: BuildRun[] = builds.map(mappedBuildRun); diff --git a/plugins/azure-devops-backend/src/service/router.test.ts b/plugins/azure-devops-backend/src/service/router.test.ts index a77600feb0..65cb27271e 100644 --- a/plugins/azure-devops-backend/src/service/router.test.ts +++ b/plugins/azure-devops-backend/src/service/router.test.ts @@ -161,6 +161,8 @@ describe('createRouter', () => { 'myProject', 'af4ae3af-e747-4129-9bbc-d1329f6b0998', 40, + undefined, + undefined, ); expect(response.status).toEqual(200); expect(response.body).toEqual(builds); @@ -215,6 +217,8 @@ describe('createRouter', () => { 'myProject', 'myRepo', 50, + undefined, + undefined, ); expect(response.status).toEqual(200); expect(response.body).toEqual(repoBuilds); @@ -252,6 +256,8 @@ describe('createRouter', () => { expect(azureDevOpsApi.getGitTags).toHaveBeenCalledWith( 'myProject', 'myRepo', + undefined, + undefined, ); expect(response.status).toEqual(200); expect(response.body).toEqual(gitTags); @@ -315,6 +321,8 @@ describe('createRouter', () => { 'myProject', 'myRepo', { status: 1, top: 50 }, + undefined, + undefined, ); expect(response.status).toEqual(200); expect(response.body).toEqual(pullRequests); @@ -341,6 +349,8 @@ describe('createRouter', () => { expect(azureDevOpsApi.getBuildDefinitions).toHaveBeenCalledWith( 'myProject', 'myBuildDefinition', + undefined, + undefined, ); expect(response.status).toEqual(200); expect(response.body).toEqual(inputDefinitions); @@ -397,6 +407,8 @@ describe('createRouter', () => { 50, 'myRepo', undefined, + undefined, + undefined, ); expect(response.status).toEqual(200); expect(response.body).toEqual(buildRuns); @@ -452,6 +464,8 @@ describe('createRouter', () => { 50, undefined, 'myDefinition', + undefined, + undefined, ); expect(response.status).toEqual(200); expect(response.body).toEqual(buildRuns); diff --git a/plugins/azure-devops-backend/src/service/router.ts b/plugins/azure-devops-backend/src/service/router.ts index 9fc762f1a7..9a71c8f03d 100644 --- a/plugins/azure-devops-backend/src/service/router.ts +++ b/plugins/azure-devops-backend/src/service/router.ts @@ -75,10 +75,14 @@ export async function createRouter( router.get('/builds/:projectName/:repoId', async (req, res) => { const { projectName, repoId } = req.params; const top = req.query.top ? Number(req.query.top) : DEFAULT_TOP; + const host = req.query.host?.toString(); + const org = req.query.org?.toString(); const buildList = await azureDevOpsApi.getBuildList( projectName, repoId, top, + host, + org, ); res.status(200).json(buildList); }); @@ -87,11 +91,14 @@ export async function createRouter( const { projectName, repoName } = req.params; const top = req.query.top ? Number(req.query.top) : DEFAULT_TOP; - + const host = req.query.host?.toString(); + const org = req.query.org?.toString(); const gitRepository = await azureDevOpsApi.getRepoBuilds( projectName, repoName, top, + host, + org, ); res.status(200).json(gitRepository); @@ -99,7 +106,14 @@ export async function createRouter( router.get('/git-tags/:projectName/:repoName', async (req, res) => { const { projectName, repoName } = req.params; - const gitTags = await azureDevOpsApi.getGitTags(projectName, repoName); + const host = req.query.host?.toString(); + const org = req.query.org?.toString(); + const gitTags = await azureDevOpsApi.getGitTags( + projectName, + repoName, + host, + org, + ); res.status(200).json(gitTags); }); @@ -107,7 +121,8 @@ export async function createRouter( const { projectName, repoName } = req.params; const top = req.query.top ? Number(req.query.top) : DEFAULT_TOP; - + const host = req.query.host?.toString(); + const org = req.query.org?.toString(); const status = req.query.status ? Number(req.query.status) : PullRequestStatus.Active; @@ -121,6 +136,8 @@ export async function createRouter( projectName, repoName, pullRequestOptions, + host, + org, ); res.status(200).json(gitPullRequest); @@ -158,9 +175,13 @@ export async function createRouter( '/build-definitions/:projectName/:definitionName', async (req, res) => { const { projectName, definitionName } = req.params; + const host = req.query.host?.toString(); + const org = req.query.org?.toString(); const buildDefinitionList = await azureDevOpsApi.getBuildDefinitions( projectName, definitionName, + host, + org, ); res.status(200).json(buildDefinitionList); }, @@ -171,11 +192,15 @@ export async function createRouter( const repoName = req.query.repoName?.toString(); const definitionName = req.query.definitionName?.toString(); const top = req.query.top ? Number(req.query.top) : DEFAULT_TOP; + const host = req.query.host?.toString(); + const org = req.query.org?.toString(); const builds = await azureDevOpsApi.getBuildRuns( projectName, top, repoName, definitionName, + host, + org, ); res.status(200).json(builds); }); @@ -187,12 +212,14 @@ export async function createRouter( }); router.get('/readme/:projectName/:repoName', async (req, res) => { - const host = config.getString('azureDevOps.host'); - const organization = config.getString('azureDevOps.organization'); + const host = + req.query.host?.toString() ?? config.getString('azureDevOps.host'); + const org = + req.query.org?.toString() ?? config.getString('azureDevOps.organization'); const { projectName, repoName } = req.params; const readme = await azureDevOpsApi.getReadme( host, - organization, + org, projectName, repoName, ); diff --git a/plugins/azure-devops-common/api-report.md b/plugins/azure-devops-common/api-report.md index 262d5c8136..5bd1674fc8 100644 --- a/plugins/azure-devops-common/api-report.md +++ b/plugins/azure-devops-common/api-report.md @@ -223,6 +223,10 @@ export interface Readme { // @public (undocumented) export interface ReadmeConfig { + // (undocumented) + host?: string; + // (undocumented) + org?: string; // (undocumented) project: string; // (undocumented) diff --git a/plugins/azure-devops-common/src/types.ts b/plugins/azure-devops-common/src/types.ts index 380cb3e585..afb6083867 100644 --- a/plugins/azure-devops-common/src/types.ts +++ b/plugins/azure-devops-common/src/types.ts @@ -210,6 +210,8 @@ export interface Team { export interface ReadmeConfig { project: string; repo: string; + host?: string; + org?: string; } /** @public */ diff --git a/plugins/azure-devops/README.md b/plugins/azure-devops/README.md index 7eeae09813..d7335e54c8 100644 --- a/plugins/azure-devops/README.md +++ b/plugins/azure-devops/README.md @@ -72,6 +72,53 @@ dev.azure.com/build-definition: In this case `` will be the name of your Team Project and `` will be the name of the Build Definition you would like to see Builds for, and it's possible to add more Builds separated by a comma. If the Build Definition name has spaces in it make sure to put quotes around it. +#### Multiple Organizations + +If you have multiple organizations you'll need to also add this annotation: + +```yaml +dev.azure.com/host-org: / +``` + +For this annotation `` will match the `host` value in the `integrations.azure` section in your `app-config.yaml` and `` will be the name of the Organization that is part of the `host`. Let's break this down with an example: + +Say we have the following `integrations.azure` section: + +```yaml +integrations: + azure: + - host: dev.azure.com + credentials: + - organizations: + - my-org + - my-other-org + clientId: ${AZURE_CLIENT_ID} + clientSecret: ${AZURE_CLIENT_SECRET} + tenantId: ${AZURE_TENANT_ID} + - organizations: + - another-org + clientId: ${AZURE_CLIENT_ID} + - host: server.company.com + credentials: + - organizations: + - yet-another-org + personalAccessToken: ${PERSONAL_ACCESS_TOKEN} +``` + +If the entity we are viewing lives in the `my-other-org` organization then the `dev.azure.com/host-org` annotation would look like this: + +```yaml +dev.azure.com/host-org: dev.azure.com/my-other-org +``` + +And if the entity was from `yet-another-org` it would look like this: + +```yaml +dev.azure.com/host-org: server.company.com/yet-another-org +``` + +**Note:** To save you time, effort, and confusion setting up these annotations manually you can use the `AzureDevOpsAnnotatorProcessor` processor which will add the `dev.azure.com/host-org` and `dev.azure.com/project-repo` annotations for you with the correct values. The Azure DevOps backend plugin has details on how to [add this processor](https://github.com/backstage/backstage/tree/master/plugins/azure-devops-backend#processor). + ### Azure Pipelines Component To get the Azure Pipelines component working you'll need to do the following two steps: @@ -247,8 +294,3 @@ To get the README component working you'll need to do the following two steps: - You'll need to add the `EntitySwitch.Case` above from step 2 to all the entity sections you want to see Readme in. For example if you wanted to see Readme when looking at Website entities then you would need to add this to the `websiteEntityPage` section. - The `if` prop is optional on the `EntitySwitch.Case`, you can remove it if you always want to see the tab even if the entity being viewed does not have the needed annotation - The `maxHeight` property on the `EntityAzureReadmeCard` will set the maximum screen size you would like to see, if not set it will default to 100% - -## Limitations - -- Currently multiple organizations are not supported -- Mixing Azure DevOps Services (cloud) and Azure DevOps Server (on-premise) is not supported diff --git a/plugins/azure-devops/api-report.md b/plugins/azure-devops/api-report.md index 6b33762639..38c1eed279 100644 --- a/plugins/azure-devops/api-report.md +++ b/plugins/azure-devops/api-report.md @@ -71,6 +71,8 @@ export interface AzureDevOpsApi { projectName: string, repoName?: string, definitionName?: string, + host?: string, + org?: string, options?: BuildRunOptions, ): Promise<{ items: BuildRun[]; @@ -83,6 +85,8 @@ export interface AzureDevOpsApi { getGitTags( projectName: string, repoName: string, + host?: string, + org?: string, ): Promise<{ items: GitTag[]; }>; @@ -90,6 +94,8 @@ export interface AzureDevOpsApi { getPullRequests( projectName: string, repoName: string, + host?: string, + org?: string, options?: PullRequestOptions, ): Promise<{ items: PullRequest[]; @@ -100,6 +106,8 @@ export interface AzureDevOpsApi { getRepoBuilds( projectName: string, repoName: string, + host?: string, + org?: string, options?: RepoBuildOptions, ): Promise<{ items: RepoBuild[]; @@ -124,6 +132,8 @@ export class AzureDevOpsClient implements AzureDevOpsApi { projectName: string, repoName?: string, definitionName?: string, + host?: string, + org?: string, options?: BuildRunOptions, ): Promise<{ items: BuildRun[]; @@ -136,6 +146,8 @@ export class AzureDevOpsClient implements AzureDevOpsApi { getGitTags( projectName: string, repoName: string, + host?: string, + org?: string, ): Promise<{ items: GitTag[]; }>; @@ -143,6 +155,8 @@ export class AzureDevOpsClient implements AzureDevOpsApi { getPullRequests( projectName: string, repoName: string, + host?: string, + org?: string, options?: PullRequestOptions, ): Promise<{ items: PullRequest[]; @@ -153,6 +167,8 @@ export class AzureDevOpsClient implements AzureDevOpsApi { getRepoBuilds( projectName: string, repoName: string, + host?: string, + org?: string, options?: RepoBuildOptions, ): Promise<{ items: RepoBuild[]; diff --git a/plugins/azure-devops/src/api/AzureDevOpsApi.ts b/plugins/azure-devops/src/api/AzureDevOpsApi.ts index ce6a3cac39..89aa4b7d6e 100644 --- a/plugins/azure-devops/src/api/AzureDevOpsApi.ts +++ b/plugins/azure-devops/src/api/AzureDevOpsApi.ts @@ -40,17 +40,23 @@ export interface AzureDevOpsApi { getRepoBuilds( projectName: string, repoName: string, + host?: string, + org?: string, options?: RepoBuildOptions, ): Promise<{ items: RepoBuild[] }>; getGitTags( projectName: string, repoName: string, + host?: string, + org?: string, ): Promise<{ items: GitTag[] }>; getPullRequests( projectName: string, repoName: string, + host?: string, + org?: string, options?: PullRequestOptions, ): Promise<{ items: PullRequest[] }>; @@ -66,6 +72,8 @@ export interface AzureDevOpsApi { projectName: string, repoName?: string, definitionName?: string, + host?: string, + org?: string, options?: BuildRunOptions, ): Promise<{ items: BuildRun[] }>; diff --git a/plugins/azure-devops/src/api/AzureDevOpsClient.ts b/plugins/azure-devops/src/api/AzureDevOpsClient.ts index a202008798..76e38b064c 100644 --- a/plugins/azure-devops/src/api/AzureDevOpsClient.ts +++ b/plugins/azure-devops/src/api/AzureDevOpsClient.ts @@ -47,12 +47,20 @@ export class AzureDevOpsClient implements AzureDevOpsApi { public async getRepoBuilds( projectName: string, repoName: string, + host?: string, + org?: string, options?: RepoBuildOptions, ): Promise<{ items: RepoBuild[] }> { const queryString = new URLSearchParams(); if (options?.top) { queryString.append('top', options.top.toString()); } + if (host) { + queryString.append('host', host); + } + if (org) { + queryString.append('org', org); + } const urlSegment = `repo-builds/${encodeURIComponent( projectName, )}/${encodeURIComponent(repoName)}?${queryString}`; @@ -64,10 +72,19 @@ export class AzureDevOpsClient implements AzureDevOpsApi { public async getGitTags( projectName: string, repoName: string, + host?: string, + org?: string, ): Promise<{ items: GitTag[] }> { + const queryString = new URLSearchParams(); + if (host) { + queryString.append('host', host); + } + if (org) { + queryString.append('org', org); + } const urlSegment = `git-tags/${encodeURIComponent( projectName, - )}/${encodeURIComponent(repoName)}`; + )}/${encodeURIComponent(repoName)}?${queryString}`; const items = await this.get(urlSegment); return { items }; @@ -76,6 +93,8 @@ export class AzureDevOpsClient implements AzureDevOpsApi { public async getPullRequests( projectName: string, repoName: string, + host?: string, + org?: string, options?: PullRequestOptions, ): Promise<{ items: PullRequest[] }> { const queryString = new URLSearchParams(); @@ -85,6 +104,12 @@ export class AzureDevOpsClient implements AzureDevOpsApi { if (options?.status) { queryString.append('status', options.status.toString()); } + if (host) { + queryString.append('host', host); + } + if (org) { + queryString.append('org', org); + } const urlSegment = `pull-requests/${encodeURIComponent( projectName, )}/${encodeURIComponent(repoName)}?${queryString}`; @@ -113,12 +138,20 @@ export class AzureDevOpsClient implements AzureDevOpsApi { projectName: string, repoName?: string, definitionName?: string, + host?: string, + org?: string, options?: BuildRunOptions, ): Promise<{ items: BuildRun[] }> { const queryString = new URLSearchParams(); if (repoName) { queryString.append('repoName', repoName); } + if (host) { + queryString.append('host', host); + } + if (org) { + queryString.append('org', org); + } if (definitionName) { const definitionNames = definitionName.split(','); if (definitionNames.length > 1) { @@ -149,10 +182,17 @@ export class AzureDevOpsClient implements AzureDevOpsApi { } public async getReadme(opts: ReadmeConfig): Promise { + const queryString = new URLSearchParams(); + if (opts.host) { + queryString.append('host', opts.host); + } + if (opts.org) { + queryString.append('org', opts.org); + } return await this.get( `readme/${encodeURIComponent(opts.project)}/${encodeURIComponent( opts.repo, - )}`, + )}?${queryString}`, ); } diff --git a/plugins/azure-devops/src/hooks/useBuildRuns.ts b/plugins/azure-devops/src/hooks/useBuildRuns.ts index 0c10dc8db8..e335d2ffaf 100644 --- a/plugins/azure-devops/src/hooks/useBuildRuns.ts +++ b/plugins/azure-devops/src/hooks/useBuildRuns.ts @@ -42,8 +42,9 @@ export function useBuildRuns( const api = useApi(azureDevOpsApiRef); const { value, loading, error } = useAsync(() => { - const { project, repo, definition } = getAnnotationValuesFromEntity(entity); - return api.getBuildRuns(project, repo, definition, options); + const { project, repo, definition, host, org } = + getAnnotationValuesFromEntity(entity); + return api.getBuildRuns(project, repo, definition, host, org, options); }, [api]); return { diff --git a/plugins/azure-devops/src/hooks/useGitTags.ts b/plugins/azure-devops/src/hooks/useGitTags.ts index 8a2fb2825d..57489316da 100644 --- a/plugins/azure-devops/src/hooks/useGitTags.ts +++ b/plugins/azure-devops/src/hooks/useGitTags.ts @@ -30,8 +30,8 @@ export function useGitTags(entity: Entity): { const api = useApi(azureDevOpsApiRef); const { value, loading, error } = useAsync(() => { - const { project, repo } = getAnnotationValuesFromEntity(entity); - return api.getGitTags(project, repo as string); + const { project, repo, host, org } = getAnnotationValuesFromEntity(entity); + return api.getGitTags(project, repo as string, host, org); }, [api]); return { diff --git a/plugins/azure-devops/src/hooks/usePullRequests.ts b/plugins/azure-devops/src/hooks/usePullRequests.ts index 1ac6afae24..af2c4b1cc1 100644 --- a/plugins/azure-devops/src/hooks/usePullRequests.ts +++ b/plugins/azure-devops/src/hooks/usePullRequests.ts @@ -46,8 +46,8 @@ export function usePullRequests( const api = useApi(azureDevOpsApiRef); const { value, loading, error } = useAsync(() => { - const { project, repo } = getAnnotationValuesFromEntity(entity); - return api.getPullRequests(project, repo as string, options); + const { project, repo, host, org } = getAnnotationValuesFromEntity(entity); + return api.getPullRequests(project, repo as string, host, org, options); }, [api, top, status]); return { diff --git a/plugins/azure-devops/src/hooks/useReadme.ts b/plugins/azure-devops/src/hooks/useReadme.ts index 67d3c5dfd0..348b4219f0 100644 --- a/plugins/azure-devops/src/hooks/useReadme.ts +++ b/plugins/azure-devops/src/hooks/useReadme.ts @@ -30,8 +30,8 @@ export function useReadme(entity: Entity): { const api = useApi(azureDevOpsApiRef); const { value, loading, error } = useAsync(() => { - const { project, repo } = getAnnotationValuesFromEntity(entity); - return api.getReadme({ project, repo: repo as string }); + const { project, repo, host, org } = getAnnotationValuesFromEntity(entity); + return api.getReadme({ project, repo: repo as string, host, org }); }, [api]); return {