11import { CONFIG_DIR , ConfigIO } from '../../../lib' ;
22import type { AwsDeploymentTarget } from '../../../schema' ;
33import { withTargetRegion } from '../../aws' ;
4+ import { deleteConfigurationBundle } from '../../aws/agentcore-config-bundles' ;
45import { CdkToolkitWrapper , silentIoHost } from '../../cdk/toolkit-lib' ;
56import { type DiscoveredStack , findStack } from '../../cloudformation/stack-discovery' ;
6- import { deleteHttpGatewayWithTargets } from './post-deploy-http-gateways' ;
7+ import { deleteOrphanedABTests } from './post-deploy-ab-tests' ;
8+ import { deleteOrphanedHttpGateways } from './post-deploy-http-gateways' ;
79import { StackSelectionStrategy } from '@aws-cdk/toolkit-lib' ;
810import { existsSync } from 'fs' ;
911import { join } from 'path' ;
@@ -113,11 +115,15 @@ export async function performStackTeardown(targetName: string): Promise<StackTea
113115 const discovered = await discoverDeployedTargets ( ) ;
114116 const deployedTarget = discovered . deployedTargets . find ( dt => dt . target . name === targetName ) ;
115117
116- // Clean up imperatively-created HTTP gateways before stack destruction
118+ // Clean up imperatively-created resources before stack destruction.
119+ // Ordering: AB tests first (they create rules on gateways), then gateways, then bundles.
120+ // Delegates to the existing orphan-cleanup functions with an empty spec so everything
121+ // is treated as orphaned — reuses stop/poll/delete/role-cleanup logic without duplication.
117122 try {
118123 const deployedState = await configIO . readDeployedState ( ) ;
119- const httpGateways = deployedState . targets ?. [ targetName ] ?. resources ?. httpGateways ;
120- if ( httpGateways ) {
124+ const resources = deployedState . targets ?. [ targetName ] ?. resources ;
125+
126+ if ( resources ?. httpGateways || resources ?. configBundles || resources ?. abTests ) {
121127 let region = deployedTarget ?. target . region ;
122128 if ( ! region ) {
123129 try {
@@ -129,29 +135,49 @@ export async function performStackTeardown(targetName: string): Promise<StackTea
129135 }
130136 }
131137 if ( ! region ) {
132- console . warn (
133- 'Warning: Could not determine region for HTTP gateway cleanup — gateways may need manual deletion'
134- ) ;
138+ console . warn ( 'Warning: Could not determine region for resource cleanup — resources may need manual deletion' ) ;
135139 }
136140 if ( region ) {
137- for ( const [ gwName , gwState ] of Object . entries ( httpGateways ) ) {
138- try {
139- const result = await deleteHttpGatewayWithTargets ( {
140- region,
141- gatewayId : gwState . gatewayId ,
142- gatewayName : gwName ,
143- knownTargetId : gwState . targetId ,
144- roleArn : gwState . roleArn ,
145- roleCreatedByCli : gwState . roleCreatedByCli ,
146- } ) ;
147- if ( result . success ) {
148- console . log ( `Deleted HTTP gateway "${ gwName } "` ) ;
149- } else {
150- console . warn ( `Warning: Failed to delete HTTP gateway "${ gwName } ": ${ result . error } ` ) ;
141+ const projectSpec = await configIO . readProjectSpec ( ) ;
142+ const emptySpec = { ...projectSpec , abTests : [ ] , httpGateways : [ ] } ;
143+
144+ if ( resources . abTests ) {
145+ const abResult = await deleteOrphanedABTests ( {
146+ region,
147+ projectSpec : emptySpec ,
148+ existingABTests : resources . abTests ,
149+ } ) ;
150+ for ( const r of abResult . results ) {
151+ if ( r . status === 'deleted' ) {
152+ console . log ( `Deleted AB test "${ r . testName } "` ) ;
153+ } else if ( r . error ) {
154+ console . warn ( `Warning: Failed to delete AB test "${ r . testName } ": ${ r . error } ` ) ;
155+ }
156+ }
157+ }
158+
159+ if ( resources . httpGateways ) {
160+ const gwResult = await deleteOrphanedHttpGateways ( {
161+ region,
162+ projectSpec : emptySpec ,
163+ existingHttpGateways : resources . httpGateways ,
164+ } ) ;
165+ for ( const r of gwResult . results ) {
166+ if ( r . status === 'deleted' ) {
167+ console . log ( `Deleted HTTP gateway "${ r . gatewayName } "` ) ;
168+ } else if ( r . error ) {
169+ console . warn ( `Warning: Failed to delete HTTP gateway "${ r . gatewayName } ": ${ r . error } ` ) ;
151170 }
171+ }
172+ }
173+
174+ for ( const [ bundleName , bundleState ] of Object . entries ( resources . configBundles ?? { } ) ) {
175+ try {
176+ await deleteConfigurationBundle ( { region, bundleId : bundleState . bundleId } ) ;
177+ console . log ( `Deleted config bundle "${ bundleName } "` ) ;
152178 } catch ( err ) {
153179 console . warn (
154- `Warning: Error during HTTP gateway "${ gwName } " cleanup: ${ err instanceof Error ? err . message : String ( err ) } `
180+ `Warning: Error during config bundle "${ bundleName } " cleanup: ${ err instanceof Error ? err . message : String ( err ) } `
155181 ) ;
156182 }
157183 }
@@ -161,7 +187,7 @@ export async function performStackTeardown(targetName: string): Promise<StackTea
161187 // Only suppress "file not found" — other errors (corrupt state, permissions) should warn
162188 const msg = err instanceof Error ? err . message : String ( err ) ;
163189 if ( ! msg . includes ( 'ENOENT' ) && ! msg . includes ( 'not found' ) && ! msg . includes ( 'does not exist' ) ) {
164- console . warn ( `Warning: Could not read deployed state for HTTP gateway cleanup: ${ msg } ` ) ;
190+ console . warn ( `Warning: Could not read deployed state for resource cleanup: ${ msg } ` ) ;
165191 }
166192 }
167193
0 commit comments