diff --git a/packages/aws-cdk/lib/api/util/cloudformation.ts b/packages/aws-cdk/lib/api/util/cloudformation.ts index e4fa597e506b4..66f7752371f7c 100644 --- a/packages/aws-cdk/lib/api/util/cloudformation.ts +++ b/packages/aws-cdk/lib/api/util/cloudformation.ts @@ -371,6 +371,14 @@ export async function stabilizeStack(cfn: CloudFormation, stackName: string) { if (status.isInProgress) { debug('Stack %s has an ongoing operation in progress and is not stable (%s)', stackName, status); return undefined; + } else if (status.isReviewInProgress) { + // This may happen if a stack creation operation is interrupted before the ChangeSet execution starts. Recovering + // from this would requiring manual intervention (deleting or executing the pending ChangeSet), and failing to do + // so will result in an endless wait here (the ChangeSet wont delete or execute itself). Instead of blocking + // "forever" we proceed as if the stack was existing and stable. If there is a concurrent operation that just + // hasn't finished proceeding just yet, either this operation or the concurrent one may fail due to the other one + // having made progress. Which is fine. I guess. + debug('Stack %s is in REVIEW_IN_PROGRESS state. Considering this is a stable status (%s)', stackName, status); } return stack; diff --git a/packages/aws-cdk/lib/api/util/cloudformation/stack-status.ts b/packages/aws-cdk/lib/api/util/cloudformation/stack-status.ts index 76069868cf99b..8e2ae674a9074 100644 --- a/packages/aws-cdk/lib/api/util/cloudformation/stack-status.ts +++ b/packages/aws-cdk/lib/api/util/cloudformation/stack-status.ts @@ -26,7 +26,11 @@ export class StackStatus { } get isInProgress(): boolean { - return this.name.endsWith('_IN_PROGRESS'); + return this.name.endsWith('_IN_PROGRESS') && !this.isReviewInProgress; + } + + get isReviewInProgress(): boolean { + return this.name === 'REVIEW_IN_PROGRESS'; } get isNotFound(): boolean {