Auto-deploy with Github OIDC and AWS
Photo by SpaceX on Unsplash

Auto-deploy with Github OIDC and AWS

So you have built your product you have written and tested tests for your application, and you have Docker setup. The only thing that remains is deploying so you build your image from a Dockerfile config or Docker compose and upload the image to AWS Elastic Container Registry (ECR) and continue from there.

But using this way of deploying is daunting and requires you to wait for the build to complete and there's no assurance of anything, what if you miss adding a configuration or a test failed and you only realize it after testing it on the production server you have set up. One solution is to use Github Actions Workflows in combination with its OpenID Connect.

OpenID Connect allows a workflow to access the cloud provider by requesting a short-lived token that will authenticate the workflow which in this case runs all tests and deploy a built image to the provider, ECR.

So here's how we do it,

First, we add set up our GitHub workflow for the project, in my case Golang. In the parent folder add a .github folder and add a tests.yml and a deploy.yml file.

In the tests.yml file we will add some config to run all of our tests we can then add a success requirement or guard to our main branch to guard it from accepting any Pull Requests (PR) that have less than 100% tests passed.


name: Run Unit test
# Add hook on the main branch
on:
    push:
      branches: [ "main" ]
    pull_request:
      branches: [ "main" ]

jobs:
    test:
        name: Test
        runs-on: ubuntu-latest

        services:
            mongodb:
                image: mongo
                env: 
                    DB_NAME: mydb
                    DB_USER: root
                    DB_PASS: secret
                ports:
                    - 8081:8081
                options: --health-cmd "mongo --version" --health-interval 10s --health-timeout 5s --health-retries 3
            
            redis:
                image: redis
                ports:
                    - 6379:6379
                options: --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 3

            
            rabbitmq:
                image: rabbitmq:3.8.9-management
                ports:
                    - 5672:5672
                    - 15672:15672
                env:
                    RQ_USERNAME: mr_rabbit
                    RQ_PASS: rabbitismypassword
                options: --health-cmd "rabbitmqctl node_health_check" --health-interval 10s --health-timeout 5s --health-retries 3
            
        steps:
            - name: Checkout code
              uses: actions/checkout@v3

            - name: Set up Go
              uses: actions/setup-go@v2
              with:
                go-version: 1.19
            
            - name: Install Dependencies
              run: go mod download

            - name: Run tests
              run: make test        

So the following configuration pulls all the images that my app needs to make a full tests run all on services, then downloads all dependencies then runs all tests via a command I have written in a Makefile.

Now for the cherry on top, we add our deploy

name: Deploy to production

on:
  push:
    branches: [ "main" ]

env:
    AWS_REGION: "us-east-2"

permissions:
    id-token: write # Required for requesting JWT
    contents: read # Required for checking out the repository

jobs:
    assumeRoleCallAndIdentity:
        runs-on: ubuntu-latest
        steps:
            - name: Checkout
              uses: actions/checkout@v3

            - name: Configure aws crendentials
              uses: aws-actions/configure-aws-credentials@v1.7.0
              with:
                role-to-assume: ${{ secrets.AWS_ARN }}
                role-session-name: ${{ secrets.AWS_ROLE_SESSION_NAME }}
                aws-region: ${{ env.AWS_REGION }}
            
            - name: STS GetCallerIdentity
              run: |
                aws sts get-caller-identity

    deploy:
        name: Build image
        runs-on: ubuntu-latest

        steps:
            - name: Checkout
              uses: actions/checkout@v3
            
            - name: Install Kubectl
              uses: azure/setup-kubectl@v3
              with:
                version: 'v.1.21.3'
              id: install
            
            - name: Login to AWS ECR
              id: login-ecr
              uses: aws-actions/amazon-ecr-login@v1
            
            - name: Build, tag, and push image to Amazon ECR
              env: 
                ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
                ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }}
                IMAGE_TAG: ${{ github.sha }}
              run: |
                docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
                docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG        

The config is almost the same as the test one allowing us to set the branch we want the workflow to trigger from. But we have an env, we set our config here so we can use it repetitively anywhere in the config. Since it's AWS we set the region, and permissions allow us to set rules for what the workflow can do and what it can't.

The sugar comes from the rest, the workflow allows us to assume a role as we would from the AWS Console. We use Github secrets to set our role Amazon Resource Name (ARN)

We use STS GetCallerIdentity to get details about the current role, this will tell the next action whether pushing to ECR is allowed for the role.

Finally, We build the image and deploy it to the ECR, the secrets you see there tells the GitHub Action where to push the built image. We can also set the tag to ensure we use a specific TAG for different use cases. We can have one for Staging, Development and another for Production to set up a healthy development pipeline.

To Finalise, you can head to the repository to the Settings tab and select the Actions and all the way down allow Github Actions to approve PRs

No alt text provided for this image

Happy building 🔥🔥.

To learn more about this head over to the following to get a better understanding.


Github OIDC. Learn how to configure Auto Deploy for any Cloud Provider

AWS Identity Providers. AWS provision for Identities



To view or add a comment, sign in

More articles by Brian mwangi

  • MongoDB and Docker Compose

    One of the hard things I had to do recently was trying to work with MongoDB and Docker Compose. The problem was that I…

Explore content categories