diff --git a/packages/code-analyzer-apexguru-engine/src/config.ts b/packages/code-analyzer-apexguru-engine/src/config.ts index a51216bc..f2bc0eeb 100644 --- a/packages/code-analyzer-apexguru-engine/src/config.ts +++ b/packages/code-analyzer-apexguru-engine/src/config.ts @@ -13,7 +13,7 @@ export type ApexGuruEngineConfig = { /** * Maximum time to wait for ApexGuru API response (in milliseconds) - * Default: 300000 (5 minutes) + * Default: 600000 (10 minutes) */ api_timeout_ms: number; @@ -42,7 +42,7 @@ export type ApexGuruEngineConfig = { * Default configuration values */ export const DEFAULT_APEXGURU_ENGINE_CONFIG: ApexGuruEngineConfig = { - api_timeout_ms: 300000, // 5 minutes + api_timeout_ms: 600000, // 10 minutes api_initial_retry_ms: 2000, // 2 seconds api_max_retry_ms: 60000, // 60 seconds api_backoff_multiplier: 2 // 2x exponential backoff @@ -60,9 +60,9 @@ export const APEXGURU_ENGINE_CONFIG_DESCRIPTION: ConfigDescription = { defaultValue: null }, api_timeout_ms: { - descriptionText: 'Maximum time to wait for ApexGuru API response (in milliseconds). Default: 300000 (5 minutes)', + descriptionText: 'Maximum time to wait for ApexGuru API response (in milliseconds). Default: 600000 (10 minutes)', valueType: 'number', - defaultValue: 300000 + defaultValue: 600000 }, api_initial_retry_ms: { descriptionText: 'Initial retry delay for polling ApexGuru API (in milliseconds). Default: 2000 (2 seconds)', diff --git a/packages/code-analyzer-apexguru-engine/src/engine.ts b/packages/code-analyzer-apexguru-engine/src/engine.ts index 085737bc..7bad51a5 100644 --- a/packages/code-analyzer-apexguru-engine/src/engine.ts +++ b/packages/code-analyzer-apexguru-engine/src/engine.ts @@ -96,7 +96,7 @@ export class ApexGuruEngine extends EngineEventEmitter implements Engine { this.apexGuruService.cleanup(); if (this.isInvalidSessionError(error)) { return this.skipWithError('INVALID_SESSION', - 'ApexGuru skipped the scan because your org session is invalid or expired. (401 Unauthorized: invalid session).\n' + + 'Code Analyzer skipped ApexGuru scan because your org session is invalid or expired. (401 Unauthorized: invalid session).\n' + 'Re-authenticate: sf org login web\n' + 'Then run the scan again.', ''); @@ -204,7 +204,8 @@ export class ApexGuruEngine extends EngineEventEmitter implements Engine { const detail = error instanceof Error ? error.message : String(error); if (this.isScanTimeoutError(error)) { return this.skipWithError('SCAN_TIMEOUT', - `Code Analyzer skipped ApexGuru scan because the workspace scan timed out after ${this.config.api_timeout_ms} ms.`, + `Code Analyzer skipped ApexGuru scan because the workspace scan timed out after ${formatSeconds(this.config.api_timeout_ms)}. ` + + 'Increase the timeout setting in the Code Analyzer configuration file.', ''); } if (this.isApiUnavailableError(error)) { @@ -288,6 +289,14 @@ export class ApexGuruEngine extends EngineEventEmitter implements Engine { } } + +function formatSeconds(ms: number): string { + const seconds = ms / 1000; + // Drop the trailing ".0" for whole numbers, keep up to 1 decimal otherwise. + const rounded = Number.isInteger(seconds) ? seconds : Math.round(seconds * 10) / 10; + return `${rounded} ${rounded === 1 ? 'second' : 'seconds'}`; +} + /** * Convert ApexGuru violation to Code Analyzer violation format * diff --git a/packages/code-analyzer-apexguru-engine/src/services/ApexGuruAuthService.ts b/packages/code-analyzer-apexguru-engine/src/services/ApexGuruAuthService.ts index f695e64c..fe9c4433 100644 --- a/packages/code-analyzer-apexguru-engine/src/services/ApexGuruAuthService.ts +++ b/packages/code-analyzer-apexguru-engine/src/services/ApexGuruAuthService.ts @@ -42,10 +42,9 @@ export class ApexGuruAuthService { const errorMessage = err instanceof Error ? err.message : String(err); this.emitLogEvent(LogLevel.Fine, `Failed to authenticate with org '${config.targetOrg}': ${errorMessage}`); throw new Error( - `Failed to authenticate with org '${config.targetOrg}'. ` + - 'Please verify the org alias/username and ensure you are authenticated:\n' + - ' sf org list\n' + - ' sf org login web' + `We couldn't find the org '${config.targetOrg}', or it isn't authenticated.\n\n` + + `Run sf org list to see available orgs.\n` + + `Run sf org login web --alias ${config.targetOrg} to authenticate a new org.` ); } } diff --git a/packages/code-analyzer-apexguru-engine/src/services/ApexGuruService.ts b/packages/code-analyzer-apexguru-engine/src/services/ApexGuruService.ts index cdda1abf..6db89f9b 100644 --- a/packages/code-analyzer-apexguru-engine/src/services/ApexGuruService.ts +++ b/packages/code-analyzer-apexguru-engine/src/services/ApexGuruService.ts @@ -360,8 +360,8 @@ function formatHttpError(status: number, body: string): string { const statusText = STATUS_TEXT[status] ?? 'Error'; const detail = summarizeErrorBody(body); return detail - ? `SFAP API returned ${status} ${statusText}: ${detail}` - : `SFAP API returned ${status} ${statusText}`; + ? `${status} ${statusText}: ${detail}` + : `${status} ${statusText}`; } const STATUS_TEXT: Record = { diff --git a/packages/code-analyzer-apexguru-engine/test/ApexGuruAuthService.test.ts b/packages/code-analyzer-apexguru-engine/test/ApexGuruAuthService.test.ts index 2fee6f79..d9a76c56 100644 --- a/packages/code-analyzer-apexguru-engine/test/ApexGuruAuthService.test.ts +++ b/packages/code-analyzer-apexguru-engine/test/ApexGuruAuthService.test.ts @@ -46,7 +46,7 @@ describe('ApexGuruAuthService', () => { await expect(authService.initialize({ targetOrg: 'invalid-org' })) .rejects - .toThrow("Failed to authenticate with org 'invalid-org'"); + .toThrow("We couldn't find the org 'invalid-org', or it isn't authenticated."); }); it('should initialize with default org when no targetOrg provided', async () => { diff --git a/packages/code-analyzer-apexguru-engine/test/ApexGuruEngine.test.ts b/packages/code-analyzer-apexguru-engine/test/ApexGuruEngine.test.ts index 66d52b71..bd9512ce 100644 --- a/packages/code-analyzer-apexguru-engine/test/ApexGuruEngine.test.ts +++ b/packages/code-analyzer-apexguru-engine/test/ApexGuruEngine.test.ts @@ -229,7 +229,7 @@ describe('ApexGuruEngine', () => { status: 'skipped', error: { code: 'INVALID_SESSION', - message: 'ApexGuru skipped the scan because your org session is invalid or expired. (401 Unauthorized: invalid session).\n' + + message: 'Code Analyzer skipped ApexGuru scan because your org session is invalid or expired. (401 Unauthorized: invalid session).\n' + 'Re-authenticate: sf org login web\n' + 'Then run the scan again.', remediation: '' @@ -299,11 +299,12 @@ describe('ApexGuruEngine', () => { status: 'skipped', error: { code: 'SCAN_TIMEOUT', - message: 'Code Analyzer skipped ApexGuru scan because the workspace scan timed out after 300000 ms.', + message: 'Code Analyzer skipped ApexGuru scan because the workspace scan timed out after 600 seconds. ' + + 'Increase the timeout setting in the Code Analyzer configuration file.', remediation: '' } }); - expect(logSpy).toHaveBeenCalledWith(LogLevel.Warn, expect.stringContaining('workspace scan timed out after 300000 ms')); + expect(logSpy).toHaveBeenCalledWith(LogLevel.Warn, expect.stringContaining('workspace scan timed out after 600 seconds')); expect(mockApexGuruService.cleanup).toHaveBeenCalled(); });