Stages, approvals, and stack names
What you'll build
- A dev → prod promotion path expressed as config data, with a fail-closed approval gate.
- Multi-region stages that fan out — without growing the pipeline.
- Forced deployment roles for controlled (Automation Framework) accounts.
- Stack names you control per stage with
stageStackName.
Stages are config rows, not pipeline code
A stage is either a bare name or an object with its own environment:
export default defineCICD({
application: 'my-app',
repository: Repository.codecommit('my-app'),
stages: [
'dev', // inner loop, auto-approved
{ name: 'prod', env: { account: '333333333333', region: 'eu-west-1' }, manualApproval: true },
],
});
A multi-region stage stays one deploy action — the region fan-out happens inside cdk-cicd deploy
(the regions deploy in turn), so the pipeline shape doesn't grow with regions:
{ name: 'prod', env: { account: '333333333333', regions: ['eu-west-1', 'us-east-1'] } }
Manual-approval gates are fail-closed
manualApproval: true puts a Manual Approval action ahead of the stage's deploy (at a lower run
order), so the deploy cannot start until a human approves. Non-dev/res stages are gated by default;
set manualApproval: false to opt a stage out. Rejection or the approval timeout fails the stage —
nothing ships unapproved.
Forced deployment roles
In controlled accounts, deploys must go through a specific, pre-provisioned role rather than the
pipeline's own identity. Set deployment on the stage to force the deploy role and (optionally) the
CloudFormation execution role — the wrapper threads them into synth and deploy for you, with no change to
bin/:
{
name: 'prod',
env: { account: '333333333333', region: 'eu-west-1' },
manualApproval: true,
deployment: {
deployRole: 'arn:aws:iam::333333333333:role/automation-deployer',
cfnExecutionRole: 'arn:aws:iam::333333333333:role/automation-deployer',
},
}
This is the Automation Framework pattern
Forcing a controlled role per stage is exactly what enterprise "deploy only through role X" policies
need. Container mode (chapter 5) uses the same deployment.deployRole shape on its deploy targets.
Controlling the CloudFormation stack name
Autopilot synthesizes the same bin/ once per stage, so a bare new MyStack(app, 'my-app') deploys the same
name in every stage. Use the opt-in stageStackName helper to qualify it by stage:
import { stageStackName } from '@cdklabs/cdk-cicd-wrapper';
new MyStack(app, 'my-app', {
stackName: stageStackName('my-app'), // -> my-app-dev / my-app-prod
env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
});
This is the one place you'd import the wrapper in bin/, and it's opt-in. It reads the stage from
CDK_STAGE (which cdk-cicd exec sets). Migrating from Blueprint? Pass the options object to reproduce
Blueprint's exact stack name so you update in place instead of recreating — Blueprint prefixed the
stage (uppercase by default), e.g. DEV-my-app:
stackName: stageStackName('my-app', { stageFirst: true, uppercaseStage: true }), // -> DEV-my-app / PROD-my-app
stageFirst puts the stage before the base; uppercaseStage matches Blueprint's default uppercase stage
ids (drop it if your Blueprint stages were lowercase/custom-case). See the migration chapter.
Verify
Verify
- The pipeline shows a Manual Approval action before each gated stage's deploy; approving it lets the deploy proceed, rejecting it fails the stage.
- For a multi-region stage, each region's stack is created in turn under the one deploy action.
- With
stageStackName, the deployed CloudFormation stacks are named per stage (e.g.my-app-dev,my-app-prod). Check locally:
CDK_STAGE=prod npx cdk-cicd synth --stage prod # stack name resolves to my-app-prod
Recap
Stages, approvals, regions, and roles are all config data on the stages array — the pipeline shape
doesn't grow as you add regions, and gates are fail-closed by default. stageStackName gives you explicit
control of CloudFormation stack names per stage, which is also the key to migrating without a recreate.
Next: how and when the pipeline synthesizes, and the tuning knobs that go with it.