📣 Limited offer: subscribe to cloudonaut plus, get a t-shirt for free

📣 Limited offer: free cloudonaut t-shirt

GitHub Actions vs. AWS CodePipeline

Andreas Wittig – 21 Feb 2020 (updated 23 Feb 2020)

Deployment pipelines first! When launching a new project, start with building a deployment pipeline. Automating the process from changing the source code to shipping your application to the production environment is a success factor.

But how to build a deployment pipeline? This post compares two different approaches: GitHub Actions and AWS CodePipeline.

GitHub Actions vs. AWS CodePipeline

GitHub has been hosting source code for more than ten years. On top of that, GitHub announced their CI/CD service called GitHub Actions to the public in November 2019.

AWS empowers developers with its continuous delivery service CodePipeline since July 2015. About a year later, AWS announced an essential add-on: CodeBuild. When I write about CodePipeline in the following, I always refer to a combination of CodePipeline and CodeBuild. So to be more accurate, the title of this blog post should be: GitHub Actions vs. CodePipeline and CodeBuild.

Overview

Both GitHub Actions and AWS CodePipeline use similar concepts to provide a deployment pipeline:

  • Workflow Management: customize the deployment workflow to your needs by arranging actions in parallel or order.
  • Isolated Job Execution: use pre-build or custom container images to provide an isolated environment for executing actions (e.g., a build job).

Deployment Pipeline: Overview

In summary, the main concepts are similar, but what are the differences?

Comparison

The following table compares GitHub Actions and AWS CodePipeline. To achieve better comparability, I examine the GitHub-hosted runner with 2 CPU and 7 GB memory with the CodeBuild compute type general1.medium, which comes with 4 CPU and 7 GB memory.

GitHub Actions AWS CodePipeline
Free Tier (Linux) free for public repositories1
GitHub Free: 2,000 build minutes per month
GitHub Pro: 3,000 build minutes
GitHub Team: 10,000 build minutes
50 minutes per month2
Costs for Pipeline free $1.00 per month
Costs for Build Job $0.008 per minute1 $0.010 per minute2
Environments Linux, Windows, macOS Linux, (Windows)3
Source Code Repository GitHub GitHub, Bitbucket, AWS CodeCommit, Amazon S3
Deployment Target Any environment, works best for public cloud providers. Mainly AWS, in theory you could deploy to other cloud providers as well.
AWS Authentication Store access keys of IAM user in GitHub Secrets5 IAM role, no need to manage access keys
Developer Experience 🏖 Easy to use. 🤷‍♀️ Difficult to get started.
Integrations Open marketplace providing all kinds of integrations of mixed quality. Pre-built and high quality integrations into the AWS ecosystem.
Self-hosted Workers? ⚠️ (With custom actions and custom code)8
Serialize pipeline executions 4 9
Support for multiple branches?
Pipeline as Code ✅ built-in ✅ with CloudFormation or Terraform

GitHub Actions offers an outstanding developer experience. As long as you host your source code on GitHub, the solution is flexible, not only because of the integrations (aka actions) offered in the open marketplace. AWS CodePipeline integrates very well into the AWS ecosystem. Being able to use IAM roles for authentication instead of fiddling around with access keys for IAM users is a big plus.

Special offer: cloudonaut t-shirt

Do you love our blog posts and podcast episodes? Unlock our weekly videos and online events by subscribing to cloudonaut plus.

Special offer: Join cloudonaut plus before November 30th, and we will send you a cloudonaut t-shirt for free.

Subscribe now!

Integrations

AWS CodePiline comes with the following pre-built integrations:

  • AWS CloudFormation deploy your Infrastructure as Code templates
  • AWS CodeBuild run any kind of build job inside a container
  • AWS CodeDeploy deploy to a fleet of EC2 instances
  • Amazon Elastic Container Service (ECS) deploy your containers with ECS
  • AWS Elastic Beanstalk deploy your app on Amazon’s PaaS platform
  • AWS OpsWorks Stacks deploy your app based on Chef cookooks and recipes
  • AWS Service Catalog deploy a product
  • Alexa Skills Kit deploy your skill
  • AWS Lambda invoke customized source code
  • AWS Device Farm run UI tests on mobile devices

It worth mentioning that the integration with AWS CodeBuild allows you to run any script inside a container based on a pre-built or customized image. This provides maximum flexibility. On top of that, a few 3rd party services are integrated as well.6

GitHub has taken a different approach: its open marketplace lists more than 2,000 integrations (aka actions)7. Well known and trusted organizations (e.g., GitHub itself also AWS), as well as individuals, publish their actions. A few examples:

  • cfn-lint-action by Scott Brenner enables arbitrary actions for interacting with CloudFormation Linter.
  • amazon-ecr-login by AWS logs in the local Docker client to one or more ECR registries.
  • cache by GitHub allows caching dependencies and build outputs to improve workflow execution time.

Be careful when adding 3rd party actions to your deployment pipeline. First of all, you need to 100% trust the code that you are adding to your deployment pipeline. In theory, someone could insert malicious code or steal your AWS credentials by publishing a trojan horse to the GitHub Marketplace. Also, a 3rd party action could be removed from the GitHub Marketplace, which will break your deployment pipeline out of a sudden.

Luckily, it is not very hard to implement your own GitHub Actions.

  • Node.js run some JavaScript code
  • Docker run anything that you have packaged into a Docker image before

The following example shows how to build a GitHub Action to deploy a CloudFormation stack. I’ve decided to use a Docker-based action, as this approach is very flexible.

First of all, you need to define a Dockerfile. The Dockerfile defines the base image, installs build dependencies, and adds the entrypoint.sh script, which will be executed on each action invocation.

Dockerfile
# Base image to start from
FROM amazonlinux:2

# Installs the AWS CLI
RUN yum install -y awscli

# Adds custom entrypoint
COPY entrypoint.sh /entrypoint.sh

# Execute custom entrypoint by default when starting the container
ENTRYPOINT ["/entrypoint.sh"]

Use the entrypoint.sh script to customize your deployment. In this simple example, all we need to do is to execute the aws cloudformation deploy command.

entrypoing.sh
#!/bin/bash
set -ex

aws cloudformation deploy ...

One tiny bit is missing. GitHub Actions requires you to describe your action in an action.yml file. The configuration file includes a name and description for your action. On top of that, the action.yml file tells GitHub to run the action inside a Docker container. GitHub builds the container on-the-fly with the help of your Dockerfile.

action.yml
name: 'Deploy CloudFormation Stack'
description: 'Deploying a CoudFormation Stack'
runs:
using: 'docker'
image: 'Dockerfile'

That is a simple way to define custom actions for your deployment pipeline.

Configuration

How to configure a deployment pipeline? Define your pipeline as code. My blog post Delivery Pipeline as Code: AWS CloudFormation and AWS CodePipeline is still relevant. A lot of know-how and learnings will be baked into your deployment pipeline. Make sure that knowledge is written down in code so that you can reproduce it whenever necessary.

GitHub requires you to define your workflow within your source code repository. The following code snippet shows the definition of the deployment pipeline used to deploy this website.

  1. Check out the source code.
  2. Read the access keys for AWS from the repository secrets.
  3. Execute the custom deploy action described in the previous section.
.github/workflows/main.yml
on:
push:
branches:
- master
name: deploy
jobs:
deploy:
runs-on: ubuntu-latest
name: 'Deploy'
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: $
aws-secret-access-key: $
aws-region: eu-west-1
- name: Deploy
uses: ./.github/actions/deploy/
id: deploy

Use AWS CloudFormation or Terraform to define your AWS CodePipeline. The following example shows a CodePipeline written down as a CloudFormation template.

  1. Checkout source code.
  2. Deploy the CloudFormation stack.
pipeline.yml
# [...]
CodePipeline:
Type: 'AWS::CodePipeline::Pipeline'
Properties:
ArtifactStore:
Location: !Ref ArtifactStore
Type: S3
RoleArn: !Sub '${CodePipelineIAMRole.Arn}'
Stages:
- Name: Source
Actions:
- Name: Source
ActionTypeId:
Category: Source
Owner: ThirdParty
Version: 1
Provider: GitHub
OutputArtifacts:
- Name: Source
Configuration:
Owner: !Ref GitHubOwner
Repo: !Ref GitHubRepo
Branch: master
OAuthToken: !Ref GitHubOAuthToken
- Name: Deploy
Actions:
- Name: Deploy
ActionTypeId:
Category: Deploy
Owner: AWS
Version: 1
Provider: CloudFormation
InputArtifacts:
- Name: Source
Configuration:
ActionMode: CREATE_UPDATE
TemplatePath: 'Source::infrastructure.yml"
Capabilities: CAPABILITY_IAM
StackName: 'example'

For me, it is most important to define your deployment pipeline as code. Both approaches are similar to my point of view.

AWS Credentials

Your deployment pipelines need administrator access to be able to deploy your application and infrastructure to AWS. In general, you should avoid IAM users with access keys wherever possible. However, using access keys to authenticate an IAM user with far-reaching authorizations is the only option to execute a deployment with GitHub Actions. Of course, GitHub offers a way to store the AWS access keys in a secure and encrypted manner. A residual risk remains. On top of that, you need to rotate the access keys regularly to follow security best practices and compliance rules.

AWS CodePipeline has an advantage here. Instead of using static access keys, make use of IAM roles, which provide short-living access keys out-of-the-box. You can even define different IAM roles for various actions in your pipeline, which allows you to implement the least privilege principle.

Vendor Lock-in

In my view, there is no significant vendor lock-in for deployment pipelines. Make sure to put the real magic to custom actions running inside Docker containers. Doing so allows you to switch between CI/CD solutions very quickly. For example, I’ve migrated the deployment pipeline for this website from Jenkins to GitHub Actions within 2 hours.

It is worth mentioning that GitHub Actions works with your source code hosted on GitHub only. AWS CodePipeline works with your source code hosted on AWS CodeCommit, GitHub, or Amazon S3 (can be used as a workaround to integrate with any source code repository).

Summary

I like the experience that GitHub Actions are providing for building deployment pipelines. The deep integration into my development workflow (e.g., pull requests) is excellent. Also, GitHub Actions are easy to use. On the other hand, I’m missing the integrations into the AWS ecosystem that I’m used to from using AWS CodePipeline. However, the main concepts behind GitHub Actions and AWS CodePipeline are similar. Therefore, the details are decisive in the selection.

Andreas Wittig

Andreas Wittig

I’m an independent consultant, technical writer, and programming founder. All these activities have to do with AWS. I’m writing this blog and all other projects together with my brother Michael.

In 2009, we joined the same company as software developers. Three years later, we were looking for a way to deploy our software—an online banking platform—in an agile way. We got excited about the possibilities in the cloud and the DevOps movement. It’s no wonder we ended up migrating the whole infrastructure of Tullius Walden Bank to AWS. This was a first in the finance industry, at least in Germany! Since 2015, we have accelerated the cloud journeys of startups, mid-sized companies, and enterprises. We have penned books like Amazon Web Services in Action and Rapid Docker on AWS, we regularly update our blog, and we are contributing to the Open Source community. Besides running a 2-headed consultancy, we are entrepreneurs building Software-as-a-Service products.

We are available for projects.

You can contact me via Email, Twitter, and LinkedIn.

Briefcase icon
Hire me