Skip to content

Instantly share code, notes, and snippets.

@abasu0713
Last active June 23, 2024 21:20
Show Gist options
  • Save abasu0713/6cf75b06715cb91abc90099a91122a9c to your computer and use it in GitHub Desktop.
Save abasu0713/6cf75b06715cb91abc90099a91122a9c to your computer and use it in GitHub Desktop.
Staggered (Multi-Platform) CI using Github Actions

Staggered Continuous Integration using Github Actions

In this gist we are going to look at the simple steps required to build a staggered CI process using Github Actions that generate multi-platform images/packages/artifacts for any application. .

Some typical assumptions

  • We have an application that is deployed across 2 environments:

    1. live
    2. preview
  • We want to generate artifacts targeted for each environment that we can later use for manual and/or Continuous Deployment. Below represents a directory structure of a sample application

alphaduriendur@Arkos-MacBook-Pro personal-portfolio % tree -L 1
.
├── backend
├── deployment
└── frontend

4 directories, 0 files
alphaduriendur@Arkos-MacBook-Pro frontend % tree -L 1
.
├── Dockerfile
├── README.md
├── analysis_options.yaml
├── android
├── assets
├── build
├── images
├── ios
├── lib
├── linux
├── macos
├── pubspec.lock
├── pubspec.yaml
├── test
├── web
└── windows

12 directories, 5 files
alphaduriendur@Arkos-MacBook-Pro frontend %

The frontend in this case is a flutter app with it's own Dockerfile that builds the web server image behina a Nginx Proxy.

  • Here we create a simple Github Action Workflow that generates images based on the event:
    1. preview image on PRs and any following pushes to that PR
    2. live image on being merged to default branch.

Below is a sample Github Action that should give you a rough idea on how to go about it:

name: ci-frontend-web

on:
    push:
        branches:
            - "master"
        paths:
          - "frontend/**"
    pull_request:
        branches: [master]
        paths:
          - "frontend/**"
jobs:
  preview:
    name: Build and push for Preview
    if: github.event_name == 'pull_request' || github.ref == 'refs/heads/master' && ( github.event_name == 'push' || github.event_name == 'workflow_dispatch' )
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: ./frontend
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ secrets.DOCKERHUB_USERNAME }}/<repo-name>:preview

  live:
    name: Build and push for Live
    if: github.ref == 'refs/heads/master' && ( github.event_name == 'push' || github.event_name == 'workflow_dispatch' )
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
      
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      
      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          context: ./frontend
          platforms: linux/amd64,linux/arm64
          push: true
          tags: ${{ secrets.DOCKERHUB_USERNAME }}/<repo-name>:live

In the above sample we are:

  1. Using QEMU to build two different architectures of our image - amd64 and arm64. This allows us to run our containerized/packaged artifacts in our desired choice of hardware architecture. Check the documentation to see all the different architectures you can target for your build. If you are a systems administrators that maintain hybrid systems of mixed platforms then this would mean you would have no problem moving your application from one hardware platform to the other.
  2. We are also separating the workflow based on the event that was triggered.
Image showing workflow event

You can see for just a PR the job for the live build did not happen and was skipped since it did not satisfy the requirement

  1. Now when you merge the PR you see both images being built.
Merge action triggers both workflows

Feel free to suppress the preview step on the merge action if you like.

For more information on Github actions worfklows - follow the official documentation

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment