Use AzureDevOpsCredentialsProvider
Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com>
This commit is contained in:
committed by
Andre Wanlin
parent
11a24e8a3a
commit
844969cd97
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/plugin-azure-devops-backend': patch
|
||||
---
|
||||
|
||||
Added support for using `AzureDevOpsCredentialsProvider` and deprecated `azureDevOps.token` configuration value
|
||||
@@ -20,11 +20,10 @@ import { RepoBuild } from '@backstage/plugin-azure-devops-common';
|
||||
import { Team } from '@backstage/plugin-azure-devops-common';
|
||||
import { TeamMember } from '@backstage/plugin-azure-devops-common';
|
||||
import { UrlReader } from '@backstage/backend-common';
|
||||
import { WebApi } from 'azure-devops-node-api';
|
||||
|
||||
// @public (undocumented)
|
||||
export class AzureDevOpsApi {
|
||||
constructor(logger: Logger, webApi: WebApi, urlReader: UrlReader);
|
||||
constructor(logger: Logger, urlReader: UrlReader, config: Config);
|
||||
// (undocumented)
|
||||
getAllTeams(): Promise<Team[]>;
|
||||
// (undocumented)
|
||||
|
||||
+2
@@ -24,6 +24,8 @@ export interface Config {
|
||||
/**
|
||||
* Token used to authenticate requests.
|
||||
* @visibility secret
|
||||
* @deprecated Use `integrations.azure` instead.
|
||||
* @see https://backstage.io/docs/integrations/azure/locations
|
||||
*/
|
||||
token: string;
|
||||
/**
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
"@backstage/backend-common": "workspace:^",
|
||||
"@backstage/backend-plugin-api": "workspace:^",
|
||||
"@backstage/config": "workspace:^",
|
||||
"@backstage/integration": "workspace:^",
|
||||
"@backstage/plugin-azure-devops-common": "workspace:^",
|
||||
"@types/express": "^4.17.6",
|
||||
"azure-devops-node-api": "^11.0.1",
|
||||
|
||||
@@ -49,23 +49,51 @@ import {
|
||||
import { TeamMember as AdoTeamMember } from 'azure-devops-node-api/interfaces/common/VSSInterfaces';
|
||||
import { Logger } from 'winston';
|
||||
import { PolicyEvaluationRecord } from 'azure-devops-node-api/interfaces/PolicyInterfaces';
|
||||
import { WebApi } from 'azure-devops-node-api';
|
||||
import { WebApi, getPersonalAccessTokenHandler } from 'azure-devops-node-api';
|
||||
import {
|
||||
TeamProjectReference,
|
||||
WebApiTeam,
|
||||
} from 'azure-devops-node-api/interfaces/CoreInterfaces';
|
||||
import { UrlReader } from '@backstage/backend-common';
|
||||
import { Config } from '@backstage/config';
|
||||
import {
|
||||
DefaultAzureDevOpsCredentialsProvider,
|
||||
ScmIntegrations,
|
||||
} from '@backstage/integration';
|
||||
|
||||
/** @public */
|
||||
export class AzureDevOpsApi {
|
||||
public constructor(
|
||||
private readonly logger: Logger,
|
||||
private readonly webApi: WebApi,
|
||||
private readonly urlReader: UrlReader,
|
||||
private readonly config: Config,
|
||||
) {}
|
||||
|
||||
private async getWebApi(host?: string, org?: string): Promise<WebApi> {
|
||||
const validHost = host ?? this.config.getString('azureDevOps.host');
|
||||
const validOrg = org ?? this.config.getString('azureDevOps.organization');
|
||||
const scmIntegrations = ScmIntegrations.fromConfig(this.config);
|
||||
const credentialsProvider =
|
||||
DefaultAzureDevOpsCredentialsProvider.fromIntegrations(scmIntegrations);
|
||||
const credentials = await credentialsProvider.getCredentials({
|
||||
url: `https://${validHost}/${validOrg}`,
|
||||
});
|
||||
|
||||
let validToken: string;
|
||||
if (credentials && credentials.token) {
|
||||
validToken = credentials.token;
|
||||
} else {
|
||||
validToken = this.config.getString('azureDevOps.token');
|
||||
}
|
||||
|
||||
const authHandler = getPersonalAccessTokenHandler(validToken);
|
||||
const webApi = new WebApi(`https://${validHost}/${validOrg}`, authHandler);
|
||||
return webApi;
|
||||
}
|
||||
|
||||
public async getProjects(): Promise<Project[]> {
|
||||
const client = await this.webApi.getCoreApi();
|
||||
const webApi = await this.getWebApi();
|
||||
const client = await webApi.getCoreApi();
|
||||
const projectList: TeamProjectReference[] = await client.getProjects();
|
||||
|
||||
const projects: Project[] = projectList.map(project => ({
|
||||
@@ -87,7 +115,8 @@ export class AzureDevOpsApi {
|
||||
`Calling Azure DevOps REST API, getting Repository ${repoName} for Project ${projectName}`,
|
||||
);
|
||||
|
||||
const client = await this.webApi.getGitApi();
|
||||
const webApi = await this.getWebApi();
|
||||
const client = await webApi.getGitApi();
|
||||
return client.getRepository(repoName, projectName);
|
||||
}
|
||||
|
||||
@@ -100,7 +129,8 @@ export class AzureDevOpsApi {
|
||||
`Calling Azure DevOps REST API, getting up to ${top} Builds for Repository Id ${repoId} for Project ${projectName}`,
|
||||
);
|
||||
|
||||
const client = await this.webApi.getBuildApi();
|
||||
const webApi = await this.getWebApi();
|
||||
const client = await webApi.getBuildApi();
|
||||
return client.getBuilds(
|
||||
projectName,
|
||||
undefined,
|
||||
@@ -158,7 +188,8 @@ export class AzureDevOpsApi {
|
||||
);
|
||||
|
||||
const gitRepository = await this.getGitRepository(projectName, repoName);
|
||||
const client = await this.webApi.getGitApi();
|
||||
const webApi = await this.getWebApi();
|
||||
const client = await webApi.getGitApi();
|
||||
const tagRefs: GitRef[] = await client.getRefs(
|
||||
gitRepository.id as string,
|
||||
projectName,
|
||||
@@ -169,10 +200,10 @@ export class AzureDevOpsApi {
|
||||
false,
|
||||
true,
|
||||
);
|
||||
const linkBaseUrl = `${this.webApi.serverUrl}/${encodeURIComponent(
|
||||
const linkBaseUrl = `${webApi.serverUrl}/${encodeURIComponent(
|
||||
projectName,
|
||||
)}/_git/${encodeURIComponent(repoName)}?version=GT`;
|
||||
const commitBaseUrl = `${this.webApi.serverUrl}/${encodeURIComponent(
|
||||
const commitBaseUrl = `${webApi.serverUrl}/${encodeURIComponent(
|
||||
projectName,
|
||||
)}/_git/${encodeURIComponent(repoName)}/commit`;
|
||||
const gitTags: GitTag[] = tagRefs.map(tagRef => {
|
||||
@@ -192,7 +223,8 @@ export class AzureDevOpsApi {
|
||||
);
|
||||
|
||||
const gitRepository = await this.getGitRepository(projectName, repoName);
|
||||
const client = await this.webApi.getGitApi();
|
||||
const webApi = await this.getWebApi();
|
||||
const client = await webApi.getGitApi();
|
||||
const searchCriteria: GitPullRequestSearchCriteria = {
|
||||
status: options.status,
|
||||
};
|
||||
@@ -204,7 +236,7 @@ export class AzureDevOpsApi {
|
||||
undefined,
|
||||
options.top,
|
||||
);
|
||||
const linkBaseUrl = `${this.webApi.serverUrl}/${encodeURIComponent(
|
||||
const linkBaseUrl = `${webApi.serverUrl}/${encodeURIComponent(
|
||||
projectName,
|
||||
)}/_git/${encodeURIComponent(repoName)}/pullrequest`;
|
||||
const pullRequests: PullRequest[] = gitPullRequests.map(gitPullRequest => {
|
||||
@@ -222,7 +254,8 @@ export class AzureDevOpsApi {
|
||||
`Getting dashboard pull requests for project '${projectName}'.`,
|
||||
);
|
||||
|
||||
const client = await this.webApi.getGitApi();
|
||||
const webApi = await this.getWebApi();
|
||||
const client = await webApi.getGitApi();
|
||||
|
||||
const searchCriteria: GitPullRequestSearchCriteria = {
|
||||
status: options.status,
|
||||
@@ -254,7 +287,7 @@ export class AzureDevOpsApi {
|
||||
|
||||
return convertDashboardPullRequest(
|
||||
gitPullRequest,
|
||||
this.webApi.serverUrl,
|
||||
webApi.serverUrl,
|
||||
policies,
|
||||
);
|
||||
}),
|
||||
@@ -270,7 +303,8 @@ export class AzureDevOpsApi {
|
||||
`Getting pull request policies for pull request id '${pullRequestId}'.`,
|
||||
);
|
||||
|
||||
const client = await this.webApi.getPolicyApi();
|
||||
const webApi = await this.getWebApi();
|
||||
const client = await webApi.getPolicyApi();
|
||||
|
||||
const artifactId = getArtifactId(projectId, pullRequestId);
|
||||
|
||||
@@ -285,7 +319,8 @@ export class AzureDevOpsApi {
|
||||
public async getAllTeams(): Promise<Team[]> {
|
||||
this.logger?.debug('Getting all teams.');
|
||||
|
||||
const client = await this.webApi.getCoreApi();
|
||||
const webApi = await this.getWebApi();
|
||||
const client = await webApi.getCoreApi();
|
||||
const webApiTeams: WebApiTeam[] = await client.getAllTeams();
|
||||
|
||||
const teams: Team[] = webApiTeams.map(team => ({
|
||||
@@ -307,7 +342,8 @@ export class AzureDevOpsApi {
|
||||
const { projectId, teamId } = options;
|
||||
this.logger?.debug(`Getting team member ids for team '${teamId}'.`);
|
||||
|
||||
const client = await this.webApi.getCoreApi();
|
||||
const webApi = await this.getWebApi();
|
||||
const client = await webApi.getCoreApi();
|
||||
|
||||
const teamMembers: AdoTeamMember[] =
|
||||
await client.getTeamMembersWithExtendedProperties(projectId, teamId);
|
||||
@@ -327,7 +363,8 @@ export class AzureDevOpsApi {
|
||||
`Calling Azure DevOps REST API, getting Build Definitions for ${definitionName} in Project ${projectName}`,
|
||||
);
|
||||
|
||||
const client = await this.webApi.getBuildApi();
|
||||
const webApi = await this.getWebApi();
|
||||
const client = await webApi.getBuildApi();
|
||||
return client.getDefinitions(projectName, definitionName);
|
||||
}
|
||||
|
||||
@@ -341,7 +378,8 @@ export class AzureDevOpsApi {
|
||||
`Calling Azure DevOps REST API, getting up to ${top} Builds for Repository Id ${repoId} for Project ${projectName}`,
|
||||
);
|
||||
|
||||
const client = await this.webApi.getBuildApi();
|
||||
const webApi = await this.getWebApi();
|
||||
const client = await webApi.getBuildApi();
|
||||
return client.getBuilds(
|
||||
projectName,
|
||||
definitions,
|
||||
|
||||
@@ -19,7 +19,6 @@ import {
|
||||
PullRequestOptions,
|
||||
PullRequestStatus,
|
||||
} from '@backstage/plugin-azure-devops-common';
|
||||
import { WebApi, getPersonalAccessTokenHandler } from 'azure-devops-node-api';
|
||||
|
||||
import { AzureDevOpsApi } from '../api';
|
||||
import { Config } from '@backstage/config';
|
||||
@@ -43,18 +42,10 @@ export interface RouterOptions {
|
||||
export async function createRouter(
|
||||
options: RouterOptions,
|
||||
): Promise<express.Router> {
|
||||
const { logger, reader } = options;
|
||||
const config = options.config.getConfig('azureDevOps');
|
||||
|
||||
const token = config.getString('token');
|
||||
const host = config.getString('host');
|
||||
const organization = config.getString('organization');
|
||||
|
||||
const authHandler = getPersonalAccessTokenHandler(token);
|
||||
const webApi = new WebApi(`https://${host}/${organization}`, authHandler);
|
||||
const { logger, reader, config } = options;
|
||||
|
||||
const azureDevOpsApi =
|
||||
options.azureDevOpsApi || new AzureDevOpsApi(logger, webApi, reader);
|
||||
options.azureDevOpsApi || new AzureDevOpsApi(logger, reader, config);
|
||||
|
||||
const pullRequestsDashboardProvider =
|
||||
await PullRequestsDashboardProvider.create(logger, azureDevOpsApi);
|
||||
@@ -195,6 +186,8 @@ 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 { projectName, repoName } = req.params;
|
||||
const readme = await azureDevOpsApi.getReadme(
|
||||
host,
|
||||
|
||||
@@ -5077,6 +5077,7 @@ __metadata:
|
||||
"@backstage/backend-plugin-api": "workspace:^"
|
||||
"@backstage/cli": "workspace:^"
|
||||
"@backstage/config": "workspace:^"
|
||||
"@backstage/integration": "workspace:^"
|
||||
"@backstage/plugin-azure-devops-common": "workspace:^"
|
||||
"@types/express": ^4.17.6
|
||||
"@types/supertest": ^2.0.8
|
||||
|
||||
Reference in New Issue
Block a user