I am creating a pipeline using AWS CDK. I first create my stack which consists in a vpc and an rds, I export the vpc object and use it in a post CodeBuildStep which migrates the database:
export class CdkPipelineStack extends Stack {
constructor(scope: Construct, id: string, props?: StackProps) {
super(scope, id, props)
const repo = new codecommit.Repository(this, 'CloudFrontCDKRepo', {
repositoryName: 'backend',
})
const pipeline = new CodePipeline(this, 'Pipeline', {
crossAccountKeys: false,
pipelineName: 'MyPipeline2',
synth: new ShellStep('Synth', {
input: CodePipelineSource.codeCommit(repo, 'cdk'),
commands: ['cd cdk', 'npm ci', 'npm run build', 'npx cdk synth'],
primaryOutputDirectory: 'cdk/cdk.out',
}),
})
const deploy = new DevStage(this, 'Deploy-dev')
const deployStage = pipeline.addStage(deploy)
deployStage.addPost(
new CodeBuildStep('SLS Deploy', {
commands: ['./build.sh'],
vpc: deploy.vpc
}),
)
}
}
However I am getting the following error:
Stack "MyPipelineStack" cannot consume a cross reference from stack "MyPipelineStack/Deploy-dev/S3Stack". Cross stack references are only supported for stacks deployed to the same environment or between nested stacks and their parent stack
How can I correctly import the vpc here? And if this is not possible, how do I run a codebuildstep as a separate stack which executes only after the main stack has finished?
CodePudding user response:
As @gshpychka says in the comments, you are asking CodePipeline to perform an impossible order of operations:
- The
SLS Deploy
Project is created as part of the pipeline stack (needs VPC) - The
Deploy-dev
stack deploys (creates VPC) - The
SLS Deploy
Project runs
One way around this ordering problem is to add SLS Deploy
's logic to the Deploy-dev
Stack itself. There are a couple ways to do this:
- The simplest approach is to translate
build.sh
into a TriggerFunction Lambda that has access to the VPC. A Trigger construct calls the Lambda as part of theDeploy-dev
Stack's deployment lifecycle. As the docs say, Triggers are designed for tasks like "Data priming: add initial data to resources after they are created". - If you really need a CodeBuild project in the mix, a second option is to move
SLS Deploy
intoDeploy-dev
and have it executed with a AwsCustomResource. It is a lower-level cousin ofTrigger
for runing arbitrary SDK calls (likecodebuild:StartBuild
) as part of the stack deployment cycle.
N.B. Both these methods have the added advantage of finer-grained control over when your migration script runs (e.g. on first deploy only? after each update?)