AWS for DevOps — CodePipeline

3 minute read

6.3 — CodePipeline

AWS CodePipeline is the orchestrator. It connects your source, build, and deploy stages into an automated release pipeline.

  Source Stage          Build Stage          Deploy Stage
  ┌──────────┐        ┌──────────┐        ┌──────────────┐
  │ GitHub   │───────▶│CodeBuild │───────▶│ CodeDeploy   │
  │ S3       │        │ Jenkins  │        │ ECS          │
  │ ECR      │        │          │        │ CloudFormation│
  └──────────┘        └──────────┘        └──────────────┘
       │                   │                     │
       ▼                   ▼                     ▼
  artefact in S3      artefact in S3       deployed to targets

Pipeline Concepts

Concept Description
Pipeline End-to-end workflow with ordered stages
Stage Logical group of actions (Source, Build, Test, Deploy, Approval)
Action A single task within a stage (run CodeBuild, deploy via CodeDeploy)
Artefact Output of one action passed as input to the next (stored in S3)
Transition Link between stages — can be enabled or disabled

Creating a Pipeline (CLI)

$ aws codepipeline create-pipeline --cli-input-json file://pipeline.json

pipeline.json:

{
  "pipeline": {
    "name": "my-app-pipeline",
    "roleArn": "arn:aws:iam::123456789012:role/CodePipelineRole",
    "artifactStore": {
      "type": "S3",
      "location": "my-pipeline-artefacts-bucket"
    },
    "stages": [
      {
        "name": "Source",
        "actions": [
          {
            "name": "GitHub-Source",
            "actionTypeId": {
              "category": "Source",
              "owner": "AWS",
              "provider": "CodeStarSourceConnection",
              "version": "1"
            },
            "configuration": {
              "ConnectionArn": "arn:aws:codestar-connections:ap-south-1:123456789012:connection/abc-123",
              "FullRepositoryId": "myorg/my-app",
              "BranchName": "main",
              "OutputArtifactFormat": "CODE_ZIP"
            },
            "outputArtifacts": [{ "name": "SourceOutput" }]
          }
        ]
      },
      {
        "name": "Build",
        "actions": [
          {
            "name": "CodeBuild-Build",
            "actionTypeId": {
              "category": "Build",
              "owner": "AWS",
              "provider": "CodeBuild",
              "version": "1"
            },
            "configuration": {
              "ProjectName": "my-app-build"
            },
            "inputArtifacts": [{ "name": "SourceOutput" }],
            "outputArtifacts": [{ "name": "BuildOutput" }]
          }
        ]
      },
      {
        "name": "Deploy-Staging",
        "actions": [
          {
            "name": "Deploy-to-Staging",
            "actionTypeId": {
              "category": "Deploy",
              "owner": "AWS",
              "provider": "CodeDeploy",
              "version": "1"
            },
            "configuration": {
              "ApplicationName": "my-app",
              "DeploymentGroupName": "staging"
            },
            "inputArtifacts": [{ "name": "BuildOutput" }]
          }
        ]
      },
      {
        "name": "Approval",
        "actions": [
          {
            "name": "Manual-Approval",
            "actionTypeId": {
              "category": "Approval",
              "owner": "AWS",
              "provider": "Manual",
              "version": "1"
            },
            "configuration": {
              "NotificationArn": "arn:aws:sns:ap-south-1:123456789012:pipeline-approval",
              "CustomData": "Approve deployment to production?"
            }
          }
        ]
      },
      {
        "name": "Deploy-Production",
        "actions": [
          {
            "name": "Deploy-to-Production",
            "actionTypeId": {
              "category": "Deploy",
              "owner": "AWS",
              "provider": "CodeDeploy",
              "version": "1"
            },
            "configuration": {
              "ApplicationName": "my-app",
              "DeploymentGroupName": "production"
            },
            "inputArtifacts": [{ "name": "BuildOutput" }]
          }
        ]
      }
    ]
  }
}

Stage Types

Stage Category Providers Purpose
Source GitHub (CodeStar), S3, ECR, CodeCommit Triggers the pipeline
Build CodeBuild, Jenkins Compile, test, build artefacts
Test CodeBuild, Device Farm Run integration / E2E tests
Deploy CodeDeploy, ECS, CloudFormation, S3 Ship to environment
Approval Manual Human gate before production
Invoke Lambda Custom logic (DB migration, Slack notify)

Artefact Flow

Artefacts are stored in an S3 bucket and passed between stages:

  Source Stage                Build Stage               Deploy Stage
  ┌─────────────┐           ┌─────────────┐           ┌──────────────┐
  │ SourceOutput│──────────▶│ BuildOutput  │──────────▶│ (consumes)   │
  │ (code zip)  │  input    │ (jar + specs)│  input    │              │
  └─────────────┘           └─────────────┘           └──────────────┘
         │                         │
         ▼                         ▼
    S3: pipeline-bucket/       S3: pipeline-bucket/
    SourceOutp/abc123          BuildOutpu/abc123

Manual Approval

# List pending approvals
$ aws codepipeline get-pipeline-state --name my-app-pipeline \
    --query 'stageStates[?stageName==`Approval`].actionStates'

# Approve
$ aws codepipeline put-approval-result \
    --pipeline-name my-app-pipeline \
    --stage-name Approval \
    --action-name Manual-Approval \
    --result summary="Looks good",status=Approved \
    --token <token-from-get-pipeline-state>

Disabling / Enabling Transitions

# Disable transition to production (freeze deployments)
$ aws codepipeline disable-stage-transition \
    --pipeline-name my-app-pipeline \
    --stage-name Deploy-Production \
    --transition-type Inbound \
    --reason "Change freeze for release 2.5"

# Re-enable
$ aws codepipeline enable-stage-transition \
    --pipeline-name my-app-pipeline \
    --stage-name Deploy-Production \
    --transition-type Inbound

Pipeline Execution

# Trigger a new execution manually
$ aws codepipeline start-pipeline-execution --name my-app-pipeline

# Check pipeline state
$ aws codepipeline get-pipeline-state --name my-app-pipeline \
    --query 'stageStates[].{Stage:stageName,Status:latestExecution.status}'
[
    { "Stage": "Source",            "Status": "Succeeded" },
    { "Stage": "Build",             "Status": "Succeeded" },
    { "Stage": "Deploy-Staging",    "Status": "Succeeded" },
    { "Stage": "Approval",          "Status": "InProgress" },
    { "Stage": "Deploy-Production", "Status": null }
]

Common Mistakes

Mistake Why It Hurts Fix
No manual approval before prod Untested code reaches production Add an Approval stage
Artefact name mismatch Next stage can’t find input Match outputArtifacts → inputArtifacts names exactly
Missing pipeline S3 bucket policy Pipeline can’t store artefacts Grant CodePipeline role s3:PutObject + s3:GetObject
Ignoring failed transitions Broken builds silently block pipeline Enable CloudWatch Events → SNS notifications

Quick Reference

Task Command
Create pipeline aws codepipeline create-pipeline --cli-input-json file://pipeline.json
Start execution aws codepipeline start-pipeline-execution --name NAME
Get pipeline state aws codepipeline get-pipeline-state --name NAME
Approve aws codepipeline put-approval-result --pipeline-name NAME ...
Disable transition aws codepipeline disable-stage-transition --pipeline-name NAME --stage-name STAGE ...
Delete pipeline aws codepipeline delete-pipeline --name NAME

Next → Deployment Strategies

Updated: