AWS CI/CD — CodePipeline, CodeBuild, CodeDeploy & CodeCommit

A fully managed Source → Build → Test → Deploy toolchain that automates getting application changes from a repository into production, without you running Jenkins masters or writing your own deployment scripts. This module pairs deep "how it actually works" understanding with the exam-reasoning layer the Developer Associate exam tests — including a critical, explicit flag on two services AWS has deprecated for new customers.

Deployment — primary exam domain Automation — via EventBridge Legacy — CodeCommit & CodeStar deprecated for new customers
4
Core services in scope this file
3
CodeDeploy compute platforms
2
Deployment types — in-place, blue/green
Jul 2024
CodeCommit stopped onboarding new customers
⚠️ Read this before anything else — CodeCommit and CodeStar are deprecated for new customers

Effective July 25, 2024, AWS CodeCommit stopped onboarding new customers — an AWS account that had never created a CodeCommit repository before that date cannot create one now. Existing customers with existing repositories are unaffected and can keep using them, but CodeCommit receives no new features. AWS CodeStar (the older "one-click project template" service that used to bundle CodeCommit + CodeBuild + CodeDeploy + CodePipeline together) was deprecated just days later — July 31, 2024 — and its console has been retired. Neither should be presented as the current best-practice answer for a brand-new project. The exam may still test legacy knowledge of both (how CodeCommit triggers a pipeline, what CodeStar used to bundle), but the real-world — and increasingly the exam's own — expected answer for "connect a Git source to CodePipeline" today is GitHub, Bitbucket, or GitLab via AWS CodeConnections (the current name for what was originally called CodeStar Connections — the connection mechanism itself is not deprecated, only the CodeStar project-template product is). This distinction — CodeStar (deprecated) vs CodeStar Connections/CodeConnections (current, actively used) — is a frequently-tested trap and is covered in depth in the Components and Best Practices tabs.

How These Services Actually Work Together

The Core Mechanism — Orchestration vs. Execution
⚠️ The Recurring Exam Theme

Nearly every CI/CD question on this exam tests one of three things: (1) can you match the right config file to the right servicebuildspec.yml is CodeBuild, appspec.yml is CodeDeploy, and mixing them up is the single most common distractor pattern; (2) do you know which deployment type is valid for which compute platform — in-place only exists for EC2/On-Premises, while blue/green spans EC2/On-Premises, Lambda, and ECS but means something structurally different on each one; and (3) can you correctly identify that CodeCommit and CodeStar are legacy and steer a "new project, new Git repo" scenario toward GitHub/Bitbucket/GitLab via CodeConnections instead.

Exam Domain Mapping (DVA-C02)

DomainWhere CI/CD Shows Up
Domain 1 — Development with AWS Services (32%)Writing buildspec.yml/appspec.yml, using the CodeBuild/CodeDeploy/CodePipeline SDKs and CLI, packaging Lambda/container artifacts for deployment
Domain 2 — Security (26%)Service roles per stage, iam:PassRole, storing secrets referenced from buildspec in Secrets Manager/Parameter Store rather than hardcoding them
Domain 3 — Deployment (24%)The centerpiece domain for this file — pipeline design, deployment strategies, deployment configurations, rollback behavior
Domain 4 — Troubleshooting & Optimization (18%)Diagnosing a failed build from CodeBuild logs, diagnosing a stuck/failed CodeDeploy deployment via lifecycle event logs, tuning build performance with caching

CI/CD is one of the highest-yield topic clusters on DVA-C02 — it is explicitly named in the exam guide's Deployment domain and recurs inside Domain 1 and Domain 2 questions too, so treat this file as core material, not a side topic.

Decision Tree — Mental Model

Need

Automatically build, test, and release application changes whenever code changes, without managing build servers or hand-writing deployment scripts

Developer Goal

A continuous integration / continuous delivery pipeline, fully managed, triggered by a source-control event

AWS Services

AWS CodePipeline (orchestration) + AWS CodeBuild (build/test) + AWS CodeDeploy (deploy)

Source: GitHub/Bitbucket/GitLab via CodeConnections Source (legacy): CodeCommit Source: ECR / S3 Build & Test: CodeBuild Deploy: CodeDeploy (EC2/On-Prem, ECS, Lambda) Deploy alt: CloudFormation / Elastic Beanstalk / S3
Implementation

Define stages/actions in CodePipeline; buildspec.yml drives what CodeBuild does; appspec.yml + a deployment group drive what CodeDeploy does

Monitoring

CloudWatch Logs (build output), CloudWatch Alarms (rollback trigger source), CloudTrail (API activity), SNS (manual approval / notifications)

Remediation

CodeDeploy automatic rollback on deployment failure and/or CloudWatch alarm breach; a manual approval action gates the production Deploy stage

Final Summary

Must Memorize
  • buildspec.yml phases in fixed order: install → pre_build → build → post_build
  • appspec.yml = CodeDeploy; hook order differs per compute platform
  • In-place deployments = EC2/On-Premises only; blue/green spans EC2/On-Premises, Lambda, and ECS
  • CodeCommit stopped onboarding new customers July 2024; CodeStar is deprecated — never the "current best practice" answer
  • Pipeline artifacts pass between stages via S3
Must Understand
  • EventBridge (push) vs polling (pull) as the pipeline trigger mechanism, and why EventBridge is preferred
  • Deployment configurations control how much of the fleet/traffic shifts at once (OneAtATime/HalfAtATime/AllAtOnce/Canary/Linear + custom)
  • IAM service roles are scoped per service (CodePipeline role, CodeBuild role, CodeDeploy role) and commonly require iam:PassRole
  • Automatic rollback must be explicitly configured — it is not the default behavior
  • CodeStar (deprecated product) vs CodeStar Connections/CodeConnections (current, active mechanism) are different things
Can De-prioritize
  • Exact console click-paths and screen layouts
  • Historical CodeStar project template names
  • Deep VPC networking/CIDR mechanics for CodeBuild — know it's possible, not the exact subnet math

Exam appearance probability: HIGH

Core Components & Configuration

The settings, file formats, and structural concepts inside each service that most commonly appear in exam scenarios.

2.1 CodePipeline — Stages, Actions & Artifacts Foundational
StructurePipeline → Stages → Actions
Artifact storeS3 bucket, KMS-encrypted (one per region in use)
Execution orderA stage doesn't start until every action in the prior stage succeeds
2.2 CodeBuild — Build Environments & buildspec.yml High exam relevance
PurposeCompile source, run tests, produce a deployable artifact
EnvironmentEphemeral managed container (Amazon Linux, Ubuntu, Windows) or a custom Docker image pulled from ECR
Compute typesBUILD_GENERAL1_SMALL/MEDIUM/LARGE/2XLARGE (plus GPU-enabled options)
buildspec.yml phaseWhat runs here
installInstall runtime versions and dependencies (the runtime-versions block)
pre_buildCommands before the main build — e.g. ECR login, restoring cached dependencies, linting
buildThe main compile/test/package commands — e.g. docker build, running the test suite
post_buildCleanup, pushing the built image to ECR, sending notifications, finalizing artifacts
2.3 CodeDeploy — Applications, Deployment Groups & Targets High exam relevance
ApplicationLogical name grouping the deployments of one piece of software
Deployment groupDefines the target compute, deployment configuration, and rollback/alarm settings
RevisionThe application content plus its appspec.yml — what actually gets deployed
Compute platformsEC2/On-Premises, AWS Lambda, Amazon ECS
2.4 appspec.yml & Lifecycle Hooks High-trap
Platformappspec structureHook order
EC2 / On-Premisesversion, os, files (source → destination copy mapping), hooksApplicationStop → DownloadBundle → BeforeInstall → Install → AfterInstall → ApplicationStart → ValidateService
Lambdaversion, Resources (function name, alias, current/target version, timeout)BeforeAllowTraffic → AfterAllowTraffic
ECSversion, Resources (task definition ARN, container name/port)BeforeInstall → AfterInstall → AfterAllowTestTraffic → BeforeAllowTraffic → AfterAllowTraffic
2.5 In-Place vs. Blue/Green Deployments Very high exam relevance
⚠️ "Blue/green" doesn't mean the same mechanism everywhere

On EC2 it's a fleet swap behind a load balancer. On Lambda it's weighted alias traffic shifting between function versions. On ECS it's a task-set/target-group swap. The exam expects you to know which mechanism applies to which platform, not just the phrase "blue/green."

2.6 Deployment Configurations Medium-high
PlatformBuilt-in configurations
EC2/On-Premises (in-place or blue/green)CodeDeployDefault.OneAtATime, HalfAtATime, AllAtOnce, or a custom configuration specifying minimum healthy host percentage
Lambda / ECS (blue/green traffic shifting)Canary10Percent5Minutes, Linear10PercentEvery1Minute, AllAtOnce (and similar named variants at different percentages/intervals)

Higher batch sizes (AllAtOnce) deploy fastest but risk the largest blast radius on failure; OneAtATime/Linear/Canary trade deployment speed for safety and faster detection of a bad revision before it reaches 100% of traffic.

2.7 CodeCommit Deprecated for new customers
What it isFully managed private Git repository hosting
StatusStopped onboarding new customers July 25, 2024; existing repos/customers unaffected, no new features
2.8 CodeStar & CodeStar Connections / CodeConnections Deprecated vs. current — classic trap
2.9 IAM Service Roles Per Stage Medium-high

AWS Exam Thinking

Requirement → Keywords → Expected Answer → why every distractor fails.

Fully managed CI/CD with the least operational overhead
least operational overheadbuild, test, deploy automatically
Expected Answer

AWS CodePipeline + AWS CodeBuild + AWS CodeDeploy

DistractorWhy it's wrong
Self-hosted Jenkins on EC2You now own patching, scaling, and HA for the build server — the opposite of low operational overhead
AWS CodeStarDeprecated/retired product — not a valid "set this up today" answer, even though it once bundled these same services
Custom Lambda + CLI scriptingYou'd be building your own orchestration engine — far more operational overhead than using managed orchestration
Run unit tests and produce a deployable artifact in a managed, ephemeral environment
compile / test codeno build server to manage
Expected Answer

AWS CodeBuild

DistractorWhy it's wrong
AWS CodeDeployDeploys already-built revisions — has no build/compile/test capability
AWS CodePipelineOrchestrates the workflow; delegates the actual build work to CodeBuild
A dedicated EC2 build serverRequires you to manage patching/scaling — not the managed, ephemeral answer
Zero-downtime ECS deployment with gradual traffic shifting and fast rollback
zero downtimegradual traffic shiftfast rollback
Expected Answer

CodeDeploy blue/green deployment for ECS (e.g. CodeDeployDefault.ECSLinear10PercentEvery1Minutes, with a CloudWatch alarm configured for automatic rollback)

DistractorWhy it's wrong
CodeDeploy in-place deploymentIn-place is EC2/On-Premises only — CodeDeploy has no in-place option for ECS
Native ECS service rolling update (no CodeDeploy)Works, but doesn't provide CodeDeploy's weighted traffic shifting, hooks, and alarm-based automatic rollback that "gradual" and "fast rollback" imply
Manually creating a second ECS service and swapping DNSReinvents what CodeDeploy blue/green already automates — much higher operational overhead
Gradual Lambda rollout with automatic rollback on error rate
canary releaseLambda aliasCloudWatch alarm rollback
Expected Answer

CodeDeploy blue/green for Lambda using a Canary (e.g. Canary10Percent5Minutes) deployment configuration with a CloudWatch alarm attached to the deployment group

DistractorWhy it's wrong
Manually adjusting alias weights over timeWorks technically, but is manual, error-prone, and has no built-in automatic rollback on alarm breach
Publishing a new Lambda version with no aliasWithout an alias and CodeDeploy, there's no traffic-shifting mechanism at all — every invocation hits whichever version is configured
A CodePipeline manual approval action onlyApproval gates a human decision; it doesn't perform gradual, monitored traffic shifting
GitHub push should trigger the pipeline within seconds, not on a delay
near real-time triggerGitHub source
Expected Answer

Use AWS CodeConnections as the Source action provider for the GitHub repository (webhook-driven via EventBridge)

DistractorWhy it's wrong
Migrate the repo to CodeCommit firstUnnecessary — CodeConnections integrates directly with GitHub; also CodeCommit can't onboard new customers
Leave CodePipeline on its default periodic polling behaviorPolling checks on an interval — it does not deliver near-real-time triggering
Use an S3 bucket as the Source and manually upload zipsReintroduces a manual step the scenario is explicitly trying to automate away
Brand-new AWS account needs a private, AWS-managed Git repository
new AWS accountprivate Git repo
Expected Answer

They cannot provision a new CodeCommit repository — recommend GitHub, GitLab, or Bitbucket connected via AWS CodeConnections instead

DistractorWhy it's wrong
AWS CodeCommitThe obvious-looking answer is the trap — AWS stopped onboarding new CodeCommit customers on July 25, 2024
AWS CodeStarAlso deprecated; was never itself a Git hosting service anyway (it scaffolded projects, often on top of CodeCommit)
Self-hosted GitLab on EC2Introduces server management overhead the managed alternatives avoid
The file defining build commands is missing — which service/file is it?
compile commandsinstall/pre_build/build/post_build
Expected Answer

AWS CodeBuild — buildspec.yml

DistractorWhy it's wrong
appspec.ymlDrives CodeDeploy's deployment lifecycle, not build commands
A Dockerfile aloneDefines the container image, not the CI orchestration (install/test/package) around it — buildspec still typically invokes it
template.yamlA SAM/CloudFormation template — infrastructure definition, unrelated to build phase commands
A failed EC2 deployment must self-heal to the last known-good revision
no manual interventionrestore last good version
Expected Answer

Configure CodeDeploy automatic rollback on the deployment group (on deployment failure and/or CloudWatch alarm threshold breach)

DistractorWhy it's wrong
Manually redeploy the previous revisionWorks, but requires human action — the requirement is explicitly automatic
Rely on CloudFormation stack rollbackCloudFormation rolls back infrastructure stack changes, not an application revision deployed via CodeDeploy
Auto Scaling health check instance replacementReplaces an unhealthy instance with a fresh one running the SAME (bad) revision — doesn't restore the previous app version
CodeBuild integration tests need to reach a private RDS instance
private subnetintegration tests
Expected Answer

Configure the CodeBuild project with a VPC configuration (VPC, private subnets, security group) so build containers launch inside the VPC

DistractorWhy it's wrong
Make the RDS instance publicly accessibleSecurity anti-pattern — exposes the database unnecessarily
Switch the build to run inside a Lambda functionDoesn't solve networking and abandons CodeBuild's build tooling for no reason
"VPN into" the CodeBuild serviceNot a real CodeBuild capability — VPC configuration is the actual mechanism
CodePipeline must hand off execution to CodeDeploy's service role at deploy time
access denied at deploy stagerole hand-off
Expected Answer

Grant the CodePipeline service role iam:PassRole permission scoped to the CodeDeploy service role's ARN

DistractorWhy it's wrong
Attach an AdministratorAccess policy to the pipeline roleSolves the symptom by violating least privilege — not the correct fix
Create a cross-account trust policyUnnecessary when both roles are in the same account, which is the default/common case
Add a resource-based policy to the CodeDeploy applicationCodeDeploy applications don't use resource-based policies for this hand-off — iam:PassRole on the role itself is the mechanism

Integrations & How the Pieces Chain Together

Trigger Mechanism — EventBridge vs. Polling

MechanismHow it worksWhen it applies
EventBridge (push)A source-provider change event — a CodeCommit "Repository State Change" event, or a webhook from GitHub/Bitbucket/GitLab forwarded through CodeConnections — triggers a pipeline execution within secondsDefault/recommended when the pipeline source is created via the console for CodeCommit or a CodeConnections-based provider
Polling (pull)CodePipeline periodically checks the source location for changes on a fixed intervalLegacy behavior, or a fallback when an EventBridge rule isn't configured — higher latency and unnecessary API calls compared to push-based triggering
⚠️ Exam angle

"Trigger the pipeline immediately/near real-time when code changes" is a strong signal the expected answer involves EventBridge, not polling. Polling is the thing to move away from, not the thing to configure for a "fast" requirement.

Amazon S3
WhatThe artifact store between every CodePipeline stage
WhyDurable, versioned, encrypted hand-off point that doesn't require the services to talk to each other directly
PatternSource stage output → S3 → Build stage input → S3 → Deploy stage input
Amazon ECR
WhatContainer image registry; CodeBuild pushes built images here, CodeDeploy/ECS pulls them at deploy time
WhyStandard artifact format for container-based pipelines
PatternCodeBuild builds & tags image → docker push to ECR → outputs imagedefinitions.json referencing the ECR image URI for the ECS deploy action
CloudWatch (Logs & Alarms)
LogsCodeBuild streams build output to CloudWatch Logs — the primary troubleshooting source for a failed build
AlarmsAttached to a CodeDeploy deployment group as the trigger source for automatic rollback
PatternElevated error-rate/latency alarm breaches during a blue/green shift → CodeDeploy automatically rolls back traffic to the previous version
Amazon SNS
WhatNotification target for pipeline state changes and manual approval actions
WhyLets a human get notified ("a production deploy is awaiting your approval") without watching the console
IAM
WhatDistinct service roles per stage (CodePipeline, CodeBuild, CodeDeploy), plus iam:PassRole hand-offs between them
WhyLeast-privilege access scoped to exactly what each stage needs to do
AWS Secrets Manager / Systems Manager Parameter Store
WhatReferenced directly from buildspec.yml's env block for credentials/config
WhyKeeps secrets out of source control and out of the build logs
CloudFormation / SAM / CDK — the Deploy target for infrastructure-as-code
WhatA CodePipeline Deploy stage action type in its own right — deploys/updates a CloudFormation stack instead of (or alongside) CodeDeploy
WhySAM's AWS::Serverless::Function resource can declare AutoPublishAlias + a DeploymentPreference to get CodeDeploy-style Lambda traffic shifting declared entirely as code
ECS, Lambda, EC2 Auto Scaling, Elastic Beanstalk — Deploy targets
WhatThe actual compute CodeDeploy (or another deploy action) rolls the new revision onto

End-to-End Architecture Example — Containerized Application Pipeline

Developer commit → production ECS traffic shift

See also: 08 — Cross-Service Architectures for this pattern drawn out end to end alongside four other realistic architectures.

Best Practices & Common Exam Traps

When to Use / When Not To

Must Know
  • Use CodeConnections (GitHub/Bitbucket/GitLab) for any new source repository — not CodeCommit
  • Enable automatic rollback (failure and/or alarm-based) on every production CodeDeploy deployment group
  • Reference secrets from Secrets Manager/Parameter Store in buildspec.yml — never hardcode them
  • Scope IAM service roles narrowly per pipeline/stage — no wildcard resource ARNs
  • Use blue/green for production-critical services to minimize downtime and enable fast, traffic-level rollback
Good Practice
  • Gate the production Deploy stage with a manual approval action, notified via SNS
  • Cache dependencies in CodeBuild (local or S3) to cut build time
  • Use cross-region actions for multi-region deployments instead of maintaining separate pipelines
  • Tag EC2 deployment-group targets consistently so CodeDeploy targets the right fleet
Advanced Practice
  • Use CodeBuild report groups for test/code-coverage reporting surfaced inside the pipeline
  • Use Pipeline V2 trigger filters (branch/tag/file-path glob) to run different pipeline behavior per branch
  • Declare Lambda traffic-shifting deployments as code via SAM's AutoPublishAlias + DeploymentPreference instead of configuring CodeDeploy separately
  • When unnecessary: a single Lambda function updated occasionally by one developer may not need a full pipeline — sam deploy or a direct console update can be the lower-overhead answer

Comparison — CodeBuild vs. CodeDeploy

AspectCodeBuildCodeDeploy
PurposeCompiles source, runs tests, produces an artifactRolls an already-built revision onto target compute
Config filebuildspec.ymlappspec.yml
Typical pipeline stageBuild / TestDeploy
Where it executesEphemeral managed build containerThe target compute itself — EC2/On-Premises, Lambda, or ECS
Failure behaviorBuild/test failure fails the pipeline stage — nothing is deployedDeployment failure can trigger automatic rollback if configured

Comparison — CodePipeline vs. CodeDeploy

AspectCodePipelineCodeDeploy
PurposeOrchestrates the entire release workflow across stages/servicesExecutes the specific deployment step onto compute
ScopeEnd-to-end: Source → Build → Test → Deploy → ApprovalJust the deploy action — one stage's worth of work
Can operate standalone?Not meaningfully — a pipeline with no actions does nothingYes — can be invoked directly via console/CLI/API without CodePipeline

Comparison — In-Place vs. Blue/Green Deployment Targets

Deployment typeSupported targetsMechanismRollback speed
In-placeEC2/On-Premises onlySame instances: app stopped → new revision installed → app restarted → validatedSlower — the previous revision must be redeployed through the same process
Blue/GreenEC2/On-Premises (replacement ASG/fleet), Lambda (alias traffic weighting), ECS (task set + target group swap)New environment/version stood up alongside the old one; traffic shifted gradually or all at once; old one retained briefly then removedFast — simply route traffic back to the still-running original environment

Common Exam Traps

MisconceptionReality
"CodeCommit is the standard Git source for a new pipeline"Deprecated for new customers since July 25, 2024 — use GitHub/Bitbucket/GitLab via CodeConnections
"CodeStar is a current AWS best-practice service"Deprecated and retired — legacy exam trivia only, never the "set this up today" answer
"CodeStar Connections/CodeConnections is also deprecated because it has 'CodeStar' in its old name"The connection mechanism is current and actively recommended — only the CodeStar project-template product is deprecated
"buildspec.yml belongs to CodeDeploy"buildspec.yml = CodeBuild; appspec.yml = CodeDeploy
"All CodeDeploy deployments support blue/green"Only EC2/On-Premises, Lambda, and ECS; in-place is EC2/On-Premises only, and blue/green means a different mechanism on each platform
"CodePipeline triggers instantly by default no matter the source"The modern push/EventBridge trigger is the recommended setup, but polling is still a legacy fallback mode with real latency
"CodeDeploy needs an agent for every compute platform"The CodeDeploy agent is required only for EC2/On-Premises — not for Lambda or ECS deployments
"A failed deployment rolls back automatically by default"Automatic rollback must be explicitly enabled on the deployment group (on failure and/or alarm)

CI/CD Service Lookalikes

ServiceWhat it actually answers
CodePipeline vs CodeBuildCodePipeline = orchestrates the whole release workflow. CodeBuild = does the actual compiling/testing inside one stage
CodePipeline vs CodeDeployCodePipeline = the workflow container. CodeDeploy = the deploy action's execution engine, and can run independently of CodePipeline entirely
CodeCommit vs CodeConnectionsCodeCommit = AWS-hosted Git repo (deprecated for new customers). CodeConnections = the integration bridge to an externally-hosted Git provider (current, active)
CodeDeploy vs CloudFormation deploy actionsCodeDeploy = rolls an app revision onto existing compute with lifecycle hooks and traffic shifting. CloudFormation deploy action = creates/updates infrastructure (the stack itself) as part of a pipeline
CodePipeline vs Elastic Beanstalk's built-in deploymentElastic Beanstalk can deploy new application versions on its own (rolling/immutable/blue-green via environment swap) without CodePipeline at all — CodePipeline is used to automate triggering and orchestrating that from source control
CodeStar (product) vs AWS CodeCatalystCodeCatalyst is AWS's newer, actively developed unified software-delivery service — a more current analogue to what CodeStar once tried to be. Not in scope for DVA-C02, but useful context for why CodeStar was retired

Memory Anchors

Hands-On Lab

Two guided, self-contained exercises run with the AWS CLI v2 against resources in eu-west-1. Both use a fictional theodore-dva-lab naming convention and assume an ECS cluster, service, task definition, and an Application Load Balancer with two target groups (blue/green) already exist — see 01 — Containers if you need to stand those up first. The point isn't the ECS plumbing — it's wiring CodePipeline/CodeBuild/CodeDeploy together correctly, and then deliberately breaking that wiring the exact way the exam loves to test. Source is GitHub via AWS CodeConnections throughout — never CodeCommit, consistent with the rest of this guide.

Lab 1 — Wire GitHub → CodeBuild → CodeDeploy (ECS Blue/Green)

Build a complete pipeline: a GitHub push, authenticated via AWS CodeConnections, triggers a CodeBuild image build, and CodeDeploy rolls the result onto an ECS service using a blue/green traffic shift.

  1. Create the GitHub connection.
    aws codeconnections create-connection \
      --provider-type GitHub \
      --connection-name theodore-dva-lab-gh \
      --region eu-west-1
    Returns a ConnectionArn with ConnectionStatus "PENDING".
  2. Complete the handshake in the console: Developer Tools → Settings → Connections → select the pending connection → "Update pending connection" → authorize the AWS Connector for GitHub app and choose the repository. ConnectionStatus flips to "AVAILABLE" — confirm with aws codeconnections get-connection --connection-arn <arn> --region eu-west-1.
  3. Create the ECR repository the build will push images to.
    aws ecr create-repository \
      --repository-name theodore-dva-lab \
      --image-scanning-configuration scanOnPush=true \
      --region eu-west-1
    repositoryUri returned, e.g. 111122223333.dkr.ecr.eu-west-1.amazonaws.com/theodore-dva-lab.
  4. Write buildspec.yml at the repo root — install/pre_build/build/post_build only, no deploy logic.
    version: 0.2
    phases:
      install:
        runtime-versions:
          nodejs: 18
      pre_build:
        commands:
          - echo Logging in to ECR...
          - aws ecr get-login-password --region eu-west-1 | docker login --username AWS --password-stdin $ECR_REPO_URI
          - IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c1-7)
      build:
        commands:
          - echo Building image...
          - docker build -t $ECR_REPO_URI:$IMAGE_TAG .
      post_build:
        commands:
          - echo Pushing image...
          - docker push $ECR_REPO_URI:$IMAGE_TAG
          - printf '[{"name":"theodore-dva-lab-container","imageUri":"%s"}]' "$ECR_REPO_URI:$IMAGE_TAG" > imagedefinitions.json
    artifacts:
      files:
        - imagedefinitions.json
        - appspec.yaml
        - taskdef.json
    A buildspec.yml exists that only installs, builds, and packages — it produces artifacts but never touches ECS directly.
  5. Write appspec.yaml at the repo root — this is CodeDeploy's file, not CodeBuild's, and it is never referenced by anything inside the build container.
    version: 0.0
    Resources:
      - TargetService:
          Type: AWS::ECS::Service
          Properties:
            TaskDefinition: <TASK_DEFINITION_ARN>
            LoadBalancerInfo:
              ContainerName: "theodore-dva-lab-container"
              ContainerPort: 80
    appspec.yaml committed alongside buildspec.yml, but conceptually owned by a completely different service.
  6. Create the CodeBuild project, sourced from the pipeline rather than directly from GitHub.
    aws codebuild create-project \
      --name theodore-dva-lab-build \
      --source type=CODEPIPELINE,buildspec=buildspec.yml \
      --artifacts type=CODEPIPELINE \
      --environment type=LINUX_CONTAINER,image=aws/codebuild/amazonlinux2-x86_64-standard:5.0,computeType=BUILD_GENERAL1_SMALL,privilegedMode=true \
      --service-role arn:aws:iam::111122223333:role/theodore-dva-lab-codebuild-role \
      --region eu-west-1
    Project ARN returned; privilegedMode=true is required because the build runs docker build/docker push.
  7. Create the CodeDeploy application on the ECS compute platform, then a deployment group configured for blue/green traffic shifting against the existing ALB target groups.
    aws deploy create-application \
      --application-name theodore-dva-lab-app \
      --compute-platform ECS \
      --region eu-west-1
    
    aws deploy create-deployment-group \
      --application-name theodore-dva-lab-app \
      --deployment-group-name theodore-dva-lab-dg \
      --deployment-config-name CodeDeployDefault.ECSLinear10PercentEvery1Minutes \
      --service-role-arn arn:aws:iam::111122223333:role/theodore-dva-lab-codedeploy-role \
      --ecs-services serviceName=theodore-dva-lab-svc,clusterName=theodore-dva-lab-cluster \
      --load-balancer-info targetGroupPairInfoList="[{targetGroups=[{name=theodore-dva-lab-tg-blue},{name=theodore-dva-lab-tg-green}],prodTrafficRoute={listenerArns=[arn:aws:elasticloadbalancing:eu-west-1:111122223333:listener/app/theodore-dva-lab-alb/1234567890abcdef/abcdef1234567890]}}]" \
      --auto-rollback-configuration enabled=true,events=DEPLOYMENT_FAILURE \
      --region eu-west-1
    Deployment group created with a blue/green deployment type implied by the ECS + load-balancer-info combination, and automatic rollback enabled on deployment failure.
  8. Define the pipeline as pipeline.json, then create it.
    {
      "pipeline": {
        "name": "theodore-dva-lab-pipeline",
        "roleArn": "arn:aws:iam::111122223333:role/theodore-dva-lab-codepipeline-role",
        "artifactStore": { "type": "S3", "location": "theodore-dva-lab-artifacts-eu-west-1" },
        "stages": [
          { "name": "Source", "actions": [{
            "name": "GitHub_Source",
            "actionTypeId": { "category": "Source", "owner": "AWS", "provider": "CodeStarSourceConnection", "version": "1" },
            "configuration": {
              "ConnectionArn": "arn:aws:codeconnections:eu-west-1:111122223333:connection/CONNECTION_ID",
              "FullRepositoryId": "your-org/theodore-dva-lab",
              "BranchName": "main"
            },
            "outputArtifacts": [{ "name": "SourceOutput" }]
          }]},
          { "name": "Build", "actions": [{
            "name": "CodeBuild_Build",
            "actionTypeId": { "category": "Build", "owner": "AWS", "provider": "CodeBuild", "version": "1" },
            "configuration": { "ProjectName": "theodore-dva-lab-build" },
            "inputArtifacts": [{ "name": "SourceOutput" }],
            "outputArtifacts": [{ "name": "BuildOutput" }]
          }]},
          { "name": "Deploy", "actions": [{
            "name": "CodeDeploy_ECS",
            "actionTypeId": { "category": "Deploy", "owner": "AWS", "provider": "CodeDeployToECS", "version": "1" },
            "configuration": {
              "ApplicationName": "theodore-dva-lab-app",
              "DeploymentGroupName": "theodore-dva-lab-dg",
              "TaskDefinitionTemplateArtifact": "BuildOutput",
              "AppSpecTemplateArtifact": "BuildOutput",
              "Image1ArtifactName": "BuildOutput",
              "Image1ContainerName": "IMAGE1_NAME"
            },
            "inputArtifacts": [{ "name": "BuildOutput" }]
          }]}
        ]
      }
    }
    aws codepipeline create-pipeline --cli-input-json file://pipeline.json --region eu-west-1
    Pipeline created; its first execution starts automatically, pulling the current GitHub branch HEAD as the Source artifact.
  9. Watch the pipeline run to completion.
    aws codepipeline get-pipeline-state --name theodore-dva-lab-pipeline --region eu-west-1
    Source, Build, and Deploy stages all report latestExecution.status = "Succeeded"; the ECS console briefly shows two task sets (blue and green) before settling on green at 100% traffic.
⚠️ Why this step order matters for the exam

buildspec.yml never mentions ECS, the load balancer, or traffic shifting — it only installs, builds, and packages, then hands off an imagedefinitions.json/appspec.yaml/taskdef.json bundle as its output artifact. Everything about how the new revision reaches production — the blue/green shift, the target-group swap, the rollback trigger — lives in appspec.yaml and the CodeDeploy deployment group, not in the build. The exam repeatedly tests this exact boundary: which file, and which service, owns which responsibility.

Lab 2 — Break It, Diagnose It, Fix It

Reproduce the classic trap this guide warns about elsewhere: deploy logic accidentally living inside buildspec.yml's post_build phase instead of being handled by CodeDeploy. This is one of the most common real-world — and exam — misconfigurations.

  1. Edit buildspec.yml: add a direct ECS update to post_build, and stop producing the artifacts CodeDeploy needs.
      post_build:
        commands:
          - echo Pushing image...
          - docker push $ECR_REPO_URI:$IMAGE_TAG
          - echo Deploying directly from the build...
          - aws ecs update-service \
              --cluster theodore-dva-lab-cluster \
              --service theodore-dva-lab-svc \
              --force-new-deployment \
              --region eu-west-1
    artifacts:
      files:
        - imagedefinitions.json
    buildspec.yml now performs a deployment itself and no longer packages appspec.yaml/taskdef.json as output artifacts.
  2. Commit and push to GitHub, then watch the pipeline execute.
    git add buildspec.yml
    git commit -m "break: deploy from buildspec post_build"
    git push
    aws codepipeline get-pipeline-state --name theodore-dva-lab-pipeline --region eu-west-1
    The Build stage reports "Succeeded" — the ECS service actually starts a plain rolling update triggered from inside CodeBuild — but the Deploy stage (the CodeDeployToECS action) fails.
  3. Diagnose the Deploy stage failure.
    aws codepipeline get-pipeline-state --name theodore-dva-lab-pipeline --region eu-west-1 \
      --query "stageStates[?stageName=='Deploy']"
    
    aws deploy list-deployments \
      --application-name theodore-dva-lab-app \
      --deployment-group-name theodore-dva-lab-dg \
      --region eu-west-1
    
    aws deploy get-deployment --deployment-id <id-from-above> --region eu-west-1
    The Deploy action fails because CodeDeploy can't find the appspec.yaml/taskdef.json it expects in the build's output artifact — and separately, ECS shows the service was already force-updated by CodeBuild, bypassing blue/green entirely, so that release never had a controlled traffic shift or an alarm-based rollback safety net.
  4. Fix it: revert buildspec.yml to only build/package (drop the aws ecs update-service call, restore appspec.yaml/taskdef.json to the artifacts list), then re-run the pipeline.
    git revert HEAD
    git push
    aws codepipeline start-pipeline-execution --name theodore-dva-lab-pipeline --region eu-west-1
    The Deploy stage now succeeds via CodeDeployToECS, performing a proper blue/green shift with alarm-backed automatic rollback available — confirm with aws deploy get-deployment --deployment-id <new-id> --region eu-west-1 showing status: "Succeeded" and deploymentType: "BLUE_GREEN".
⚠️ Why this exact trap keeps showing up on the exam

Putting deploy logic in post_build "works" in the sense that the ECS service does update — which is exactly what makes it a dangerous, exam-favorite distractor. It silently discards everything CodeDeploy was providing: gradual blue/green traffic shifting, lifecycle hooks like AfterAllowTestTraffic, and alarm-based automatic rollback. A question describing "the deployment updates the service but there's no gradual traffic shift and no automatic rollback" is almost always describing this exact misconfiguration — deploy logic that belongs in appspec.yaml/CodeDeploy was instead written into buildspec.yml/CodeBuild.

Flashcards — 22 Cards

Click card to flip. Mark right or wrong to track score.

Click to reveal answer
1 / 22
Mark:   Score: 0/0

Practice Quiz — 13 Questions

DVA-C02 scenario style, Easy → Specialty. Select an answer to reveal the explanation.

out of 13 correct