CI/CD — CodePipeline, CodeBuild, CodeDeploy
A comprehensive deep dive into AWS CI/CD services — CodePipeline orchestration, CodeBuild buildspec, CodeDeploy deployment strategies for EC2/Lambda/ECS, appspec.yml, CodeArtifact, and CodeStar Connections for the DVA-C02 exam.
AWS CI/CD Suite — Mental Model
AWS provides four managed services that together cover the full software delivery lifecycle.
Core mental model: CodePipeline is the conductor — it triggers stages in order and passes artifacts between them. CodeBuild is the build worker — it compiles, tests, and packages. CodeDeploy is the deployment engine — it rolls changes out safely to compute resources.
Part 1 — AWS CodePipeline
Pipeline Structure
A pipeline has stages, each stage has actions, and actions consume/produce artifacts stored in S3.
| Concept | Detail |
|---|---|
| Stage | Logical phase (Source, Build, Test, Deploy) |
| Action | Unit of work inside a stage — can run in parallel or sequentially |
| Artifact | Files passed between stages (stored in S3, encrypted with KMS) |
| Transition | Link between stages — can be disabled to pause the pipeline |
| Execution | One run of the pipeline triggered by a source change |
Source Providers
| Provider | Trigger mechanism |
|---|---|
| AWS CodeCommit | CloudWatch Events (push to branch) |
| GitHub / GitLab | CodeStar Connection (OAuth app webhook) |
| GitHub Enterprise | CodeStar Connection (self-hosted) |
| Amazon S3 | S3 event notification on object upload |
| Amazon ECR | CloudWatch Events on image push |
| Bitbucket | CodeStar Connection |
Manual Approval Action
1{
2 "name": "Approve-Production-Deploy",
3 "actionTypeId": {
4 "category": "Approval",
5 "owner": "AWS",
6 "provider": "Manual",
7 "version": "1"
8 },
9 "configuration": {
10 "NotificationArn": "arn:aws:sns:us-east-1:123456789012:pipeline-approvals",
11 "CustomData": "Review staging metrics before approving prod deploy.",
12 "ExternalEntityLink": "https://grafana.internal/d/staging"
13 }
14}The pipeline pauses. SNS sends an email/Slack notification. An authorized IAM user calls PutApprovalResult (Approved or Rejected) to continue or abort.
Pipeline Events & Notifications
1# CodePipeline emits EventBridge events on state changes
2# Event pattern to catch any pipeline failure:
3aws events put-rule --name "pipeline-failure-alert" --event-pattern '{
4 "source": ["aws.codepipeline"],
5 "detail-type": ["CodePipeline Pipeline Execution State Change"],
6 "detail": { "state": ["FAILED"] }
7 }'
8
9# Pipe to SNS → Slack Lambda for team notificationsPipeline as Code (CloudFormation)
1MyPipeline:
2 Type: AWS::CodePipeline::Pipeline
3 Properties:
4 RoleArn: !GetAtt PipelineRole.Arn
5 ArtifactStore:
6 Type: S3
7 Location: !Ref ArtifactBucket
8 EncryptionKey:
9 Id: !Ref PipelineKMSKey
10 Type: KMS
11 Stages:
12 - Name: Source
13 Actions:
14 - Name: SourceAction
15 ActionTypeId:
16 Category: Source
17 Owner: AWS
18 Provider: CodeStarSourceConnection
19 Version: '1'
20 Configuration:
21 ConnectionArn: !Ref GitHubConnection
22 FullRepositoryId: myorg/myapp
23 BranchName: main
24 OutputArtifacts:
25 - Name: SourceOutput
26
27 - Name: Build
28 Actions:
29 - Name: BuildAction
30 ActionTypeId:
31 Category: Build
32 Owner: AWS
33 Provider: CodeBuild
34 Version: '1'
35 Configuration:
36 ProjectName: !Ref BuildProject
37 InputArtifacts:
38 - Name: SourceOutput
39 OutputArtifacts:
40 - Name: BuildOutputPart 2 — AWS CodeBuild
How CodeBuild Works
buildspec.yml — Full Structure
1version: 0.2
2
3env:
4 variables:
5 NODE_ENV: production
6 parameter-store:
7 DB_PASSWORD: /myapp/prod/db-password # pulled from SSM at build start
8 secrets-manager:
9 NPM_TOKEN: myapp/npm-token:token # pulled from Secrets Manager
10 exported-variables:
11 - IMAGE_TAG # export for later pipeline stages
12
13phases:
14 install:
15 runtime-versions:
16 nodejs: 20
17 commands:
18 - npm ci --prefer-offline
19
20 pre_build:
21 commands:
22 - echo "Running pre-build checks..."
23 - aws ecr get-login-password --region $AWS_DEFAULT_REGION |
24 docker login --username AWS --password-stdin $ECR_REGISTRY
25 - export IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c1-7)
26
27 build:
28 commands:
29 - npm run test:ci
30 - npm run build
31 - docker build -t $ECR_REGISTRY/$ECR_REPO:$IMAGE_TAG .
32 - docker push $ECR_REGISTRY/$ECR_REPO:$IMAGE_TAG
33
34 post_build:
35 commands:
36 - echo "Writing image definition for CodeDeploy..."
37 - printf '[{"name":"app","imageUri":"%s"}]' "$ECR_REGISTRY/$ECR_REPO:$IMAGE_TAG" > imagedefinitions.json
38
39artifacts:
40 files:
41 - imagedefinitions.json
42 - appspec.yml
43 - taskdef.json
44 discard-paths: no
45
46cache:
47 paths:
48 - node_modules/**/* # cache node_modules between builds
49 - /root/.npm/**/*
50
51reports:
52 unit-test-results:
53 files:
54 - 'test-results/**/*.xml'
55 file-format: JUNITXMLBuild Environment
1# Key environment variables automatically available in every build:
2# CODEBUILD_BUILD_ID — unique build ID
3# CODEBUILD_BUILD_NUMBER — numeric build counter
4# CODEBUILD_RESOLVED_SOURCE_VERSION — full git commit SHA
5# CODEBUILD_SRC_DIR — path to checked-out source
6# AWS_DEFAULT_REGION — region where build runs
7# AWS_ACCOUNT_ID — your account ID
8# CODEBUILD_BUILD_SUCCEEDING — 1 if succeeding, 0 if failing (post_build only)| Build Environment | Description |
|---|---|
| Managed image | AWS-provided (Amazon Linux 2, Ubuntu) — easiest |
| Custom Docker image | Your own ECR/Docker Hub image — full control |
| ARM build | BUILD_GENERAL1_SMALL on ARM for multi-arch |
VPC Access
CodeBuild runs in AWS-managed infrastructure by default. To access resources in your VPC (RDS, ElastiCache, internal APIs):
1# CloudFormation — VPC config for CodeBuild project
2MyBuildProject:
3 Type: AWS::CodeBuild::Project
4 Properties:
5 VpcConfig:
6 VpcId: !Ref MyVpc
7 Subnets:
8 - !Ref PrivateSubnet1
9 - !Ref PrivateSubnet2
10 SecurityGroupIds:
11 - !Ref BuildSecurityGroupCaveat: When CodeBuild runs inside a VPC, it cannot reach the public internet unless your VPC has a NAT Gateway. S3 and other AWS services can be reached via VPC endpoints.
Local Build with CodeBuild Agent
1# Run a build locally — same environment as CodeBuild
2docker pull public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:5.0
3
4# Run the local agent
5docker run -it -v /var/run/docker.sock:/var/run/docker.sock -e IMAGE_NAME=public.ecr.aws/codebuild/amazonlinux2-x86_64-standard:5.0 -e ARTIFACTS=/tmp/artifacts -e SOURCE=/path/to/your/project public.ecr.aws/codebuild/local-builds:latestPart 3 — AWS CodeDeploy
Deployment Targets
| Compute | Agent required | Notes |
|---|---|---|
| EC2 / On-Premises | ✅ CodeDeploy agent | Installs on instance at boot |
| AWS Lambda | ❌ | Native integration via aliases + traffic shifting |
| Amazon ECS | ❌ | Integrates with ALB listener rules |
CodeDeploy for EC2 / On-Premises
Deployment Configurations
| Strategy | How it works | Downtime | Speed |
|---|---|---|---|
CodeDeployDefault.AllAtOnce | Deploy to all instances simultaneously | Yes | Fastest |
CodeDeployDefault.HalfAtATime | Deploy to 50% at a time | No | Medium |
CodeDeployDefault.OneAtATime | Deploy to one instance at a time | No | Slowest |
| Blue/Green | New ASG fleet; shift ALB traffic; terminate old | No | Fast |
appspec.yml — EC2
1version: 0.0
2os: linux
3
4files:
5 - source: /build/dist
6 destination: /var/www/app
7
8permissions:
9 - object: /var/www/app
10 owner: ec2-user
11 group: ec2-user
12 mode: 755
13 type:
14 - directory
15 - file
16
17hooks:
18 ApplicationStop:
19 - location: scripts/stop_server.sh
20 timeout: 30
21 runas: root
22
23 BeforeInstall:
24 - location: scripts/install_dependencies.sh
25 timeout: 60
26 runas: root
27
28 AfterInstall:
29 - location: scripts/change_permissions.sh
30 timeout: 30
31 runas: root
32
33 ApplicationStart:
34 - location: scripts/start_server.sh
35 timeout: 60
36 runas: root
37
38 ValidateService:
39 - location: scripts/validate_service.sh
40 timeout: 30
41 runas: ec2-userEC2 Deployment Lifecycle Hook Order
For Blue/Green deployments, additional hooks run on the new (green) instances:
BeforeAllowTraffic → traffic shifted → AfterAllowTraffic
CodeDeploy for Lambda
Lambda deployments shift traffic between two alias weights pointing to different function versions.
Lambda Deployment Configurations
| Config | Description |
|---|---|
LambdaAllAtOnce | Shift 100% immediately |
LambdaCanary10Percent5Minutes | 10% for 5 min, then 90% |
LambdaCanary10Percent30Minutes | 10% for 30 min, then 90% |
LambdaLinear10PercentEvery1Minute | +10% every 1 min (10 min total) |
LambdaLinear10PercentEvery2Minutes | +10% every 2 min (20 min total) |
LambdaLinear10PercentEvery3Minutes | +10% every 3 min (30 min total) |
LambdaLinear10PercentEvery10Minutes | +10% every 10 min (100 min total) |
| Custom | Your own percentage + interval |
appspec.yml — Lambda
1version: 0.0
2Resources:
3 - MyFunction:
4 Type: AWS::Lambda::Function
5 Properties:
6 Name: MyLambdaFunction
7 Alias: prod
8 CurrentVersion: !Ref CurrentVersion
9 TargetVersion: !Ref NewVersion
10
11Hooks:
12 - BeforeAllowTraffic: MyValidationFunction # runs before shifting traffic
13 - AfterAllowTraffic: MyMonitorFunction # runs after full shift1// BeforeAllowTraffic / AfterAllowTraffic hook Lambda
2import { CodeDeployClient, PutLifecycleEventHookExecutionStatusCommand } from '@aws-sdk/client-codedeploy';
3
4const codedeploy = new CodeDeployClient({});
5
6export async function handler(event) {
7 const { DeploymentId, LifecycleEventHookExecutionId } = event;
8
9 try {
10 // Run your validation (smoke test, canary check, etc.)
11 await runSmokeTest();
12
13 await codedeploy.send(new PutLifecycleEventHookExecutionStatusCommand({
14 deploymentId: DeploymentId,
15 lifecycleEventHookExecutionId: LifecycleEventHookExecutionId,
16 status: 'Succeeded',
17 }));
18 } catch (err) {
19 await codedeploy.send(new PutLifecycleEventHookExecutionStatusCommand({
20 deploymentId: DeploymentId,
21 lifecycleEventHookExecutionId: LifecycleEventHookExecutionId,
22 status: 'Failed', // triggers automatic rollback
23 }));
24 }
25}CodeDeploy for ECS
ECS deployments replace the current task set with a new one and shift ALB listener traffic.
1# appspec.yml — ECS
2version: 0.0
3Resources:
4 - TargetService:
5 Type: AWS::ECS::Service
6 Properties:
7 TaskDefinition: <TASK_DEFINITION>
8 LoadBalancerInfo:
9 ContainerName: app
10 ContainerPort: 8080
11 PlatformVersion: LATEST
12
13Hooks:
14 - BeforeInstall: BeforeInstallHookLambda
15 - AfterInstall: AfterInstallHookLambda
16 - AfterAllowTestTraffic: TestTrafficHookLambda
17 - BeforeAllowTraffic: BeforeAllowTrafficHookLambda
18 - AfterAllowTraffic: AfterAllowTrafficHookLambdaECS Blue/Green uses two target groups on the ALB. The new task set receives test traffic first (via a test listener on a separate port), then production traffic shifts over.
Rollback Behavior
| Trigger | Behavior |
|---|---|
| Deployment failure | Rolls back to last successful deployment revision |
| CloudWatch Alarm breach | Automatic rollback if alarm configured on deployment group |
| Manual rollback | Via console or aws deploy create-deployment with previous revision |
Important: Rollback in CodeDeploy is not an undo — it creates a new deployment of the previous revision. The deployment history always shows both the failed deployment and the rollback deployment.
Part 4 — AWS CodeArtifact
CodeArtifact is a managed artifact repository compatible with npm, PyPI, Maven, Gradle, NuGet, and Swift.
1# Authenticate npm to CodeArtifact (token valid for 12 hours)
2aws codeartifact login --tool npm --domain my-domain --domain-owner 123456789012 --repository my-repo
3
4# Now npm install reads from CodeArtifact (with upstream fallback to npmjs.com)
5npm install lodash # served from CodeArtifact cache or proxied from npm
6
7# Publish a private package
8npm publish # goes to CodeArtifact repo
9
10# Python — authenticate pip
11aws codeartifact login --tool pip --domain my-domain --repository my-repo
12pip install boto3| Concept | Detail |
|---|---|
| Domain | Container for repositories; enables cross-repo policies |
| Repository | Package store for a specific tool (npm, PyPI, etc.) |
| Upstream | Pull-through cache for public registries |
| Asset | Individual package file (tarball, wheel, etc.) |
| Authorization token | 12-hour token from GetAuthorizationToken API |
Part 5 — CodeStar Connections
CodeStar Connections provides OAuth-based integration between CodePipeline/CodeBuild and third-party Git providers.
| Provider | Connection type |
|---|---|
| GitHub.com | CodeStar Connection (OAuth app) |
| GitHub Enterprise Server | CodeStar Connection (self-hosted) |
| GitLab.com | CodeStar Connection |
| GitLab Self-Managed | CodeStar Connection |
| Bitbucket Cloud | CodeStar Connection |
Connections must be manually activated in the console once (OAuth handshake), then they can be referenced in CloudFormation/CDK pipelines without any secrets.
Full Pipeline Example (GitHub → Build → Lambda Deploy)
1# Trigger a manual pipeline execution
2aws codepipeline start-pipeline-execution --name my-pipeline
3
4# Get pipeline status
5aws codepipeline get-pipeline-state --name my-pipeline
6
7# Approve a manual approval action
8aws codepipeline put-approval-result --pipeline-name my-pipeline --stage-name Approve-Prod --action-name ManualApproval --result actionStatus=Approved,summary="Metrics look good" --token <token-from-get-pipeline-state>
9
10# Get CodeDeploy deployment status
11aws deploy get-deployment --deployment-id d-ABCDEF123
12
13# Stop a deployment (with optional rollback)
14aws deploy stop-deployment --deployment-id d-ABCDEF123 --auto-rollback-enabledDVA-C02 Quick Reference
| Topic | Key Fact |
|---|---|
| CodePipeline artifact storage | S3 bucket (encrypted with KMS) |
| CodePipeline trigger for CodeCommit | CloudWatch Events (not polling) |
| CodePipeline trigger for GitHub | CodeStar Connection (webhook) |
| Manual approval notification | SNS topic |
| CodeBuild phases order | install → pre_build → build → post_build |
| buildspec.yml default location | Root of source repository |
| CodeBuild VPC caveat | Needs NAT Gateway to reach internet from VPC |
| CodeBuild env var from SSM | parameter-store section in buildspec env block |
| CodeBuild env var from Secrets Manager | secrets-manager section in buildspec env block |
| CodeDeploy EC2 requires | CodeDeploy agent installed on instances |
| CodeDeploy Lambda requires | No agent — uses alias traffic shifting |
| CodeDeploy ECS requires | No agent — uses ALB listener rules + two target groups |
| appspec.yml EC2 hook order | ApplicationStop → BeforeInstall → Install → AfterInstall → ApplicationStart → ValidateService |
| CodeDeploy rollback mechanism | New deployment of previous revision (not an undo) |
| Lambda canary deployment | Small % first (e.g., 10%), then rest after interval |
| Lambda linear deployment | Equal % increments on a fixed schedule |
| CodeDeploy alarm rollback | CloudWatch Alarm triggers automatic rollback |
| CodeArtifact token validity | 12 hours |
| CodeArtifact upstream | Pull-through cache for public package registries |
| Cross-account pipeline | CodePipeline assumes role in target account for deploy actions |
| Pipeline notification events | EventBridge (CodePipeline emits state change events) |
Practice Questions9
Q1. A development team uses AWS CodePipeline. After a code push to CodeCommit, the pipeline triggers CodeBuild. CodeBuild compiles the code but the unit tests fail. What happens to the pipeline?
Select one answer before revealing.
Q2. A developer wants to run unit tests and integration tests in parallel during a CodePipeline Build stage to reduce total build time. Which CodeBuild feature supports running multiple build groups in parallel?
Select one answer before revealing.
Q3. A team uses AWS CodeDeploy to deploy to EC2 instances. They want to gradually shift traffic from the old version to the new version — starting with 10% and shifting 100% after 10 minutes if no alarms trigger. Which deployment configuration should be used?
Select one answer before revealing.
Q4. A developer writes a buildspec.yml for CodeBuild. The build has 4 phases. Which of the following represents the correct order of phases in a CodeBuild build?
Select one answer before revealing.
Q5. A developer uses AWS SAM to define a Lambda function and API Gateway. After running `sam deploy`, the developer needs to test the Lambda function locally before the next deployment. Which command should be used?
Select one answer before revealing.
Q6. A developer needs to create a CodePipeline that builds a Docker image, pushes it to ECR, and updates an ECS service. The pipeline must pass the ECR image URI from the Build stage to the Deploy stage. How is data passed between CodePipeline stages?
Select one answer before revealing.
Q7. A team wants to enforce a manual approval before production deployments in their CodePipeline. A Slack notification must be sent to the ops team when approval is required. Which CodePipeline action type should be added?
Select one answer before revealing.
Q8. A developer uses CodeDeploy to deploy a new version of a Lambda function. They want to automatically roll back if the p99 latency CloudWatch alarm triggers within 10 minutes of deployment. Which CodeDeploy feature enables this?
Select one answer before revealing.
Q9. A developer uses AWS CloudFormation to deploy infrastructure. After updating a stack, the deployment fails. CloudFormation shows ROLLBACK_IN_PROGRESS. What does this mean and what is the developer's next step?
Select one answer before revealing.