How to set up a simple CI/CD for AWS CDK projects
Tags: aws, serverless, cdk, devops
Published: 2022-08-20 16:26:00

I've recently found out there is really easy way to set up simple CI/CD for cdk projects. Like most things with AWS, I felt like there aren't enough guides and tutorials about it. So I'm sharing my experience on how I did it. 

## Problem
My team and I has been experiencing major slowdown in our cdk deployments recently. We all have our own development sandbox account we deploy to. Deployments doesn't take long in our own environments. Because it is fairly incremental and small updates we're deploying. It takes 1-2 minutes most of the time. But when we done testing in our environment, we deploy to shared staging environment for more testing and QA. So each developer has to deploy from their own machines. Our staging deployments can take 10-20 minutes each time. So I always wondered, why does it take so long in staging. Then I've noticed from my cdk logs that when we deploy from different machines, cdk updates its metadata in every stack we have on our project. Even the stacks that doesn't have any changes gets updated. On the contrary, when we make 2 consecutive deployments from the same machine, it takes 1-2 minutes like our own environments. So I decided to automate our staging deployment process with AWS Pipeline. 

## Solution
I've had some experience building a simple CI/CD using AWS CodeCommit, CodeBuild, CodeDeploy and Pipelines etc. Because I built it manually from AWS Web Console, I remember it being not that easy to set up. 

Then I've realized that easiest and most convenient way to build must be the CDK itself. The CDK has many different constructs for building CI/CD pipelines. Most of them for individual services that is part of the pipeline. 

Then there is a CDK contruct library called [CDK Pipelines](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines-readme.html) (aws-cdk-lib.pipelines) which has higher level of constructs that integrates many different aws services and their CDK constructs together. It is opinionated library that purposely built for deploying cdk applications. They states it perfectly clear in the documentation that this library is not suitable for highly customizable CI/CD pipelines.

> A construct library for painless Continuous Delivery of CDK applications.
> CDK Pipelines is an opinionated construct library. It is purpose-built to deploy one or more copies of your CDK applications using CloudFormation with a minimal amount of effort on your part. It is not intended to support arbitrary deployment pipelines, and very specifically it is not built to use CodeDeploy to applications to instances, or deploy your custom-built ECR images to an ECS cluster directly: use CDK file assets with CloudFormation Init for instances, or CDK container assets for ECS clusters instead.
> Give the CDK Pipelines way of doing things a shot first: you might find it does everything you need. If you want or need more control, we recommend you drop down to using the aws-codepipeline construct library directly.
_[Full documentation](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines-readme.html)_

So I felt this is good enough for us as starting point. So we decided to build our CI/CD with it. 

## How to do it?
Before writing any code we need to set up authentication method for AWS Pipeline to pull our repositories from Github.

**1. Create personal access token** 
Go to https://github.com/settings/tokens to create personal access token with right permissions

**2. Save the token under the name of `github-token` in AWS Secrets Manager in your AWS account**. 

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5eh7sxf28vge6kvrai0l.png)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ypeadcd2cf0wjqggoatr.png)

**3. Set up the pipeline with CDK Pipelines**

Here is an typescript code example of CDK Pipelines

```typescript
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import { CodePipeline, CodePipelineSource, CodeBuildStep } from 'aws-cdk-lib/pipelines';
import * as iam from 'aws-cdk-lib/aws-iam';
import { ComputeType } from 'aws-cdk-lib/aws-codebuild';

export class CodePipelineStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    const pipeline = new CodePipeline(this, 'Pipeline', {
      pipelineName: 'CorePipeline',
      selfMutation: false,
      synth: new CodeBuildStep('DeploymentStep', {
        input: CodePipelineSource.gitHub('OWNER/REPO', 'branch_name'),
        commands: [
          'npm ci',
          'npx cdk synth',
          'npm run deploy-ci'
        ],
        buildEnvironment: {
          computeType: ComputeType.LARGE,
        },
        rolePolicyStatements: [
          new iam.PolicyStatement({
            effect: iam.Effect.ALLOW,
            actions: ['*'],
            resources: ['*'],
          }),
        ],
      })
    });

  }
}

```

> `selfMutation: false`
> If set to `true`, it will deploy your application everytime you make changes to the pipeline and also automatically adds `cdk deploy` command to the scripts. I'd rather turn it off because I have custom build scripts in our project. Also I don't want unnecessary deployment when I'm initially setting up the pipeline
> `computeType: ComputeType.LARGE` 
> Here you can choose what type of instance you want to use for your deployment. Instance types and its pricing can be found from CodeBuild [documentation](https://aws.amazon.com/codebuild/pricing/)
> ```
> rolePolicyStatements: [
>   new iam.PolicyStatement({
>     effect: iam.Effect.ALLOW,
>     actions: ['*'],
>     resources: ['*'],
>   }),
> ],
> ```
> Here is the part I'm not really proud of at the moment. The Codebuild needs the necessary IAM permissions to deploy your stacks to the CloudFormation. I expected these permissions would be handled by CDK itself. But I got permissions error during my initial deployments. It is a temporary workaround for that.

And deploy. You can see your deployment results from AWS Pipeline dashboard


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/16idgj3etzp4k8vlq2u0.png) 



That is it folks. I hope you find this helpful.

**Sources**
[Continuous integration and delivery (CI/CD) using CDK Pipelines](https://docs.aws.amazon.com/cdk/v2/guide/cdk_pipeline.html
)
[CDK Pipelines](https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.pipelines-readme.html)