Added multi-org support

Signed-off-by: Andre Wanlin <awanlin@spotify.com>
This commit is contained in:
Andre Wanlin
2023-11-27 18:35:41 -06:00
parent df4a219c52
commit c70e4f52eb
13 changed files with 202 additions and 31 deletions
+7
View File
@@ -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
+21 -2
View File
@@ -60,12 +60,16 @@ export class AzureDevOpsApi {
getBuildDefinitions(
projectName: string,
definitionName: string,
host?: string,
org?: string,
): Promise<BuildDefinitionReference[]>;
// (undocumented)
getBuildList(
projectName: string,
repoId: string,
top: number,
host?: string,
org?: string,
): Promise<Build[]>;
// (undocumented)
getBuildRuns(
@@ -73,6 +77,8 @@ export class AzureDevOpsApi {
top: number,
repoName?: string,
definitionName?: string,
host?: string,
org?: string,
): Promise<BuildRun[]>;
// (undocumented)
getBuilds(
@@ -80,6 +86,8 @@ export class AzureDevOpsApi {
top: number,
repoId?: string,
definitions?: number[],
host?: string,
org?: string,
): Promise<Build[]>;
// (undocumented)
getDashboardPullRequests(
@@ -90,16 +98,25 @@ export class AzureDevOpsApi {
getGitRepository(
projectName: string,
repoName: string,
host?: string,
org?: string,
): Promise<GitRepository>;
// (undocumented)
getGitTags(projectName: string, repoName: string): Promise<GitTag[]>;
getGitTags(
projectName: string,
repoName: string,
host?: string,
org?: string,
): Promise<GitTag[]>;
// (undocumented)
getProjects(): Promise<Project[]>;
getProjects(host?: string, org?: string): Promise<Project[]>;
// (undocumented)
getPullRequests(
projectName: string,
repoName: string,
options: PullRequestOptions,
host?: string,
org?: string,
): Promise<PullRequest[]>;
// (undocumented)
getReadme(
@@ -116,6 +133,8 @@ export class AzureDevOpsApi {
projectName: string,
repoName: string,
top: number,
host?: string,
org?: string,
): Promise<RepoBuild[]>;
// (undocumented)
getTeamMembers(options: {
@@ -130,8 +130,8 @@ export class AzureDevOpsApi {
return webApi;
}
public async getProjects(): Promise<Project[]> {
const webApi = await this.getWebApi();
public async getProjects(host?: string, org?: string): Promise<Project[]> {
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<GitRepository> {
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<Build[]> {
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<GitTag[]> {
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<PullRequest[]> {
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<BuildDefinitionReference[]> {
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<Build[]> {
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);
@@ -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,
);
@@ -223,6 +223,10 @@ export interface Readme {
// @public (undocumented)
export interface ReadmeConfig {
// (undocumented)
host?: string;
// (undocumented)
org?: string;
// (undocumented)
project: string;
// (undocumented)
+2
View File
@@ -210,6 +210,8 @@ export interface Team {
export interface ReadmeConfig {
project: string;
repo: string;
host?: string;
org?: string;
}
/** @public */
+16
View File
@@ -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[];
@@ -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[] }>;
@@ -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<GitTag[]>(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<Readme> {
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}`,
);
}
@@ -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 {
+2 -2
View File
@@ -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 {
@@ -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 {
+2 -2
View File
@@ -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 {