Skip to content

Bootstrapping AWS CDK Automation With Amazon CodeCatalyst

Posted on:January 24, 2024Β atΒ 03:57 PM

image

Abstract

  • A step-by-step guide on establishing an AWS CDK setup alongside Amazon CodeCatalyst from the ground up, enabling the creation of a comprehensive CI/CD pipeline for your infrastructure.

  • AWS CDK is fantastic for overseeing your entire infrastructure as code, but when multiple developers are involved in modifying the infrastructure, the situation can become chaotic without a proper mechanism like a CI/CD pipeline. Absence of such a system makes coordinating and communicating changes to the infrastructure a challenging task, and this challenge amplifies as more individuals participate in the modification process.

  • This tutorial will guide you through setting up a CI/CD pipeline using Amazon CodeCatalyst and AWS CDK for building To-Do web application

    <img src=https://raw.githubusercontent.com/vumdao/codecatalyst-cdk-todo-web-app/master/docs/images/diagram.png width=900>

Table Of Contents

Open Table Of Contents

πŸš€ Setting up a CodeCatalyst Project, Repo, and Environment

  1. Login to CodeCatalyst and go to your Space (Create one if you don’t have)
  2. Create a project from scratch

<img src=https://raw.githubusercontent.com/vumdao/codecatalyst-cdk-todo-web-app/master/docs/images/create-project.png width=700>

  1. Create repository to store code and workflows of the project

<img src=https://raw.githubusercontent.com/vumdao/codecatalyst-cdk-todo-web-app/master/docs/images/create-repo.png width=700>

<img src=https://raw.githubusercontent.com/vumdao/codecatalyst-cdk-todo-web-app/master/docs/images/create-repo-details.png width=700>

  1. Create CICD Environments which associates to AWS account for deploying our infrastructure.

<img src=https://raw.githubusercontent.com/vumdao/codecatalyst-cdk-todo-web-app/master/docs/images/create-cicd-env.png width=700>

  1. Create IAM role for codecatalyst to consume during running workflows. It should be already created while you create the Space or you can customize the others

<img src=https://raw.githubusercontent.com/vumdao/codecatalyst-cdk-todo-web-app/master/docs/images/iam-role.png width=700>

πŸš€ Design workflows

  • Workflows directory

    .codecatalyst
    └── workflows
        └── main_fullstack_workflow.yaml
  • Workflows is triggered by PUSH of branch main and includes following Actions

    Triggers:
      - Branches:
          - main
        Type: PUSH
    1. FrontendBuildAndPackage build react app, target build which is shared to cross-actions by Artifacts of Outputs
    FrontendBuildAndPackage:
      Identifier: aws/build@v1
      Inputs:
        Sources:
          - WorkflowSource
      Outputs:
        Artifacts:
          - Name: frontend
            Files:
              - "**/*"
      Configuration:
        Steps:
          - Run: cd static-assets/frontend
          - Run: npm install
          - Run: echo "REACT_APP_SERVICE_URL=/api/todos" > ".env"
          - Run: npm run build
    1. FrontendTest Test frontend code
    FrontendTest:
        Identifier: aws/managed-test@v1
        Inputs:
          Sources:
            - WorkflowSource
        Outputs:
          AutoDiscoverReports:
            IncludePaths:
              - frontend/**/*.xml
            ExcludePaths:
              - frontend/node_modules/**/*
            ReportNamePrefix: AutoDiscovered
            Enabled: true
            SuccessCriteria:
              PassRate: 100
        Configuration:
          Steps:
            - Run: cd static-assets/frontend
            - Run: npm install
            - Run: npm test -- --coverage --watchAll=false;
    1. CDKBootstrapAction Run cdk bootstrap for the region of the account with latest CDK version. This action depends on FrontendTest and FrontendBuildAndPackage
    CDKBootstrapAction:
      Identifier: aws/cdk-bootstrap@v1
      Configuration:
        Region: us-east-1
        CdkCliVersion: latest
      Environment:
        Name: default_environment
        Connections:
          - Name: "123456789012"
            Role: CodeCatalystWorkflowDevelopmentRole-simflexcloud
      DependsOn:
        - FrontendTest
        - FrontendBuildAndPackage
    1. CDKDeploy Download build target of FrontendBuildAndPackage and trigger cdk deploy, this action depends on CDKBootstrapAction. Here I don’t use the defined action aws/cdk-deploy@v1 of CodeCatalyst because I’d like to use projen and pnmp in CDK and handle copying frontend target build
    CDKDeploy:
      Identifier: aws/build@v1
      Inputs:
        Artifacts:
          - frontend
      Outputs:
        AutoDiscoverReports:
          IncludePaths:
            - "**/*"
          ExcludePaths:
            - "*/.codecatalyst/workflows/*"
          ReportNamePrefix: AutoDiscovered
          Enabled: true
      Configuration:
        Steps:
          - Run: cp -r static-assets/frontend/build static-assets/cdkStack/src/lib/frontend/
          - Run: cd static-assets/cdkStack
          - Run: npm install -g pnpm
          - Run: pnpm i --no-frozen-lockfile
          - Run: export CDK_DEPLOY_ACCOUNT=123456789012
          - Run: export CDK_DEPLOY_REGION=us-east-1
          - Run: pnpm dlx projen deploy --all --require-approval never
      Environment:
        Name: default_environment
        Connections:
          - Name: "123456789012"
            Role: CodeCatalystWorkflowDevelopmentRole-simflexcloud
      DependsOn:
        - FrontendTest
        - FrontendBuildAndPackage
  • Use EC2 compute type for CodeCatalyst workflows

    Compute:
      Type: EC2
      Fleet: Linux.x86-64.Large

πŸš€ Source code and CDK stacks

  • Structure

    • cdkStack Define CDK stacks and use projen for configuration management as well as pnpm
    • frontend Frontend react app
    static-assets
    β”œβ”€β”€ cdkStack
    β”‚Β Β  β”‚Β Β  β”œβ”€β”€ LICENSE
    β”‚Β Β  β”‚Β Β  β”œβ”€β”€ README.md
    β”‚Β Β  β”‚Β Β  β”œβ”€β”€ cdk.json
    β”‚Β Β  β”‚Β Β  β”œβ”€β”€ package.json
    β”‚Β Β  β”‚Β Β  β”œβ”€β”€ src
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ bin
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  └── main.ts
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ lib
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ backend
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ lambda
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ CorsAPIGatewayProxyResult.ts
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Todo.ts
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ addTodo.ts
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ deleteTodo.ts
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ getTodo.ts
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”œβ”€β”€ getTodos.ts
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  └── updateTodo.ts
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  └── todo-api-stack.ts
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β  └── frontend
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β      β”œβ”€β”€ build
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β      β”œβ”€β”€ constants.ts
    β”‚Β Β  β”‚Β Β  β”‚Β Β  β”‚Β Β      └── frontend-stack.ts
    β”‚Β Β  β”‚Β Β  β”‚Β Β  └── main.ts
    β”‚Β Β  β”‚Β Β  β”œβ”€β”€ test
    β”‚Β Β  β”‚Β Β  β”‚Β Β  └── todo-api.test.ts
    β”‚Β Β  β”‚Β Β  β”œβ”€β”€ tsconfig.dev.json
    β”‚Β Β  β”‚Β Β  └── tsconfig.json
    β”‚Β Β  └── frontend
    β”‚Β Β      β”œβ”€β”€ README.md
    β”‚Β Β      β”œβ”€β”€ babel.config.js
    β”‚Β Β      β”œβ”€β”€ jest.config.js
    β”‚Β Β      β”œβ”€β”€ package.json
    β”‚Β Β      β”œβ”€β”€ public
    β”‚Β Β      β”‚Β Β  β”œβ”€β”€ index.html
    β”‚Β Β      β”‚Β Β  β”œβ”€β”€ manifest.json
    β”‚Β Β      β”‚Β Β  └── robots.txt
    β”‚Β Β      β”œβ”€β”€ src
    β”‚Β Β      β”‚Β Β  β”œβ”€β”€ App.css
    β”‚Β Β      β”‚Β Β  β”œβ”€β”€ App.test.tsx
    β”‚Β Β      β”‚Β Β  β”œβ”€β”€ App.tsx
    β”‚Β Β      β”‚Β Β  β”œβ”€β”€ index.css
    β”‚Β Β      β”‚Β Β  β”œβ”€β”€ index.tsx
    β”‚Β Β      β”‚Β Β  β”œβ”€β”€ react-app-env.d.ts
    β”‚Β Β      β”‚Β Β  β”œβ”€β”€ reportWebVitals.ts
    β”‚Β Β      β”‚Β Β  β”œβ”€β”€ setupTests.ts
    β”‚Β Β      β”‚Β Β  β”œβ”€β”€ to-do.api.ts
    β”‚Β Β      β”‚Β Β  └── to-do.types.ts
    β”‚Β Β      └── tsconfig.json
    β”œβ”€β”€ tsconfig.dev.json
    β”œβ”€β”€ tsconfig.json
    └── yarn.lock

πŸš€ Push source code to repo

  • Init the repo and add repo URL which is created from the above as origin

    <img src=https://raw.githubusercontent.com/vumdao/codecatalyst-cdk-todo-web-app/master/docs/images/clone-repo.png width=700>

    ➜  git init
    Initialized empty Git repository in /Users/vudao/workspace/codecatalyst/cdk-todo-web-app/.git/
    ➜  git remote add origin https://vumdao@git.us-west-2.codecatalyst.aws/v1/simflexcloud/cdk-todo-web-app/cdk-todo-web-app
    ➜  git branch --set-upstream-to=origin/main main
    branch 'main' set up to track 'origin/main' by rebasing.
    ➜  git pull
    ➜  git add .
    ➜  git commit -m "Init commit"
    ➜  git push origin main

πŸš€ Workflows Runs

πŸš€ Conclusion

Congratulations! You’ve successfully bootstrapped and initialized AWS CDK with CodeCatalyst, and you can now deploy infrastructure changes or update frontend/backend using a pull request workflow.


Reference