CI/CD for AWS CDK with GitHub Actions

Automate your infrastructure deployments directly from your source control. This guide provides a complete workflow for setting up a GitHub Actions pipeline to build, test, and deploy your AWS CDK stacks.

Automating your infrastructure deployments is a cornerstone of modern DevOps. For teams using the AWS CDK and hosting their code on GitHub, GitHub Actions provides a powerful and convenient way to create a full CI/CD pipeline. This allows you to automatically build, test, and deploy your infrastructure whenever you push changes to your repository.

This guide provides a complete workflow for setting up a CI/CD pipeline for your AWS CDK project using GitHub Actions.

The Goal: A Pipeline for Pull Requests and Merges

Our pipeline will have two main triggers:

  1. On Pull Request: When a pull request is opened, the pipeline will run unit tests and perform a cdk diff to show a preview of the infrastructure changes.
  2. On Merge to main: When a pull request is merged into the main branch, the pipeline will run tests and then automatically deploy the changes to your AWS account.

Step 1: Configure AWS Credentials in GitHub

First, you need to securely provide AWS credentials to your GitHub Actions workflow. The best practice is to use OpenID Connect (OIDC), which allows your workflow to assume an IAM role without needing to store long-lived access keys.

  1. Create an IAM OIDC Provider in your AWS account for GitHub.
  2. Create an IAM Role that the GitHub Actions workflow will assume. This role needs permissions to perform CloudFormation deployments and any other actions your CDK stack requires.
  3. Establish a Trust Relationship between the role and the OIDC provider, scoping it to your specific GitHub repository.
  4. Store the IAM Role ARN as a secret in your GitHub repository's settings (e.g., AWS_IAM_ROLE_ARN).

Step 2: Create the GitHub Actions Workflow File

In your repository, create a new file at .github/workflows/deploy.yml. This YAML file will define your CI/CD pipeline.

Here is a complete workflow that implements our desired logic:

name: Deploy CDK Stack

on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write # Required for OIDC
      contents: read

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          role-to-assume: ${{ secrets.AWS_IAM_ROLE_ARN }}
          aws-region: us-east-1 # Change to your region

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '18'

      - name: Install dependencies
        run: npm install

      - name: Run unit tests
        run: npm test

      - name: CDK Diff on Pull Request
        if: github.event_name == 'pull_request'
        run: npx cdk diff

      - name: CDK Deploy on Merge
        if: github.event_name == 'push' && github.ref == 'refs/heads/main'
        run: npx cdk deploy --require-approval never

Breaking Down the Workflow

  • on: This section defines the triggers. The workflow runs on any push or pull_request to the main branch.

  • jobs: We define a single job named deploy that runs on an Ubuntu runner.

  • permissions: This is critical for OIDC. It grants the workflow permission to request a JWT from GitHub, which is then used to assume the IAM role in AWS.

  • Checkout code: The standard action to check out your repository's code.

  • Configure AWS Credentials: This official AWS action handles the OIDC authentication flow. It uses the AWS_IAM_ROLE_ARN secret you created to assume the IAM role, making temporary AWS credentials available to subsequent steps.

  • Setup Node.js and Install dependencies: These steps prepare the environment by installing Node.js and your project's npm dependencies, including the AWS CDK.

  • Run unit tests: This step executes your project's test suite (npm test). If the tests fail, the pipeline stops, preventing a broken deployment.

  • CDK Diff on Pull Request: This step is conditional. The if statement ensures it only runs when the triggering event is a pull_request. It executes cdk diff, which will appear in the pull request's checks, allowing reviewers to see exactly what infrastructure will change.

  • CDK Deploy on Merge: This step is also conditional. It only runs on a push to the main branch (which happens on a merge). It executes cdk deploy with the --require-approval never flag to run non-interactively. This is the step that actually deploys your infrastructure.

Conclusion

With this single workflow file, you have a robust CI/CD pipeline for your AWS CDK project. This automated process enforces testing, provides visibility into changes through pull requests, and ensures that your main branch always represents your deployed infrastructure.

By integrating your IaC with a CI/CD pipeline, you move from manual, error-prone deployments to a reliable, automated, and auditable process, which is a fundamental practice of modern DevOps.