Home > Net >  CodePipeline: create vpc in stack and use it in post CodeBuildStep
CodePipeline: create vpc in stack and use it in post CodeBuildStep

Time:04-27

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:

  1. The SLS Deploy Project is created as part of the pipeline stack (needs VPC)
  2. The Deploy-dev stack deploys (creates VPC)
  3. 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:

  1. 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 the Deploy-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".
  2. If you really need a CodeBuild project in the mix, a second option is to move SLS Deploy into Deploy-dev and have it executed with a AwsCustomResource. It is a lower-level cousin of Trigger for runing arbitrary SDK calls (like codebuild: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?)

  • Related