Skip to content

Commit e2667d1

Browse files
authored
chore(cli): bootstrap stack downgrading is no longer an error (#18378)
Previously, bootstrap downgrading is an error. That is, when the bootstrap stack is currently version '9', and you're trying to run `cdk bootstrap` with version '8', the command will currently fail. This makes it hard to script around, and in fact this is causing us problems in the pipeline where we unconditionally run `cdk bootstrap` and an accidentally upgraded bootstrap stack fails all tests. This is happening for no good reason, since the bootstrap stacks are backwards compatible. Turn this case from an error into a successful no-op. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent e1731b1 commit e2667d1

File tree

4 files changed

+17
-8
lines changed

4 files changed

+17
-8
lines changed

packages/aws-cdk/lib/api/bootstrap/deploy-bootstrap.ts

+13-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import * as path from 'path';
33
import * as cxschema from '@aws-cdk/cloud-assembly-schema';
44
import * as cxapi from '@aws-cdk/cx-api';
55
import * as fs from 'fs-extra';
6+
import * as logging from '../../logging';
67
import { Mode, SdkProvider, ISDK } from '../aws-auth';
78
import { deployStack, DeployStackResult } from '../deploy-stack';
89
import { DEFAULT_TOOLKIT_STACK_NAME, ToolkitInfo } from '../toolkit-info';
@@ -65,7 +66,18 @@ export class BootstrapStack {
6566

6667
const newVersion = bootstrapVersionFromTemplate(template);
6768
if (this.currentToolkitInfo.found && newVersion < this.currentToolkitInfo.version && !options.force) {
68-
throw new Error(`Not downgrading existing bootstrap stack from version '${this.currentToolkitInfo.version}' to version '${newVersion}'. Use --force to force or set the '@aws-cdk/core:newStyleStackSynthesis' feature flag in cdk.json to use the latest bootstrap version.`);
69+
logging.warning(`Bootstrap stack already at version '${this.currentToolkitInfo.version}'. Not downgrading it to version '${newVersion}' (use --force if you intend to downgrade)`);
70+
if (newVersion === 0) {
71+
// A downgrade with 0 as target version means we probably have a new-style bootstrap in the account,
72+
// and an old-style bootstrap as current target, which means the user probably forgot to put this flag in.
73+
logging.warning('(Did you set the \'@aws-cdk/core:newStyleStackSynthesis\' feature flag in cdk.json?)');
74+
}
75+
76+
return {
77+
noOp: true,
78+
outputs: {},
79+
stackArn: this.currentToolkitInfo.bootstrapStack.stackId,
80+
};
6981
}
7082

7183
const outdir = await fs.mkdtemp(path.join(os.tmpdir(), 'cdk-bootstrap'));

packages/aws-cdk/lib/api/deploy-stack.ts

+2-4
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ export interface DeployStackResult {
2828
readonly noOp: boolean;
2929
readonly outputs: { [name: string]: string };
3030
readonly stackArn: string;
31-
readonly stackArtifact: cxapi.CloudFormationStackArtifact;
3231
}
3332

3433
export interface DeployStackOptions {
@@ -241,7 +240,6 @@ export async function deployStack(options: DeployStackOptions): Promise<DeploySt
241240
noOp: true,
242241
outputs: cloudFormationStack.outputs,
243242
stackArn: cloudFormationStack.stackId,
244-
stackArtifact,
245243
};
246244
} else {
247245
debug(`${deployName}: deploying...`);
@@ -330,7 +328,7 @@ async function prepareAndExecuteChangeSet(
330328
debug('Deleting empty change set %s', changeSet.Id);
331329
await cfn.deleteChangeSet({ StackName: deployName, ChangeSetName: changeSetName }).promise();
332330
}
333-
return { noOp: true, outputs: cloudFormationStack.outputs, stackArn: changeSet.StackId!, stackArtifact };
331+
return { noOp: true, outputs: cloudFormationStack.outputs, stackArn: changeSet.StackId! };
334332
}
335333

336334
const execute = options.execute === undefined ? true : options.execute;
@@ -367,7 +365,7 @@ async function prepareAndExecuteChangeSet(
367365
print('Changeset %s created and waiting in review for manual execution (--no-execute)', changeSet.Id);
368366
}
369367

370-
return { noOp: false, outputs: cloudFormationStack.outputs, stackArn: changeSet.StackId!, stackArtifact };
368+
return { noOp: false, outputs: cloudFormationStack.outputs, stackArn: changeSet.StackId! };
371369
}
372370

373371
/**

packages/aws-cdk/lib/api/hotswap-deployments.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ export async function tryHotswapDeployment(
5555
// apply the short-circuitable changes
5656
await applyAllHotswappableChanges(sdk, hotswappableChanges);
5757

58-
return { noOp: hotswappableChanges.length === 0, stackArn: cloudFormationStack.stackId, outputs: cloudFormationStack.outputs, stackArtifact };
58+
return { noOp: hotswappableChanges.length === 0, stackArn: cloudFormationStack.stackId, outputs: cloudFormationStack.outputs };
5959
}
6060

6161
async function findAllHotswappableChanges(

packages/aws-cdk/test/api/bootstrap2.test.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -172,8 +172,7 @@ describe('Bootstrapping v2', () => {
172172
parameters: {
173173
cloudFormationExecutionPolicies: ['arn:policy'],
174174
},
175-
}))
176-
.rejects.toThrow('Not downgrading existing bootstrap stack');
175+
})).resolves.toEqual(expect.objectContaining({ noOp: true }));
177176
});
178177

179178
test('bootstrap template has the right exports', async () => {

0 commit comments

Comments
 (0)