Continuous integration and delivery (CI/CD) using AWS CDK Pipelines with Bitbucket
Tags: aws, react, devops, typescript
Published: 2021-10-12 13:40:07

When starting a new project the first problem we face is planning our infrastructure. In this post I'm giving a simple example of how we can create an automated pipeline using AWS CDK and Bitbucket repository. Before diving into Prerequisites and Steps.
let me first unravel the title of this post: “Continuous integration and delivery with AWS CDK Pipelines”

##Continuous Delivery
I will assume you already have heard about the term Continuous Delivery and there is many definitions out there but the simplest is CD is a set of tools and processes that helps DevOps teams to ship higher quality software, faster.

## AWS CDK vs the world
The official definition for AWS CDK is an open source software development framework to define your cloud application resources (Infrastructure) using familiar programming languages (`TypeScript, JavaScript, Python, Java and C#`).

#### Why CDk vs the world?
Basically we can compare the CDK with Serverless framework, AWS SAM, and Terraform. All these frameworks are used to develop, test and deploy your project, I will not go in all details and differences between them! 
The main benefits of using AWS CDK are: 
* Easy to use, because we will use the same programing language we use in our project, CDK can be integrated in your IDE, and you don't need to learn Yml or Terraform. 
* Component reusability and sharing, just like any other software library

For more details check this [post](https://dev.to/tastefulelk/serverless-framework-vs-sam-vs-aws-cdk-1g9g) by my friend [Sebastian Bille](https://dev.to/tastefulelk)
And another good [post](https://acloudguru.com/blog/engineering/cloudformation-terraform-or-cdk-guide-to-iac-on-aws) from [A Cloud Guru](https://acloudguru.com/)


## AWS CodeBuild vs Bitbucket Pipelines
I had a job interview recently, and as a part of the interview process I had to do some code test. They asked to create a pipeline using AWS CodeBuild with Bitbucket? My first reaction was why you want to use CodeBuild instead of Bitbucket Pipelines? 
The answer I got wasn't satisficing, The main differences I found after some search are:
* Integration with AWS services
* Price, Bitbucket Pipelines offer product package options than AWS offers pay-as-you-go
* Authentication with AWS, CodeBuild has IAM Role integration which gives temporary AWS credentials

If you want to find out more about this topic please check the following articles:
* [CI Tools comparison: CodeBuild vs Bitbucket Pipelines vs Jenkins](https://medium.com/@rokaso/ci-tools-comparison-codebuild-vs-bitbucket-pipelines-vs-jenkins-47f3d25ff984)
* [AWS CodeBuild vs Bitbucket Pipelines](https://knapsackpro.com/ci_comparisons/aws-codebuild/vs/bitbucket-pipelines)

#Getting started
The focus of this post will be on creating pipelines-as-code, so for demonstration purposes we will create and deploy a simple react-app

##Prerequisites 
* NodeJS install latest Nodejs version 
* npm or yarn should be installed globally 
* AWS CDK install with `npm install -g aws-cdk` or `yarn global add aws-cdk`
* AWS CLI
* AWS Account
* Bitbucket Account

##Steps
### 1. Create Bitbucket repo
  * Create a public or private repository in [Bitbucket] (https://bitbucket.org/repo/create) and name it myapp
  * Clone Bitbucket repo to your machine

### 2. Creating react-app 
  * Create a simple react-app in the same directory of your 
Bitbucket repository  
```bash
npx create-react-app my-app
cd my-app
yarn start
```
  * Commit react-app code to Bitbucket 

### 3. Configure AWS CLI
  * Generate an `Access Key` and `Secret Access Key` for your AWS account.

```bash
$ > export AWS_ACCESS_KEY_ID="…"
$ > export AWS_SECRET_ACCESS_KEY="…"
$ > export AWS_SESSION_TOKEN="…"
```
### 4. Create infrastructure folder 
  * Create a new folder outside the `src` folder and name it infra
  * Navigate to the infra folder
  * Init the CDK project
  ```bash
  cdk init myApp --language typescript
  ```
#### 5. Deploy infrastructure 
Before the deployment we need to update `infr.ts` under  `/lib` start by: 
* Add the following dependencies  
```javascript
import * as CDK from "@aws-cdk/core";
import * as CodeBuild from "@aws-cdk/aws-codebuild";
import * as CodePipeline from "@aws-cdk/aws-codepipeline";
import * as CodePipelineAction from "@aws-cdk/aws-codepipeline-actions";
import * as S3 from "@aws-cdk/aws-s3"; 
```
* Create pipeline and pipeline artifacts 
```javascript

    // AWS CodeBuild artifacts
    const outputSources = new CodePipeline.Artifact();
    const outputWebsite = new CodePipeline.Artifact();

    // AWS CodePipeline pipeline
    const pipeline = new CodePipeline.Pipeline(this, "Pipeline", {
      pipelineName: "MyWebsite",
      restartExecutionOnUpdate: true,
    });
```
* Add checkout stage in this stage we will clone sources from bitbucket repository
we will need to create a `connectionArn` in this step please follow the documentation in [Create a connection to Bitbucket](https://docs.aws.amazon.com/dtconsole/latest/userguide/connections-create-bitbucket.html) to get your `connectionArn`.
```javascript
// AWS CodePipeline stage to clone sources from bitbucket repository
    pipeline.addStage({
      stageName: "Source",
      actions: [
        new CodePipelineAction.CodeStarConnectionsSourceAction({
          actionName: "Checkout",
          owner: "repository owner name",
          repo: "repository name",
          output: outputSources,
          branch: "master",// the branch you deploy from
          connectionArn:
                  //Paste the generated `connectionArn` here 
     
        }),
      ],

    });
```
* Add Build stage to build our website, we will add a simple `./infra/lib/pipeline.yml` file to run CodeBuild project 
```bash
version: 0.2

phases:
  install:
    runtime-versions:
      nodejs: 12
    commands:
      - yarn install
  build:
    commands:
      - yarn build

artifacts:
  base-directory: ./build
  files:
    - '**/*'

cache:
  paths:
    - './node_modules/**/*'

```
```javascript
 // AWS CodePipeline stage to build website and CDK resources
    pipeline.addStage({
      stageName: "Build",
      actions: [
        // AWS CodePipeline action to run CodeBuild project
        new CodePipelineAction.CodeBuildAction({
          actionName: "Website",
          project: new CodeBuild.PipelineProject(this, "BuildWebsite", {
            projectName: "MyWebsite",
            buildSpec: CodeBuild.BuildSpec.fromSourceFilename(
              "./infra/lib/build.yml"
            ),
          }),
          input: outputSources,
          outputs: [outputWebsite],
        }),
      ],
    });
```
* The last stage will be adding deployment stage, we want to deploy the react-app to S3 bucket, and every time we make a new changes it will be deployed the S3 bucket 
 
```javascript
 // Amazon S3 bucket to store website
const bucketWebsite = new S3.Bucket(this, "Files", {
      websiteIndexDocument: "index.html",
      websiteErrorDocument: "error.html",
      publicReadAccess: true,
    });

    // AWS CodePipeline stage to deploy website and CDK resources
    pipeline.addStage({
      stageName: "Deploy",
      actions: [
        // AWS CodePipeline action to deploy website to S3
        new CodePipelineAction.S3DeployAction({
          actionName: "Website",
          input: outputWebsite,
          bucket: bucketWebsite,
        }),
      ],

    });
```
#### Resources:
[AWS Cloud Development Kit](https://aws.amazon.com/cdk/)
[Easily deploying infrastructure as code via AWS CDK](https://www.dasithsblog.com/blog/easily_deploying_cloud_infrastructure_via_CDK/)

#Wrapping Up
You can do almost the same thing using GitHub actions, you will need create a new connection check this [Create a connection to GitHub](https://docs.aws.amazon.com/dtconsole/latest/userguide/connection
s-create-github.html)
We can create deferent pipelines for deferent stages like Dev, QA, Prod 
The link to my Bitbucket repository is [here](https://bitbucket.org/mohammmedismaeel/aws-cdk-pipeline/src/master/)

Please let me know in the comments if this post was helpful and what I can do better next time!

Please follow me on Twitter at [@The_Al_Sanad](https://twitter.com/The_Al_Sanad) where I Will frequently write about serverless, devOps!