AWS DevOps tools automate the path from code commit to production deployment. CodePipeline orchestrates the workflow, CodeBuild compiles and tests, CodeDeploy handles deployments, and CloudFormation/CDK manages infrastructure. Together they enable continuous integration and continuous delivery (CI/CD) on AWS.

CI/CD Pipeline Overview

  Developer Push → Source (CodeCommit/GitHub)
                      ↓
                 CodeBuild (test, build, scan)
                      ↓
                 Manual Approval (optional)
                      ↓
                 CodeDeploy / ECS / Lambda
                      ↓
                 Production
  
Service Role
CodeCommit Git repository (or use GitHub/GitLab/Bitbucket)
CodeBuild Build, test, package (like Jenkins/GitHub Actions runners)
CodePipeline Orchestrates stages and actions
CodeDeploy Deploy to EC2, ECS, Lambda, on-premises
CloudFormation/CDK Infrastructure as Code

CodeBuild Project

  # buildspec.yml — placed in repository root
version: 0.2

phases:
  install:
    runtime-versions:
      nodejs: 20
    commands:
      - npm ci
  pre_build:
    commands:
      - npm run lint
      - npm test
  build:
    commands:
      - npm run build
      - docker build -t $ECR_REPO:$CODEBUILD_RESOLVED_SOURCE_VERSION .
  post_build:
    commands:
      - aws ecr get-login-password | docker login --username AWS --password-stdin $ECR_URI
      - docker push $ECR_REPO:$CODEBUILD_RESOLVED_SOURCE_VERSION
      - printf '{"ImageURI":"%s"}' $ECR_REPO:$CODEBUILD_RESOLVED_SOURCE_VERSION > imageDetail.json

artifacts:
  files:
    - imageDetail.json
    - appspec.yaml
    - taskdef.json
  
  # Create CodeBuild project
aws codebuild create-project \
    --name myapp-build \
    --source type=GITHUB,location=https://github.com/org/myapp.git \
    --artifacts type=NO_ARTIFACTS \
    --environment type=LINUX_CONTAINER,image=aws/codebuild/amazonlinux2-x86_64-standard:5.0,computeType=BUILD_GENERAL1_MEDIUM,privilegedMode=true \
    --service-role arn:aws:iam::123:role/CodeBuildServiceRole
  

CodePipeline

  # Create pipeline (simplified — use Console or CloudFormation for full setup)
aws codepipeline create-pipeline \
    --pipeline '{
        "name": "myapp-pipeline",
        "roleArn": "arn:aws:iam::123:role/CodePipelineServiceRole",
        "artifactStore": {"type": "S3", "location": "myapp-pipeline-artifacts"},
        "stages": [
            {
                "name": "Source",
                "actions": [{
                    "name": "Source",
                    "actionTypeId": {"category": "Source", "owner": "AWS", "provider": "CodeStarSourceConnection", "version": "1"},
                    "configuration": {"ConnectionArn": "arn:aws:codestar-connections:us-east-1:123:connection/xxx", "FullRepositoryId": "org/myapp", "BranchName": "main"},
                    "outputArtifacts": [{"name": "SourceOutput"}]
                }]
            },
            {
                "name": "Build",
                "actions": [{
                    "name": "Build",
                    "actionTypeId": {"category": "Build", "owner": "AWS", "provider": "CodeBuild", "version": "1"},
                    "configuration": {"ProjectName": "myapp-build"},
                    "inputArtifacts": [{"name": "SourceOutput"}],
                    "outputArtifacts": [{"name": "BuildOutput"}]
                }]
            },
            {
                "name": "Deploy",
                "actions": [{
                    "name": "Deploy",
                    "actionTypeId": {"category": "Deploy", "owner": "AWS", "provider": "ECS", "version": "1"},
                    "configuration": {
                        "ClusterName": "production",
                        "ServiceName": "myapp-service",
                        "FileName": "imagedefinitions.json"
                    },
                    "inputArtifacts": [{"name": "BuildOutput"}]
                }]
            }
        ]
    }'
  

Deployment Strategies

Strategy Downtime Rollback Speed Use Case
Rolling None Slow Simple updates
Blue/Green None Instant (switch traffic) Zero-downtime production
Canary None Fast (partial traffic) Risk mitigation
In-place Brief Manual Dev/staging

ECS Blue/Green with CodeDeploy

  {
    "version": 1,
    "Resources": [{
        "TargetService": {
            "Type": "AWS::ECS::Service",
            "Properties": {
                "TaskDefinition": "arn:aws:ecs:us-east-1:123:task-definition/myapp:5",
                "LoadBalancerInfo": {
                    "ContainerName": "myapp",
                    "ContainerPort": 8080
                }
            }
        }
    }]
}
  

CodeDeploy shifts ALB traffic from blue (current) to green (new) target group with configurable wait times and automatic rollback on CloudWatch alarm breach.

Infrastructure as Code

  // lib/pipeline-stack.ts
import * as cdk from 'aws-cdk-lib';
import * as pipelines from 'aws-cdk-lib/pipelines';

export class PipelineStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string) {
    super(scope, id);

    const pipeline = new pipelines.CodePipeline(this, 'Pipeline', {
      pipelineName: 'MyAppPipeline',
      synth: new pipelines.ShellStep('Synth', {
        input: pipelines.CodePipelineSource.gitHub('org/myapp', 'main'),
        commands: ['npm ci', 'npm run build', 'npx cdk synth'],
      }),
    });

    const deployStage = new MyAppStage(this, 'Production');
    pipeline.addStage(deployStage);
  }
}
  
  # Deploy pipeline infrastructure
cdk deploy PipelineStack
  

CloudFormation

  # Validate template
aws cloudformation validate-template --template-body file://template.yaml

# Deploy stack
aws cloudformation deploy \
    --template-file template.yaml \
    --stack-name myapp-production \
    --capabilities CAPABILITY_IAM \
    --parameter-overrides Environment=production
  

IAM Roles for CI/CD

Role Permissions
CodePipeline service role Start CodeBuild, invoke CodeDeploy, access S3 artifacts
CodeBuild service role ECR push, CloudWatch Logs, SSM parameters
CodeDeploy service role ECS/EC2/Lambda update, ALB target group swap
Deployment role (cross-account) AssumeRole in target account for multi-account

Principle of least privilege — scope ECR push to specific repositories, ECS deploy to specific services.

Secrets in Pipelines

  # Store secrets in SSM Parameter Store (SecureString)
aws ssm put-parameter \
    --name /myapp/prod/database-url \
    --value "postgresql://..." \
    --type SecureString

# Reference in buildspec.yml
# env:
#   parameter-store:
#     DATABASE_URL: /myapp/prod/database-url
  

Never commit secrets to Git — use SSM Parameter Store or Secrets Manager with IAM-scoped access.

Real-World Scenario: Full CI/CD for ECS Microservice

  GitHub (main branch)
    ↓ webhook
CodePipeline
    ├── Source: GitHub via CodeStar Connection
    ├── Build: CodeBuild
    │   ├── npm ci && npm test
    │   ├── docker build + push to ECR
    │   └── vulnerability scan (ECR scan on push)
    ├── Approval: Manual (production only)
    └── Deploy: CodeDeploy Blue/Green to ECS
        ├── New task definition registered
        ├── Green target group receives traffic gradually
        └── CloudWatch alarm rollback if 5xx > threshold
  
Stage Duration Failure Action
Source 10s Notify Slack
Build + Test 3-5 min Block deploy, notify
Approval Manual Timeout after 7 days
Deploy 5-10 min Auto-rollback on alarm

CodePipeline vs GitHub Actions vs Jenkins

Feature CodePipeline GitHub Actions Jenkins
AWS integration Native Via credentials Via plugins
Managed runners CodeBuild GitHub-hosted Self-managed
Cost Per pipeline action Free tier + minutes EC2/hosting cost
Multi-cloud AWS-focused Any cloud Any cloud
Setup complexity Medium Low High (self-managed)

Use CodePipeline when fully on AWS; GitHub Actions for polyglot repos already on GitHub.

Common Mistakes

  1. No automated tests in pipeline — deploys broken code to production
  2. Overly permissive CI/CD IAM roles — pipeline compromise = full account access
  3. No manual approval for production — every commit shouldn’t auto-deploy to prod
  4. Missing rollback strategy — blue/green without CloudWatch alarm rollback
  5. Secrets in buildspec or environment variables — use SSM/Secrets Manager
  6. No artifact immutability — rebuild same commit differently each time

Troubleshooting

Issue Diagnosis Fix
Pipeline stuck in Source GitHub connection expired Re-authorize CodeStar connection
CodeBuild fails Check build logs in CloudWatch Fix buildspec; verify IAM permissions
Deploy succeeds but app broken Health check passes but app errors Add integration tests in build stage
Slow pipeline Large Docker layers, no cache Multi-stage Dockerfile; CodeBuild cache
Cross-account deploy fails Trust policy or role assumption Verify AssumeRole permissions

Best Practices

  • Automate everything — build, test, deploy, rollback
  • Include unit, integration, and security scans in build stage
  • Use blue/green or canary deployments for production
  • Implement manual approval gates for production environments
  • Store infrastructure as code alongside application code
  • Use separate AWS accounts for dev/staging/production (AWS Organizations)
  • Monitor pipeline metrics — build duration, failure rate, deploy frequency
  • Immutable artifacts — build once, deploy same artifact everywhere

Next: ECS/EKS Containers — Expert Deep Dive.