1

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?

Vallo
  • 1,827
  • 2
  • 21
  • 42
  • When you deploy the pipeline, the VPC doesn't exist yet, so you can put a pipeline action in the vpc that the pipeline is creating. – gshpychka Apr 25 '22 at 17:55
  • How would that be? I managed to correctly deploy the pipeline by creating a `new codebuild.Project` under the stack, but now my CodeBuild step is not triggered. – Vallo Apr 25 '22 at 22:12
  • 1
    Sorry, I meant to say that you CAN'T put a pipeline action in the VPC that the pipeline itself is creating. Because the VPC doesn't exist when the pipeline is created. – gshpychka Apr 26 '22 at 07:46

1 Answers1

2

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?)

fedonev
  • 20,327
  • 2
  • 25
  • 34
  • Thanks so much for this information. I managed to correctly trigger a CodeBuild project but I noted the pipeline succeeds right after the CodeBuild project starts building, and I need to wait until it finish building to continue with my next steps. Is this possible? Otherwise I'll use a Lambda and TriggerFunction which has more flexibility. Thanks again – Vallo Apr 26 '22 at 15:42
  • 2
    @Vallo Yes, Custom Functions do have [polling functionality to "wait" until a certain state is achieved](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.custom_resources-readme.html#asynchronous-providers-iscomplete). To get this async handling, though, you must use the (even lower-level) [Provider](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.custom_resources.Provider.html) Custom Resource construct. The Provider takes 2 Lambda functions, an `onEventHandler` to call `StartBuild` and another, a `isCompleteHandler` to signal when the build is finished. – fedonev Apr 26 '22 at 16:05