Aws-cdk: Asset support in CI/CD pipelines

Created on 10 Dec 2018  路  20Comments  路  Source: aws/aws-cdk

Hi

I'm trying to follow these steps CodePipeline Actions for CloudFormation for building with CFN, but I'm have a hard time to make templatePath work.

CodeBuild calls cdk synth (and outputs template.yaml) then I set as the templatePath as follows:

const project = new codebuild.PipelineProject(this, 'Project', {
  environment: {
    buildImage: codebuild.LinuxBuildImage.UBUNTU_14_04_NODEJS_10_1_0
  },
  buildSpec: {
    version: '0.2',
    phases: {
      install: {
        commands: [
          '...'
        ]
      },
      build: {
        commands: [
          'cdk synth > ../template.yaml'
        ]
      }
    },
    artifacts: {
      files: ['template.yaml']
    }
  }
})

// ...

const pipeline = new codepipeline.Pipeline(this, 'CodePipeline', {})

const build = new codebuild.PipelineBuildAction(this, 'CodeBuild', {
  stage: pipeline.addStage('Build'),
  project,
  outputArtifactName: 'Build'
})

new cfn.PipelineCreateReplaceChangeSetAction(prodStage, 'PrepareChanges', {
  stage: prodStage,
  stackName,
  changeSetName,
  adminPermissions: true,
  templatePath: build.outputArtifact.atPath('template.yaml')
})

But I keep getting this error on the PrepareChanges stage:

image

I checked the artifact generated in the build stage and the template.yaml is in there.

Just as a random attempt, I've also tried to commit the template.yaml and use directly from source instead of build:

new codepipeline.GitHubSourceAction(this, 'GitHubSource', {
  stage: pipeline.addStage('Source'),
  owner: 'project',
  repo: 'repo',
  branch: 'master',
  oauthToken: new Secret(oauth.value),
  outputArtifactName: 'Source'
})

new cfn.PipelineCreateReplaceChangeSetAction(prodStage, 'PrepareChanges', {
  stage: prodStage,
  stackName,
  changeSetName,
  adminPermissions: true,
  templatePath: source.outputArtifact.atPath('template.yaml')
})

But it didn't work, I got the same error.

Any ideas?

@aws-cdaws-codepipeline efforlarge feature-request in-progress packagtools

Most helpful comment

Any updates on when this is expected to be supported?

All 20 comments

I've asked some people more knowledgeable to take a look, but from the error message it looks like the project you're trying to deploy is using assets.

This might not be supported yet.

Hi @rix0rrr

Thanks for the quick reply. WDYM by assets? This project has a static website and a lambda.

const websiteBucket = new s3.Bucket(parent, 'bucket', {
    websiteIndexDocument: 'index.html',
    publicReadAccess: true
})

new s3deploy.BucketDeployment(parent, 'bucket-deployment', {
  source: s3deploy.Source.asset('../web/build'),
  destinationBucket: websiteBucket
})

const fn = new lambda.Function(parent, 'function', {
  runtime: new lambda.Runtime('ruby2.5'),
  handler: 'lambda.handler',
  code: lambda.Code.asset('../app')
})

cdk synth and cdk deploy works fine, also if I download the artifact on S3 and unzip it, the template.yaml is in there.

I'm wondering if the problem is with one of these PipelineCreateReplaceChangeSetAction or templatePath: build.outputArtifact.atPath('template.yaml').

Hi @phstc,

This is what I mean by assets:

new s3deploy.BucketDeployment(parent, 'bucket-deployment', {
  source: s3deploy.Source.asset('../web/build'),
                          ^^^^^  // this
  destinationBucket: websiteBucket
})

const fn = new lambda.Function(parent, 'function', {
  runtime: new lambda.Runtime('ruby2.5'),
  handler: 'lambda.handler',
  code: lambda.Code.asset('../app')
                    ^^^^^ // and this
})

Any time you're referencing files on your local file system, we're referring to that as "assets".

It seems my guess that there is no CI/CD asset support yet is true. One of my team members who knows more about this will chip in with more information shortly.

Thanks again @rix0rrr

Confirmed. When I remove my bucket and lambda PipelineCreateReplaceChangeSetAction works.

Is the workaround to use inline lambda code for the time being?

If anyone else runs into this, I used this as a workaround:

new lambda.Function(this, 'function', {
      runtime: lambda.Runtime.NodeJS810,
      handler: 'index.handler',
      code: lambda.Code.inline(this.localAsset(path.join(__dirname, 'index.js'))),
});
localAsset(path: string) {
    return fs.readFileSync(path, 'utf8');
}

So as far as I can tell this means any CDK project using decently large Lambdas can't be deployed through a proper CD pipeline? It has to be a full cdk deploy or nothing?

If there was a step between the lines here: https://github.com/aws/aws-cdk/blob/master/packages/aws-cdk/lib/api/deploy-stack.ts#L91 for creating a ChangeSet and Executing it, I belive it could work. Everything would have been uploaded and parameters would be set, but it wouldn't be released until the Execute step. Which could be manual, CodePipeline or CLI.

@joshrp we're using cdk deploy within a CodePipeline pretty successfully, we're using the -e option to only deploy the lambda stack, and it's been working rock solid for us so far.

I hadn't see the -e, that might be a partial solution, thanks. But I don't think I was clear before, by a proper CD setup I mean I can run a build, produce an artifact and then deploy it later. Mostly so I can have a step between build and a production deploy and have artifacts I can rollback to.

If I have to rely on cdk deploy then I'm running the whole build again in production, and whatever is running that build also has to have access to deploy to production.

Ideally cdk would create a CloudFormation ChangeSet, and then stop, allowing me to approve or deny, delay or inspect it.

I'm running into the same issue, just found the issue now

Please see #3437 for details on how we plan to support this

If anyone else runs into this, I used this as a workaround:

new lambda.Function(this, 'function', {
      runtime: lambda.Runtime.NodeJS810,
      handler: 'index.handler',
      code: lambda.Code.inline(this.localAsset(path.join(__dirname, 'index.js'))),
});
localAsset(path: string) {
    return fs.readFileSync(path, 'utf8');
}

This only handles the Lambda. Is there currently a workaround for the BucketDeployment asset?

@LiveJay this is how you can reference the bucket asset, it works fine for me, but I don't really get how I should handle multiple lambdas in 1 stack.

Any updates on when this is expected to be supported?

In a current project we're using this gist as workaround while waiting for native CDK support: https://gist.github.com/ottokruse/41694de3831d6bfe9080743b352aa2fe

It's a script to publish CDK assets (e.g. Lambda function code) to S3 and generate parameter files, so you can combine cdk synth with CloudFormation deployments. This is essentially the equivalent of 'sam package' but then for CDK.

@BDQ How do you handle cdk permissions within codebuild?

@mikestopcontinues we add the required permissions codebuild job's Role policy:

const deploy = new codebuild.PipelineProject(stack, "dply", {...})

 deploy.addToRolePolicy(
    new iam.PolicyStatement({
      resources: [...],
      actions: [...]
   })
)

@BDQ Thanks!

This has been implemented as CDK Pipelines.

@rix0rrr Are there plans to support report groups in pipelines? It's why I haven't switched to them.

Was this page helpful?
0 / 5 - 0 ratings