From 8a0edf7292c687473493deef6702a7400b649c5e Mon Sep 17 00:00:00 2001 From: Jesse Turner Date: Tue, 28 Apr 2026 19:14:36 +0000 Subject: [PATCH 1/2] fix(e2e): add debug logging for gateway import failures Print the import log file and CloudFormation stack events when the gateway import test fails to help diagnose IMPORT_ROLLBACK_IN_PROGRESS errors in CI. Confidence: high Scope-risk: narrow --- e2e-tests/import-gateway.test.ts | 33 ++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/e2e-tests/import-gateway.test.ts b/e2e-tests/import-gateway.test.ts index 91522e592..4533f1cc4 100644 --- a/e2e-tests/import-gateway.test.ts +++ b/e2e-tests/import-gateway.test.ts @@ -100,6 +100,39 @@ describe.sequential('e2e: import gateway', () => { if (result.exitCode !== 0) { console.log('Import gateway stdout:', result.stdout); console.log('Import gateway stderr:', result.stderr); + + // Print the import log file for debugging CI failures + const logMatch = /Log: (.+)/.exec(result.stderr); + if (logMatch) { + const logPath = join(projectPath, logMatch[1]!); + try { + const logContents = await readFile(logPath, 'utf-8'); + console.log('Import gateway log:\n', logContents); + } catch { + console.log('Could not read log file:', logPath); + } + } + + // Print CloudFormation stack events for the failed import + const cfnEvents = await spawnAndCollect( + 'aws', + [ + 'cloudformation', + 'describe-stack-events', + '--stack-name', + `AgentCore-${agentName}-default`, + '--query', + 'StackEvents[?ResourceStatus==`IMPORT_FAILED` || ResourceStatus==`IMPORT_ROLLBACK_IN_PROGRESS`]', + '--output', + 'json', + '--region', + region, + ], + projectPath + ); + if (cfnEvents.exitCode === 0) { + console.log('CloudFormation failed events:', cfnEvents.stdout); + } } expect(result.exitCode, `Import gateway failed: ${result.stderr}`).toBe(0); From d8eae1ca95018f50459e34b97cccae3ce1207151 Mon Sep 17 00:00:00 2001 From: Jesse Turner Date: Tue, 28 Apr 2026 19:23:32 +0000 Subject: [PATCH 2/2] fix(e2e): add shared debug logging for all import test failures Add dumpImportDebugInfo to e2e-helper that prints the import log file and CloudFormation stack events when an import fails. Used by both import-resources and import-gateway tests to diagnose CI failures. Confidence: high Scope-risk: narrow --- e2e-tests/e2e-helper.ts | 43 +++++++++++++++++++++++++++++- e2e-tests/import-gateway.test.ts | 39 +++------------------------ e2e-tests/import-resources.test.ts | 12 ++++----- 3 files changed, 50 insertions(+), 44 deletions(-) diff --git a/e2e-tests/e2e-helper.ts b/e2e-tests/e2e-helper.ts index 5e3d30b39..e0f6a51cc 100644 --- a/e2e-tests/e2e-helper.ts +++ b/e2e-tests/e2e-helper.ts @@ -14,7 +14,7 @@ import { } from '@aws-sdk/client-bedrock-agentcore-control'; import { execSync } from 'node:child_process'; import { randomUUID } from 'node:crypto'; -import { mkdir, rm, writeFile } from 'node:fs/promises'; +import { mkdir, readFile, rm, writeFile } from 'node:fs/promises'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { afterAll, beforeAll, describe, expect, it } from 'vitest'; @@ -377,3 +377,44 @@ export async function teardownE2EProject(projectPath: string, agentName: string, await deleteCredentialProvider(client, `${agentName}${modelProvider}`); } } + +export async function dumpImportDebugInfo( + label: string, + result: RunResult, + projectPath: string, + stackName: string, + region: string +): Promise { + console.log(`Import ${label} stdout:`, result.stdout); + console.log(`Import ${label} stderr:`, result.stderr); + + const logMatch = /Log: (.+)/.exec(result.stderr); + if (logMatch) { + try { + const logContents = await readFile(join(projectPath, logMatch[1]!), 'utf-8'); + console.log(`Import ${label} log:\n`, logContents); + } catch { + /* log file may not exist */ + } + } + + const cfnEvents = await spawnAndCollect( + 'aws', + [ + 'cloudformation', + 'describe-stack-events', + '--stack-name', + stackName, + '--query', + 'StackEvents[?ResourceStatus==`IMPORT_FAILED` || ResourceStatus==`IMPORT_ROLLBACK_IN_PROGRESS`]', + '--output', + 'json', + '--region', + region, + ], + projectPath + ); + if (cfnEvents.exitCode === 0 && cfnEvents.stdout.trim() !== '[]') { + console.log(`CloudFormation failed events for ${label}:`, cfnEvents.stdout); + } +} diff --git a/e2e-tests/import-gateway.test.ts b/e2e-tests/import-gateway.test.ts index 4533f1cc4..2aea04f02 100644 --- a/e2e-tests/import-gateway.test.ts +++ b/e2e-tests/import-gateway.test.ts @@ -7,7 +7,7 @@ import { spawnAndCollect, stripAnsi, } from '../src/test-utils/index.js'; -import { installCdkTarball, runAgentCoreCLI, writeAwsTargets } from './e2e-helper.js'; +import { dumpImportDebugInfo, installCdkTarball, runAgentCoreCLI, writeAwsTargets } from './e2e-helper.js'; import { execSync } from 'node:child_process'; import { randomUUID } from 'node:crypto'; import { mkdir, readFile, rm } from 'node:fs/promises'; @@ -89,6 +89,7 @@ describe.sequential('e2e: import gateway', () => { }, 600_000); const run = (args: string[]): Promise => runAgentCoreCLI(args, projectPath); + const stackName = `AgentCore-${agentName}-default`; // ── Import test ─────────────────────────────────────────────────── @@ -98,41 +99,7 @@ describe.sequential('e2e: import gateway', () => { const result = await run(['import', 'gateway', '--arn', gatewayArn]); if (result.exitCode !== 0) { - console.log('Import gateway stdout:', result.stdout); - console.log('Import gateway stderr:', result.stderr); - - // Print the import log file for debugging CI failures - const logMatch = /Log: (.+)/.exec(result.stderr); - if (logMatch) { - const logPath = join(projectPath, logMatch[1]!); - try { - const logContents = await readFile(logPath, 'utf-8'); - console.log('Import gateway log:\n', logContents); - } catch { - console.log('Could not read log file:', logPath); - } - } - - // Print CloudFormation stack events for the failed import - const cfnEvents = await spawnAndCollect( - 'aws', - [ - 'cloudformation', - 'describe-stack-events', - '--stack-name', - `AgentCore-${agentName}-default`, - '--query', - 'StackEvents[?ResourceStatus==`IMPORT_FAILED` || ResourceStatus==`IMPORT_ROLLBACK_IN_PROGRESS`]', - '--output', - 'json', - '--region', - region, - ], - projectPath - ); - if (cfnEvents.exitCode === 0) { - console.log('CloudFormation failed events:', cfnEvents.stdout); - } + await dumpImportDebugInfo('gateway', result, projectPath, stackName, region); } expect(result.exitCode, `Import gateway failed: ${result.stderr}`).toBe(0); diff --git a/e2e-tests/import-resources.test.ts b/e2e-tests/import-resources.test.ts index e97f62f42..d51cbffac 100644 --- a/e2e-tests/import-resources.test.ts +++ b/e2e-tests/import-resources.test.ts @@ -9,7 +9,7 @@ import { spawnAndCollect, stripAnsi, } from '../src/test-utils/index.js'; -import { installCdkTarball, runAgentCoreCLI, writeAwsTargets } from './e2e-helper.js'; +import { dumpImportDebugInfo, installCdkTarball, runAgentCoreCLI, writeAwsTargets } from './e2e-helper.js'; import { execSync } from 'node:child_process'; import { randomUUID } from 'node:crypto'; import { mkdir, readFile, rm } from 'node:fs/promises'; @@ -112,6 +112,7 @@ describe.sequential('e2e: import runtime/memory/evaluator', () => { }, 600_000); const run = (args: string[]): Promise => runAgentCoreCLI(args, projectPath); + const stackName = `AgentCore-${agentName}-default`; // ── Import tests ────────────────────────────────────────────────── @@ -121,8 +122,7 @@ describe.sequential('e2e: import runtime/memory/evaluator', () => { const result = await run(['import', 'runtime', '--arn', runtimeArn, '--code', appDir, '--name', agentName, '-y']); if (result.exitCode !== 0) { - console.log('Import runtime stdout:', result.stdout); - console.log('Import runtime stderr:', result.stderr); + await dumpImportDebugInfo('runtime', result, projectPath, stackName, region); } expect(result.exitCode, `Import runtime failed: ${result.stderr}`).toBe(0); @@ -137,8 +137,7 @@ describe.sequential('e2e: import runtime/memory/evaluator', () => { const result = await run(['import', 'memory', '--arn', memoryArn, '-y']); if (result.exitCode !== 0) { - console.log('Import memory stdout:', result.stdout); - console.log('Import memory stderr:', result.stderr); + await dumpImportDebugInfo('memory', result, projectPath, stackName, region); } expect(result.exitCode, `Import memory failed: ${result.stderr}`).toBe(0); @@ -153,8 +152,7 @@ describe.sequential('e2e: import runtime/memory/evaluator', () => { const result = await run(['import', 'evaluator', '--arn', evaluatorArn]); if (result.exitCode !== 0) { - console.log('Import evaluator stdout:', result.stdout); - console.log('Import evaluator stderr:', result.stderr); + await dumpImportDebugInfo('evaluator', result, projectPath, stackName, region); } expect(result.exitCode, `Import evaluator failed: ${result.stderr}`).toBe(0);