Skip to content

Commit

Permalink
Build multi-architecture images (#197)
Browse files Browse the repository at this point in the history
# What
Allows us to push multi-architecture builds for `linux/amd64` and `linux/arm64` on merge to master. Fixes: #196

Tests are performed by building the relevant image and tagging it with the image name the tests expect.  This follows the original implementation in `test.sh`.  This will likely change to an explicit image name specification as we move the test suite in to Javascript but it's being maintained for now in the interest of simplicity.

## Goals
* To decouple image build from the test run. This will help as we refactor the test suite for this issue #191.
* Not have CI take a long time due to multi-architecture builds for interim pushes to pull requests.
* CI should fail fast if any of the image builds or tests fail
* Parallelize builds as much as possible.


## Notes
* Since the `unprivileged` and `latest-njs` images build off the base `oss` image, there were some strange moves that had to be done to make that work without rebuilding the base image every time. Specifically, we had to set `setup-buildx-action` to run in `docker` driver mode so we can simply `load` the base image. Otherwise we would have had to use a local repository.  However, in `docker` mode `upload-artifact` doesn't like the file produced so we have to save the file again.
* I wanted to build images once and then run tests against them and push at the end. However, there was not a clean way to get the full multi-architecture images all the way to the push step so I just build them again against all architectures and perform tests in the runner architecture.  This saves us from needing conditionals in the test portions.
  • Loading branch information
4141done authored Jan 12, 2024
1 parent 231fa7d commit 98f31ef
Show file tree
Hide file tree
Showing 2 changed files with 268 additions and 119 deletions.
337 changes: 241 additions & 96 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,54 @@ on:
pull_request:
branches: [ master ]

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
build:
runs-on: ubuntu-latest

if: github.ref != 'refs/heads/master'
env:
CI: true


# Job progression. We make sure that the base image [oss] builds and passes tests before kicking off the other builds

# ┌──────────────────┐ ┌────────────────┐ ┌────────────────┐
# ┌─────────┐ ┌─────────┬────► Build Latest NJS ├────────►Test Latest NJS ├─────►│Push Latest NJS │
# │Build OSS├────►│Test OSS │ └──────────────────┘ └────────────────┘ └────────────────┘
# └─────────┘ └──┬──────┤
# │ │ ┌──────────────────┐ ┌──────────────────┐ ┌─────────────────┐
# │ └────►Build Unprivileged├───────►Test Unprivileged ├────►│Push Unprivileged│
# │ └──────────────────┘ └──────────────────┘ ├────────┬────────┘
# │ ├────────┤
# └──────────────────────────────────────────────────────────────►│Push OSS│
# └────────┘

# As a last step, if we are on the main/master branch, multi-architecture images will be built and pushed to github packages
# and docker hub

jobs:
build-oss-for-test:
runs-on: ubuntu-22.04
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and export
uses: docker/build-push-action@v5
with:
file: Dockerfile.oss
context: .
tags: nginx-s3-gateway , nginx-s3-gateway:oss
outputs: type=docker,dest=${{ runner.temp }}/oss.tar
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: oss
path: ${{ runner.temp }}/oss.tar
retention-days: 1
if-no-files-found: error

test-oss:
runs-on: ubuntu-22.04
needs: build-oss-for-test
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: sudo apt-get update -qq && sudo apt-get install -y curl wait-for-it
- name: Restore cached binaries
Expand All @@ -34,35 +72,60 @@ jobs:
curl --insecure --retry 6 --fail --silent --location "https://dl.min.io/client/mc/release/linux-$(dpkg --print-architecture)/archive/mc.RELEASE.2023-06-19T19-31-19Z.sha256sum" | sha256sum --check -
mv mc.RELEASE.2023-06-19T19-31-19Z mc
chmod +x mc
- name: Save cached binaries
id: cache-binaries-save
uses: actions/cache/save@v3
- name: Download artifact
uses: actions/download-artifact@v3
with:
path: .bin
key: ${{ steps.cache-binaries-restore.outputs.cache-primary-key }}
- name: Run tests - latest njs version
run: ./test.sh --latest-njs --type oss
name: oss
path: ${{ runner.temp }}
- name: Load image
run: |
docker load --input ${{ runner.temp }}/oss.tar
- name: Run tests - stable njs version
run: ./test.sh --type oss
- name: Run tests - stable njs version - unprivileged process
run: ./test.sh --unprivileged --type oss
- name: Run tests - latest njs version - unprivileged process
run: ./test.sh --latest-njs --unprivileged --type oss

build_and_deploy:
runs-on: ubuntu-latest

if: github.ref == 'refs/heads/master'
build-latest-njs-for-test:
runs-on: ubuntu-22.04
needs: test-oss
steps:
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- uses: actions/checkout@v2

- name: Get current date
id: date
run: echo "date=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
- name: Configure Github Package Registry
run: echo ${{ secrets.GITHUB_TOKEN }} | docker login docker.pkg.github.com -u $GITHUB_ACTOR --password-stdin
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker
- name: Download artifact
uses: actions/download-artifact@v3
with:
name: oss
path: ${{ runner.temp }}
- name: Load image
run: |
docker load --input ${{ runner.temp }}/oss.tar
- name: Build and load oss image
uses: docker/build-push-action@v5
with:
file: Dockerfile.latest-njs
context: .
tags: nginx-s3-gateway:latest-njs-oss
load: true
# Save manually here since we need to use the `docker` buildx `driver` but that can't output
# a file that upload-artifact likes.
- name: save image
run: |
docker save nginx-s3-gateway:latest-njs-oss > ${{ runner.temp }}/latest-njs.tar
- name: Upload artifact - latest-njs
uses: actions/upload-artifact@v3
with:
name: latest-njs
path: ${{ runner.temp }}/latest-njs.tar
retention-days: 1
if-no-files-found: error

test-latest-njs:
runs-on: ubuntu-22.04
needs: build-latest-njs-for-test
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: sudo apt-get update -qq && sudo apt-get install -y curl wait-for-it
- name: Restore cached binaries
Expand All @@ -75,79 +138,161 @@ jobs:
run: |
mkdir .bin || exit 0
cd .bin
curl --insecure --retry 6 --fail --silent --location --output mc.RELEASE.2023-06-19T19-31-19Z "https://dl.min.io/client/mc/release/linux-$(dpkg --print-architecture)/archive/mc.RELEASE.2023-06-19T19-31-19Z"
curl --insecure --retry 6 --fail --location --output mc.RELEASE.2023-06-19T19-31-19Z "https://dl.min.io/client/mc/release/linux-$(dpkg --print-architecture)/archive/mc.RELEASE.2023-06-19T19-31-19Z"
curl --insecure --retry 6 --fail --silent --location "https://dl.min.io/client/mc/release/linux-$(dpkg --print-architecture)/archive/mc.RELEASE.2023-06-19T19-31-19Z.sha256sum" | sha256sum --check -
mv mc.RELEASE.2023-06-19T19-31-19Z mc
chmod +x mc
# Run tests and builds image
- name: Download artifact
uses: actions/download-artifact@v3
with:
name: latest-njs
path: ${{ runner.temp }}
- name: Load image
run: |
docker load --input ${{ runner.temp }}/latest-njs.tar
docker tag nginx-s3-gateway:latest-njs-oss nginx-s3-gateway
- name: Run tests - latest njs version
run: ./test.sh --latest-njs --type oss
# latest-njs-oss image push [Github]
- name: Tag container image for Push to github [latest-njs-oss date]
run: docker tag nginx-s3-gateway:latest-njs-oss docker.pkg.github.com/$GITHUB_REPOSITORY/nginx-oss-s3-gateway:latest-njs-oss-${{ steps.date.outputs.date }}
- name: Tag container image for Push to github [latest-njs-oss]
run: docker tag nginx-s3-gateway:latest-njs-oss docker.pkg.github.com/$GITHUB_REPOSITORY/nginx-oss-s3-gateway:latest-njs-oss
- name: Push container image to github [latest-njs-oss date]
run: docker push docker.pkg.github.com/$GITHUB_REPOSITORY/nginx-oss-s3-gateway:latest-njs-oss-${{ steps.date.outputs.date }}
- name: Push container image to github [latest-njs-oss]
run: docker push docker.pkg.github.com/$GITHUB_REPOSITORY/nginx-oss-s3-gateway:latest-njs-oss

# Run tests and builds image
- name: Run tests - stable njs version - unprivileged process

build-unprivileged-for-test:
runs-on: ubuntu-22.04
needs: test-oss
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
driver: docker
- name: Download artifact
uses: actions/download-artifact@v3
with:
name: oss
path: ${{ runner.temp }}
- name: Load image
run: |
docker load --input ${{ runner.temp }}/oss.tar
- name: Build and load oss image
uses: docker/build-push-action@v5
with:
file: Dockerfile.unprivileged
context: .
tags: nginx-s3-gateway:unprivileged-oss
load: true
# Save manually here since we need to use the `docker` buildx `driver` but that can't output
# a file that upload-artifact likes.
- name: save image
run: |
docker save nginx-s3-gateway:unprivileged-oss > ${{ runner.temp }}/unprivileged.tar
- name: Upload artifact - unprivileged
uses: actions/upload-artifact@v3
with:
name: unprivileged
path: ${{ runner.temp }}/unprivileged.tar
retention-days: 1
if-no-files-found: error

test-unprivileged:
runs-on: ubuntu-22.04
needs: build-unprivileged-for-test
steps:
- uses: actions/checkout@v4
- name: Install dependencies
run: sudo apt-get update -qq && sudo apt-get install -y curl wait-for-it
- name: Restore cached binaries
id: cache-binaries-restore
uses: actions/cache/restore@v3
with:
path: .bin
key: ${{ runner.os }}-binaries
- name: Install MinIO Client
run: |
mkdir .bin || exit 0
cd .bin
curl --insecure --retry 6 --fail --location --output mc.RELEASE.2023-06-19T19-31-19Z "https://dl.min.io/client/mc/release/linux-$(dpkg --print-architecture)/archive/mc.RELEASE.2023-06-19T19-31-19Z"
curl --insecure --retry 6 --fail --silent --location "https://dl.min.io/client/mc/release/linux-$(dpkg --print-architecture)/archive/mc.RELEASE.2023-06-19T19-31-19Z.sha256sum" | sha256sum --check -
mv mc.RELEASE.2023-06-19T19-31-19Z mc
chmod +x mc
- name: Download artifact
uses: actions/download-artifact@v3
with:
name: unprivileged
path: ${{ runner.temp }}
- name: Load image
run: |
docker load --input ${{ runner.temp }}/unprivileged.tar
docker tag nginx-s3-gateway:unprivileged-oss nginx-s3-gateway
- name: Run tests - unprivileged
run: ./test.sh --unprivileged --type oss
# unprivileged-oss image push [Github]
- name: Tag container image for Push to github [unprivileged-oss date]
run: docker tag nginx-s3-gateway:unprivileged-oss docker.pkg.github.com/$GITHUB_REPOSITORY/nginx-oss-s3-gateway:unprivileged-oss-${{ steps.date.outputs.date }}
- name: Tag container image for Push to github [unprivileged-oss]
run: docker tag nginx-s3-gateway:unprivileged-oss docker.pkg.github.com/$GITHUB_REPOSITORY/nginx-oss-s3-gateway:unprivileged-oss
- name: Push container image to github [unprivileged-oss date]
run: docker push docker.pkg.github.com/$GITHUB_REPOSITORY/nginx-oss-s3-gateway:unprivileged-oss-${{ steps.date.outputs.date }}
- name: Push container image to github [unprivileged-oss]
run: docker push docker.pkg.github.com/$GITHUB_REPOSITORY/nginx-oss-s3-gateway:unprivileged-oss

# Run tests and builds image
- name: Run tests - stable njs version
run: ./test.sh --type oss
# oss image push [Github]
- name: Tag container image for Push to github [oss date]
run: docker tag nginx-s3-gateway:oss docker.pkg.github.com/$GITHUB_REPOSITORY/nginx-oss-s3-gateway:latest-${{ steps.date.outputs.date }}
- name: Tag container image for Push to github [oss]
run: docker tag nginx-s3-gateway:oss docker.pkg.github.com/$GITHUB_REPOSITORY/nginx-oss-s3-gateway:latest
- name: Push container image to github [oss date]
run: docker push docker.pkg.github.com/$GITHUB_REPOSITORY/nginx-oss-s3-gateway:latest-${{ steps.date.outputs.date }}
- name: Push container image to github [oss latest]
run: docker push docker.pkg.github.com/$GITHUB_REPOSITORY/nginx-oss-s3-gateway:latest
# Login to Docker Hub

# After the tests are done, build multiarch and push to both github packages and dockerhub if we are on master/main
tag-and-push:
runs-on: ubuntu-22.04
needs: [test-oss, test-latest-njs, test-unprivileged]

if: |
github.ref == 'refs/heads/master' ||
github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Get current date
id: date
run: echo "date=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
with:
platforms: linux/amd64,linux/arm64
- name: Login to Docker Hub
uses: docker/login-action@v1
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_HUB_USERNAME }}
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
# latest-njs-oss image push [Docker Hub]
- name: Tag container image for Push to Docker Hub [latest-njs-oss date]
run: docker tag nginx-s3-gateway:latest-njs-oss nginxinc/nginx-s3-gateway:latest-njs-oss-${{ steps.date.outputs.date }}
- name: Tag container image for Push to Docker Hub [latest-njs-oss]
run: docker tag nginx-s3-gateway:latest-njs-oss nginxinc/nginx-s3-gateway:latest-njs-oss
- name: Push container image to Docker Hub [latest-njs-oss date]
run: docker push nginxinc/nginx-s3-gateway:latest-njs-oss-${{ steps.date.outputs.date }}
- name: Push container image to Docker Hub [latest-njs-oss]
run: docker push nginxinc/nginx-s3-gateway:latest-njs-oss
# unprivileged-oss image push [Docker Hub]
- name: Tag container image for Push to Docker Hub [unprivileged-oss date]
run: docker tag nginx-s3-gateway:unprivileged-oss nginxinc/nginx-s3-gateway:unprivileged-oss-${{ steps.date.outputs.date }}
- name: Tag container image for Push to Docker Hub [unprivileged-oss]
run: docker tag nginx-s3-gateway:unprivileged-oss nginxinc/nginx-s3-gateway:unprivileged-oss
- name: Push container image to Docker Hub [unprivileged-oss date]
run: docker push nginxinc/nginx-s3-gateway:unprivileged-oss-${{ steps.date.outputs.date }}
- name: Push container image to Docker Hub [unprivileged-oss]
run: docker push nginxinc/nginx-s3-gateway:unprivileged-oss
# oss image push [Docker Hub]
- name: Tag container image for Push to Docker Hub [oss date]
run: docker tag nginx-s3-gateway:oss nginxinc/nginx-s3-gateway:latest-${{ steps.date.outputs.date }}
- name: Tag container image for Push to Docker Hub [oss]
run: docker tag nginx-s3-gateway:oss nginxinc/nginx-s3-gateway:latest
- name: Push container image to Docker Hub [oss date]
run: docker push nginxinc/nginx-s3-gateway:latest-${{ steps.date.outputs.date }}
- name: Push container image to Docker Hub [oss latest]
run: docker push nginxinc/nginx-s3-gateway:latest
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Build and push image [oss]
uses: docker/build-push-action@v5
with:
file: Dockerfile.oss
context: .
push: true
platforms: linux/amd64,linux/arm64
provenance: false
tags: |
ghcr.io/${{ github.repository }}/nginx-oss-s3-gateway:latest-${{ steps.date.outputs.date }}
ghcr.io/${{ github.repository }}/nginx-oss-s3-gateway:latest
nginxinc/nginx-s3-gateway:latest-${{ steps.date.outputs.date }}
nginxinc/nginx-s3-gateway:latest
- name: Build and push image [latest-njs]
uses: docker/build-push-action@v5
with:
file: Dockerfile.latest-njs
context: .
push: true
platforms: linux/amd64,linux/arm64
provenance: false
tags: |
ghcr.io/${{ github.repository }}/nginx-oss-s3-gateway:latest-njs-oss-${{ steps.date.outputs.date }}
ghcr.io/${{ github.repository }}/nginx-oss-s3-gateway:latest-njs-oss
nginxinc/nginx-s3-gateway:latest-njs-oss-${{ steps.date.outputs.date }}
nginxinc/nginx-s3-gateway:latest-njs-oss
- name: Build and push image [unprivileged]
uses: docker/build-push-action@v5
with:
file: Dockerfile.unprivileged
context: .
push: true
platforms: linux/amd64,linux/arm64
provenance: false
tags: |
ghcr.io/${{ github.repository }}/nginx-oss-s3-gateway:unprivileged-oss-${{ steps.date.outputs.date }}
ghcr.io/${{ github.repository }}/nginx-oss-s3-gateway:unprivileged-oss
nginxinc/nginx-s3-gateway:unprivileged-oss-${{ steps.date.outputs.date }}
nginxinc/nginx-s3-gateway:unprivileged-oss
Loading

0 comments on commit 98f31ef

Please sign in to comment.