Skip to main content

Continuous Delivery with AWS CodePipeline

Tobias Jonas Tobias Jonas 3 min read
Continuous Delivery with AWS CodePipeline

Continuous Delivery is an essential part of modern software development. AWS offers a complete CI/CD ecosystem with CodePipeline, CodeBuild, and CodeDeploy. In this post, we show how to set up a deployment pipeline for a Scala application.

AWS DevOps Tools Overview

AWS CodePipeline

CodePipeline is the orchestrating service that connects the individual steps of a deployment pipeline. It defines the workflow from source code change to deployment.

AWS CodeBuild

CodeBuild is a fully managed build service. It compiles source code, runs tests, and produces deployable artifacts.

AWS CodeDeploy

CodeDeploy automates deployment to EC2 instances, Lambda functions, or ECS services.

Pipeline Architecture

A typical pipeline consists of the following stages:

Source → Build → Test → Deploy (Staging) → Deploy (Production)

Step 1: Setting Up Source Stage

The source stage monitors the code repository for changes. AWS supports various sources:

  • AWS CodeCommit - AWS’s own Git service
  • GitHub - Via GitHub Connections
  • Bitbucket - Via Bitbucket Connections
  • S3 - For artifact-based deployments

Example: GitHub Connection

# cloudformation-template.yaml
SourceStage:
  Actions:
    - Name: Source
      ActionTypeId:
        Category: Source
        Owner: AWS
        Provider: CodeStarSourceConnection
        Version: 1
      Configuration:
        ConnectionArn: !Ref GitHubConnection
        FullRepositoryId: myorg/myrepo
        BranchName: main
      OutputArtifacts:
        - Name: SourceCode

Step 2: Build Stage with CodeBuild

buildspec.yml for Scala/sbt

version: 0.2

phases:
  install:
    runtime-versions:
      java: corretto11
  pre_build:
    commands:
      - echo "Installing sbt..."
      - curl -fL "https://github.com/sbt/sbt/releases/download/v1.9.0/sbt-1.9.0.tgz" | tar xz
      - export PATH="$PATH:./sbt/bin"
  build:
    commands:
      - echo "Building..."
      - sbt clean compile
      - sbt test
      - sbt "Docker / stage"
  post_build:
    commands:
      - echo "Build completed"
      - docker build -t $ECR_REPO:$CODEBUILD_RESOLVED_SOURCE_VERSION .
      - docker push $ECR_REPO:$CODEBUILD_RESOLVED_SOURCE_VERSION

artifacts:
  files:
    - appspec.yml
    - taskdef.json
  discard-paths: no

cache:
  paths:
    - '/root/.ivy2/**/*'
    - '/root/.sbt/**/*'

Creating CodeBuild Project

BuildProject:
  Type: AWS::CodeBuild::Project
  Properties:
    Name: my-scala-build
    ServiceRole: !GetAtt CodeBuildRole.Arn
    Artifacts:
      Type: CODEPIPELINE
    Environment:
      Type: LINUX_CONTAINER
      ComputeType: BUILD_GENERAL1_MEDIUM
      Image: aws/codebuild/amazonlinux2-x86_64-standard:4.0
      PrivilegedMode: true
      EnvironmentVariables:
        - Name: ECR_REPO
          Value: !Sub ${AWS::AccountId}.dkr.ecr.${AWS::Region}.amazonaws.com/my-app
    Source:
      Type: CODEPIPELINE
      BuildSpec: buildspec.yml
    Cache:
      Type: S3
      Location: !Sub ${CacheBucket}/build-cache

Step 3: Deploy Stage

Option A: ECS Deployment

For containerized applications, ECS is a good choice:

DeployStage:
  Actions:
    - Name: Deploy
      ActionTypeId:
        Category: Deploy
        Owner: AWS
        Provider: ECS
        Version: 1
      Configuration:
        ClusterName: !Ref ECSCluster
        ServiceName: !Ref ECSService
        FileName: imagedefinitions.json
      InputArtifacts:
        - Name: BuildOutput

Option B: Lambda Deployment

For serverless applications:

DeployStage:
  Actions:
    - Name: Deploy
      ActionTypeId:
        Category: Deploy
        Owner: AWS
        Provider: CloudFormation
        Version: 1
      Configuration:
        ActionMode: CREATE_UPDATE
        StackName: my-lambda-stack
        TemplatePath: BuildOutput::template.yaml

Step 4: Approval Stage (optional)

For production deployments, a manual approval is recommended:

ApprovalStage:
  Actions:
    - Name: ManualApproval
      ActionTypeId:
        Category: Approval
        Owner: AWS
        Provider: Manual
        Version: 1
      Configuration:
        NotificationArn: !Ref ApprovalTopic
        CustomData: "Please approve deployment to production"

Complete Pipeline

Pipeline:
  Type: AWS::CodePipeline::Pipeline
  Properties:
    Name: my-scala-pipeline
    RoleArn: !GetAtt PipelineRole.Arn
    Stages:
      - Name: Source
        Actions:
          - Name: Source
            # ... Source Configuration
      - Name: Build
        Actions:
          - Name: Build
            # ... Build Configuration
      - Name: DeployStaging
        Actions:
          - Name: Deploy
            # ... Staging Deployment
      - Name: Approval
        Actions:
          - Name: ManualApproval
            # ... Approval Configuration
      - Name: DeployProduction
        Actions:
          - Name: Deploy
            # ... Production Deployment

Best Practices

1. Infrastructure as Code

The entire pipeline should be defined as CloudFormation or CDK. This makes it versioned and reproducible.

2. Secrets Management

Use AWS Secrets Manager or Parameter Store for credentials:

EnvironmentVariables:
  - Name: DB_PASSWORD
    Type: SECRETS_MANAGER
    Value: my-secret-name:password

3. Use Caching

CodeBuild caching significantly speeds up builds - especially for sbt with its many dependencies.

4. Set Up Notifications

SNS notifications for build failures:

NotificationRule:
  Type: AWS::CodeStarNotifications::NotificationRule
  Properties:
    Name: pipeline-notifications
    Resource: !Sub arn:aws:codepipeline:${AWS::Region}:${AWS::AccountId}:${Pipeline}
    EventTypeIds:
      - codepipeline-pipeline-pipeline-execution-failed
    Targets:
      - TargetType: SNS
        TargetAddress: !Ref NotificationTopic

Conclusion

AWS CodePipeline provides a complete CI/CD solution that seamlessly integrates into the AWS ecosystem. For teams already using AWS, it’s a natural choice. The combination of CodePipeline, CodeBuild, and various deployment options enables flexible and robust deployment workflows.

At innFactory, we successfully use AWS CodePipeline for our cloud projects and help companies optimize their CI/CD processes on AWS.

Tobias Jonas
Written by Tobias Jonas CEO

Cloud-Architekt und Experte für AWS, Google Cloud, Azure und STACKIT. Vor der Gründung der innFactory bei Siemens und BMW tätig.

LinkedIn