DEV Community

Prakash Rao
Prakash Rao

Posted on

4 1 2

Advanced CI/CD Pipelines on AWS

In this post, I’ll walk you through setting up an advanced CI/CD pipeline on AWS using native services and show you how to create and configure components like CodeBuild, CodeDeploy, and CodePipeline using AWS CLI commands and configuration files. I will also include outputs for each command so you can see what to expect when you run these commands yourself.

Flow Chart

Note:

  1. Flowchart was created using mermaid.live
  2. Since CodeCommit is no longer onboarding new customers, choosing GitHub as the source repository. If you already have a GitHub repository for your project, simply update the configuration files accordingly.

Prerequisites: Please make sure that the AWS CLI is installed and configured with the proper IAM permissions.

1. Create a Source Repository in GitHub

First, let’s create a new GitHub repository where our source code will be there.

git init
git remote add origin https://github.com/<YOUR_GITHUB_USERNAME>/advanced-ci-cd-repo.git
git add .
git commit -m "Initial commit"
git push -u origin main
Enter fullscreen mode Exit fullscreen mode

2. Set Up a CodeBuild Project

Next let's create a CodeBuild project that builds our application. In this example, we’ll use a simple Node.js project. Save the following JSON configuration as codebuild-project.json:

{
  "name": "advanced-ci-cd-build",
  "description": "Build project for advanced CI/CD pipeline demo",
  "source": {
    "type": "GITHUB",
    "location": "https://github.com/<YOUR_GITHUB_USERNAME>/advanced-ci-cd-repo"
  },
  "artifacts": {
    "type": "NO_ARTIFACTS"
  },
  "environment": {
    "type": "LINUX_CONTAINER",
    "image": "aws/codebuild/standard:6.0",
    "computeType": "BUILD_GENERAL1_MEDIUM",
    "environmentVariables": [
      {
        "name": "NODE_ENV",
        "value": "production"
      }
    ]
  },
  "serviceRole": "arn:aws:iam::<YOUR_ACCOUNT_ID>:role/CodeBuildServiceRole"
}

Enter fullscreen mode Exit fullscreen mode

Create project with:

aws codebuild create-project --cli-input-json file://codebuild-project.json
Enter fullscreen mode Exit fullscreen mode

Output:

{
  "project": {
    "name": "advanced-ci-cd-build",
    "arn": "arn:aws:codebuild:us-east-1:123456789012:project/advanced-ci-cd-build",
    "description": "Build project for advanced CI/CD pipeline demo",
    "source": {
      "type": "GITHUB",
      "location": "https://github.com/<YOUR_GITHUB_USERNAME>/advanced-ci-cd-repo"
    },
    "artifacts": {
      "type": "NO_ARTIFACTS"
    },
    "environment": {
      "type": "LINUX_CONTAINER",
      "image": "aws/codebuild/standard:6.0",
      "computeType": "BUILD_GENERAL1_MEDIUM",
      "environmentVariables": [
        {
          "name": "NODE_ENV",
          "value": "production"
        }
      ]
    },
    "serviceRole": "arn:aws:iam::<YOUR_ACCOUNT_ID>:role/CodeBuildServiceRole",
    "created": "2024-05-10T15:00:00Z"
  }
}

Enter fullscreen mode Exit fullscreen mode

Note: Make sure CodeBuild service role has permissions for GitHub, S3 (if you use artifacts), and CloudWatch logging.

3. Define a Build Specification (buildspec.yml)

Create a buildspec.yml file in the root of the repository. This file instructs CodeBuild on how to run our build.

version: 0.2

phases:
  install:
    runtime-versions:
      nodejs: 16
    commands:
      - echo "Installing dependencies..."
      - npm install
  pre_build:
    commands:
      - echo "Running lint and tests..."
      - npm run lint
      - npm test
  build:
    commands:
      - echo "Building the project..."
      - npm run build
  post_build:
    commands:
      - echo "Build completed on `date`"
artifacts:
  files:
    - '**/*'
  discard-paths: yes
Enter fullscreen mode Exit fullscreen mode

Push this file to the GitHub repository so CodeBuild uses it during the build process.

4. Set Up a CodeDeploy Application and Deployment Group

For blue/green deployments, we’ll use CodeDeploy.

Create a CodeDeploy Application

Command:

aws deploy create-application \
    --application-name advanced-ci-cd-app \
    --compute-platform Server
Enter fullscreen mode Exit fullscreen mode

Output:

{
  "applicationId": "abcdef12-3456-7890-abcd-ef1234567890",
  "applicationName": "advanced-ci-cd-app",
  "computePlatform": "Server"
}
Enter fullscreen mode Exit fullscreen mode

Create a Deployment Group
Save the following as deployment-group.json (update below values as needed):

{
  "applicationName": "advanced-ci-cd-app",
  "deploymentGroupName": "advanced-ci-cd-deploy-group",
  "deploymentConfigName": "CodeDeployDefault.OneAtATime",
  "ec2TagFilters": [
    {
      "Key": "Name",
      "Value": "MyAppServer",
      "Type": "KEY_AND_VALUE"
    }
  ],
  "serviceRoleArn": "arn:aws:iam::<YOUR_ACCOUNT_ID>:role/CodeDeployServiceRole",
  "blueGreenDeploymentConfiguration": {
    "terminateBlueInstancesOnDeploymentSuccess": {
      "action": "TERMINATE",
      "terminationWaitTimeInMinutes": 5
    },
    "deploymentReadyOption": {
      "actionOnTimeout": "CONTINUE_DEPLOYMENT"
    }
  },
  "autoRollbackConfiguration": {
    "enabled": true,
    "events": ["DEPLOYMENT_FAILURE"]
  }
}
Enter fullscreen mode Exit fullscreen mode

Create Deployment group with:

aws deploy create-deployment-group --cli-input-json file://deployment-group.json
Enter fullscreen mode Exit fullscreen mode

Output:

{
  "deploymentGroupId": "abcdef12-3456-7890-abcd-ef1234567890",
  "deploymentGroupName": "advanced-ci-cd-deploy-group",
  "applicationName": "advanced-ci-cd-app"
}
Enter fullscreen mode Exit fullscreen mode

Note: Make sure that the CodeDeploy service role has the necessary permissions to access EC2 and execute deployment actions.

5. Create a CodePipeline

Let's put everything together by creating a pipeline that orchestrates the source, build, and deployment stages.

Save the following as pipeline.json (adjust names, regions, and bucket names as needed):

{
  "pipeline": {
    "name": "advanced-ci-cd-pipeline",
    "roleArn": "arn:aws:iam::<YOUR_ACCOUNT_ID>:role/CodePipelineServiceRole",
    "artifactStore": {
      "type": "S3",
      "location": "<YOUR_ARTIFACT_BUCKET>"
    },
    "stages": [
      {
        "name": "Source",
        "actions": [
          {
            "name": "SourceAction",
            "actionTypeId": {
              "category": "Source",
              "owner": "ThirdParty",
              "provider": "GitHub",
              "version": "1"
            },
            "outputArtifacts": [
              {
                "name": "SourceOutput"
              }
            ],
            "configuration": {
              "Owner": "<YOUR_GITHUB_USERNAME>",
              "Repo": "advanced-ci-cd-repo",
              "Branch": "main",
              "OAuthToken": "<YOUR_GITHUB_OAUTH_TOKEN>"
            },
            "runOrder": 1
          }
        ]
      },
      {
        "name": "Build",
        "actions": [
          {
            "name": "BuildAction",
            "actionTypeId": {
              "category": "Build",
              "owner": "AWS",
              "provider": "CodeBuild",
              "version": "1"
            },
            "inputArtifacts": [
              {
                "name": "SourceOutput"
              }
            ],
            "outputArtifacts": [
              {
                "name": "BuildOutput"
              }
            ],
            "configuration": {
              "ProjectName": "advanced-ci-cd-build"
            },
            "runOrder": 1
          }
        ]
      },
      {
        "name": "Deploy",
        "actions": [
          {
            "name": "DeployAction",
            "actionTypeId": {
              "category": "Deploy",
              "owner": "AWS",
              "provider": "CodeDeploy",
              "version": "1"
            },
            "inputArtifacts": [
              {
                "name": "BuildOutput"
              }
            ],
            "configuration": {
              "ApplicationName": "advanced-ci-cd-app",
              "DeploymentGroupName": "advanced-ci-cd-deploy-group"
            },
            "runOrder": 1
          }
        ]
      }
    ],
    "version": 1
  }
}
Enter fullscreen mode Exit fullscreen mode

Create pipeline with:

aws codepipeline create-pipeline --cli-input-json file://pipeline.json
Enter fullscreen mode Exit fullscreen mode

Output:

{
  "pipeline": {
    "name": "advanced-ci-cd-pipeline",
    "version": 1,
    "artifactStore": {
      "type": "S3",
      "location": "my-artifact-bucket"
    },
    "stages": [
      {
        "name": "Source",
        "actions": [ { ..... } ]
      },
      {
        "name": "Build",
        "actions": [ { ..... } ]
      },
      {
        "name": "Deploy",
        "actions": [ { ..... } ]
      }
    ]
  },
  "created": "2024-05-10T15:30:00Z"
}

Enter fullscreen mode Exit fullscreen mode

6. Testing and Monitoring the Pipeline

After creating the pipeline, trigger a test execution by pushing a commit to your GitHub repository. Then, check the pipeline status with:

aws codepipeline get-pipeline-execution --pipeline-name advanced-ci-cd-pipeline --pipeline-execution-id <execution-id>
Enter fullscreen mode Exit fullscreen mode

Output:

{
  "pipelineExecution": {
    "pipelineName": "advanced-ci-cd-pipeline",
    "pipelineExecutionId": "12345678-1234-1234-1234-123456789012",
    "status": "Succeeded",
    "artifactRevisions": [ ..... ],
    "startTime": "2024-05-10T15:31:00Z",
    "lastUpdateTime": "2024-05-10T15:33:00Z"
  }
}

Enter fullscreen mode Exit fullscreen mode

Additionally, we can set up CloudWatch dashboards and alarms to monitor key metrics such as build duration and deployment status.

Conclusion

In this blog I demonstrated how we can build an advanced CI/CD pipeline on AWS using CLI commands and configuration files. By integrating GitHub, CodeBuild, CodeDeploy (with blue/green deployments), and CodePipeline, we created a fully automated workflow.

Happy Deploying! :)

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

AWS GenAI LIVE image

How is generative AI increasing efficiency?

Join AWS GenAI LIVE! to find out how gen AI is reshaping productivity, streamlining processes, and driving innovation.

Learn more

👋 Kindness is contagious

If you found this post useful, consider leaving a ❤️ or a nice comment!

Got it