From 26904a75ebbf0cfdabcfd4e197568430caeba761 Mon Sep 17 00:00:00 2001 From: Rhys Koedijk Date: Sun, 10 Nov 2024 18:55:54 +1300 Subject: [PATCH] Only log debug messages when the task is actually in debug mode; Add more debug messages to DevOps client to better diagnose failed API calls --- extension/tasks/dependabotV2/index.ts | 5 ++- .../azure-devops/AzureDevOpsWebApiClient.ts | 35 +++++++++++-------- .../utils/dependabot-cli/DependabotCli.ts | 2 +- .../DependabotOutputProcessor.ts | 17 +++++---- 4 files changed, 37 insertions(+), 22 deletions(-) diff --git a/extension/tasks/dependabotV2/index.ts b/extension/tasks/dependabotV2/index.ts index 6df91cf1..358ee44b 100644 --- a/extension/tasks/dependabotV2/index.ts +++ b/extension/tasks/dependabotV2/index.ts @@ -56,11 +56,13 @@ async function run() { const prAuthorClient = new AzureDevOpsWebApiClient( taskInputs.organizationUrl.toString(), taskInputs.systemAccessToken, + taskInputs.debug, ); const prApproverClient = taskInputs.autoApprove ? new AzureDevOpsWebApiClient( taskInputs.organizationUrl.toString(), taskInputs.autoApproveUserToken || taskInputs.systemAccessToken, + taskInputs.debug, ) : null; @@ -79,8 +81,9 @@ async function run() { taskInputs, prAuthorClient, prApproverClient, - existingPullRequests, existingBranchNames, + existingPullRequests, + taskInputs.debug, ), taskInputs.debug, ); diff --git a/extension/tasks/dependabotV2/utils/azure-devops/AzureDevOpsWebApiClient.ts b/extension/tasks/dependabotV2/utils/azure-devops/AzureDevOpsWebApiClient.ts index c9cf2de9..0028cf8c 100644 --- a/extension/tasks/dependabotV2/utils/azure-devops/AzureDevOpsWebApiClient.ts +++ b/extension/tasks/dependabotV2/utils/azure-devops/AzureDevOpsWebApiClient.ts @@ -23,18 +23,19 @@ import { export class AzureDevOpsWebApiClient { private readonly organisationApiUrl: string; private readonly identityApiUrl: string; - private readonly accessToken: string; private readonly connection: WebApi; + private readonly debug: boolean; + private authenticatedUserId: string; private resolvedUserIds: Record; public static API_VERSION = '5.0'; // this is the same version used by dependabot-core - constructor(organisationApiUrl: string, accessToken: string) { + constructor(organisationApiUrl: string, accessToken: string, debug: boolean = false) { this.organisationApiUrl = organisationApiUrl.replace(/\/$/, ''); // trim trailing slash this.identityApiUrl = getIdentityApiUrl(organisationApiUrl).replace(/\/$/, ''); // trim trailing slash - this.accessToken = accessToken; this.connection = new WebApi(organisationApiUrl, getPersonalAccessTokenHandler(accessToken)); + this.debug = debug; this.resolvedUserIds = {}; } @@ -628,7 +629,7 @@ export class AzureDevOpsWebApiClient { .map((key) => `${key}=${params[key]}`) .join('&'); const fullUrl = `${url}?api-version=${apiVersion}${queryString ? `&${queryString}` : ''}`; - return await this.restApiRequest('GET', fullUrl, () => + return await this.restApiRequest('GET', fullUrl, undefined, () => this.connection.rest.client.get(fullUrl, { Accept: 'application/json', }), @@ -641,7 +642,7 @@ export class AzureDevOpsWebApiClient { apiVersion: string = AzureDevOpsWebApiClient.API_VERSION, ): Promise { const fullUrl = `${url}?api-version=${apiVersion}`; - return await this.restApiRequest('POST', fullUrl, () => + return await this.restApiRequest('POST', fullUrl, data, () => this.connection.rest.client.post(fullUrl, JSON.stringify(data), { 'Content-Type': 'application/json', }), @@ -654,7 +655,7 @@ export class AzureDevOpsWebApiClient { apiVersion: string = AzureDevOpsWebApiClient.API_VERSION, ): Promise { const fullUrl = `${url}?api-version=${apiVersion}`; - return await this.restApiRequest('PUT', fullUrl, () => + return await this.restApiRequest('PUT', fullUrl, data, () => this.connection.rest.client.put(fullUrl, JSON.stringify(data), { 'Content-Type': 'application/json', }), @@ -668,7 +669,7 @@ export class AzureDevOpsWebApiClient { apiVersion: string = AzureDevOpsWebApiClient.API_VERSION, ): Promise { const fullUrl = `${url}?api-version=${apiVersion}`; - return await this.restApiRequest('PATCH', fullUrl, () => + return await this.restApiRequest('PATCH', fullUrl, data, () => this.connection.rest.client.patch(fullUrl, JSON.stringify(data), { 'Content-Type': contentType || 'application/json', }), @@ -678,20 +679,26 @@ export class AzureDevOpsWebApiClient { private async restApiRequest( method: string, url: string, - request: () => Promise, + payload: any, + requestAsync: () => Promise, ): Promise { - console.debug(`🌎 🠊 [${method}] ${url}`); - const response = await request(); + if (this.debug) console.debug(`🌎 🠊 [${method}] ${url}`); + const response = await requestAsync(); const body = await response.readBody(); - console.debug(`🌎 🠈 [${response.message.statusCode}] ${response.message.statusMessage}`); + if (this.debug) console.debug(`🌎 🠈 [${response.message.statusCode}] ${response.message.statusMessage}`); try { if (response.message.statusCode < 200 || response.message.statusCode > 299) { - throw new Error(`Request to '${url}' failed: ${response.message.statusCode} ${response.message.statusMessage}`); + throw new Error( + `HTTP ${method} '${url}' failed: ${response.message.statusCode} ${response.message.statusMessage}`, + ); } return JSON.parse(body); } catch (e) { - if (body) { - console.debug(body); + if (this.debug) { + // Log the error, request, and response for debugging purposes + if (e) console.debug('ERROR:', e); + if (payload) console.debug('REQUEST:', payload); + if (body) console.debug('RESPONSE:', body); } throw e; } diff --git a/extension/tasks/dependabotV2/utils/dependabot-cli/DependabotCli.ts b/extension/tasks/dependabotV2/utils/dependabot-cli/DependabotCli.ts index 32a10c65..b884a9fe 100644 --- a/extension/tasks/dependabotV2/utils/dependabot-cli/DependabotCli.ts +++ b/extension/tasks/dependabotV2/utils/dependabot-cli/DependabotCli.ts @@ -23,7 +23,7 @@ export class DependabotCli { public static readonly CLI_IMAGE_LATEST = 'github.com/dependabot/cli/cmd/dependabot@latest'; - constructor(cliToolImage: string, outputProcessor: IDependabotUpdateOutputProcessor, debug: boolean) { + constructor(cliToolImage: string, outputProcessor: IDependabotUpdateOutputProcessor, debug: boolean = false) { this.jobsPath = path.join(os.tmpdir(), 'dependabot-jobs'); this.toolImage = cliToolImage; this.outputProcessor = outputProcessor; diff --git a/extension/tasks/dependabotV2/utils/dependabot-cli/DependabotOutputProcessor.ts b/extension/tasks/dependabotV2/utils/dependabot-cli/DependabotOutputProcessor.ts index 5b97a563..a2fc96aa 100644 --- a/extension/tasks/dependabotV2/utils/dependabot-cli/DependabotOutputProcessor.ts +++ b/extension/tasks/dependabotV2/utils/dependabot-cli/DependabotOutputProcessor.ts @@ -16,9 +16,10 @@ import { IDependabotUpdateOutputProcessor } from './interfaces/IDependabotUpdate export class DependabotOutputProcessor implements IDependabotUpdateOutputProcessor { private readonly prAuthorClient: AzureDevOpsWebApiClient; private readonly prApproverClient: AzureDevOpsWebApiClient; - private readonly existingPullRequests: IPullRequestProperties[]; private readonly existingBranchNames: string[]; + private readonly existingPullRequests: IPullRequestProperties[]; private readonly taskInputs: ISharedVariables; + private readonly debug: boolean; // Custom properties used to store dependabot metadata in projects. // https://learn.microsoft.com/en-us/rest/api/azure/devops/core/projects/set-project-properties @@ -36,14 +37,16 @@ export class DependabotOutputProcessor implements IDependabotUpdateOutputProcess taskInputs: ISharedVariables, prAuthorClient: AzureDevOpsWebApiClient, prApproverClient: AzureDevOpsWebApiClient, - existingPullRequests: IPullRequestProperties[], existingBranchNames: string[], + existingPullRequests: IPullRequestProperties[], + debug: boolean = false, ) { this.taskInputs = taskInputs; this.prAuthorClient = prAuthorClient; this.prApproverClient = prApproverClient; - this.existingPullRequests = existingPullRequests; this.existingBranchNames = existingBranchNames; + this.existingPullRequests = existingPullRequests; + this.debug = debug; } /** @@ -54,10 +57,13 @@ export class DependabotOutputProcessor implements IDependabotUpdateOutputProcess * @returns */ public async process(update: IDependabotUpdateOperation, type: string, data: any): Promise { - section(`Processing '${type}'`); - console.debug('Data:', data); const project = this.taskInputs.project; const repository = this.taskInputs.repository; + + section(`Processing '${type}'`); + if (this.debug) { + console.debug(data); + } switch (type) { // Documentation on the 'data' model for each output type can be found here: // See: https://github.com/dependabot/cli/blob/main/internal/model/update.go @@ -65,7 +71,6 @@ export class DependabotOutputProcessor implements IDependabotUpdateOutputProcess case 'update_dependency_list': // Store the dependency list snapshot in project properties, if configured if (this.taskInputs.storeDependencyList) { - console.info(`Updating the dependency list snapshot for project '${project}'...`); return await this.prAuthorClient.updateProjectProperty( this.taskInputs.projectId, DependabotOutputProcessor.PROJECT_PROPERTY_NAME_DEPENDENCY_LIST,