DevOps with CodePipeline
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
AWS CDK (Recommended)
// 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
- No automated tests in pipeline — deploys broken code to production
- Overly permissive CI/CD IAM roles — pipeline compromise = full account access
- No manual approval for production — every commit shouldn’t auto-deploy to prod
- Missing rollback strategy — blue/green without CloudWatch alarm rollback
- Secrets in buildspec or environment variables — use SSM/Secrets Manager
- 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.