Commit 5a9d16dceb213af734697e7f552a5b79b6e46893

Edward Thomson 2020-11-23T14:28:26

ci: support multi-arch docker builds Provide the base to our docker images and run with the QEMU docker support optionally.

diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml
index 99a4b15..a29030c 100644
--- a/.github/workflows/coverity.yml
+++ b/.github/workflows/coverity.yml
@@ -20,7 +20,7 @@ jobs:
       with:
         fetch-depth: 0
     - name: Download container
-      run: ci/getcontainer.sh ci/docker/xenial
+      run: ci/getcontainer.sh xenial
       env:
         DOCKER_REGISTRY: ${{ env.docker-registry }}
         GITHUB_TOKEN: ${{ secrets.github_token }}
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 90fe4e0..091f518 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -26,10 +26,22 @@ jobs:
     strategy:
       matrix:
         container:
-        - xenial
-        - bionic
-        - focal
-        - docurium
+        - name: xenial
+        - name: bionic
+        - name: focal
+        - name: docurium
+        - name: bionic-x86
+          dockerfile: bionic
+          base: multiarch/ubuntu-core:x86-bionic
+          qemu: true
+        - name: bionic-arm32
+          dockerfile: bionic
+          base: multiarch/ubuntu-core:armhf-bionic
+          qemu: true
+        - name: bionic-arm64
+          dockerfile: bionic
+          base: multiarch/ubuntu-core:arm64-bionic
+          qemu: true
     runs-on: ubuntu-latest
     steps:
     - name: Check out repository
@@ -37,15 +49,23 @@ jobs:
       with:
         fetch-depth: 0
       if: github.event_name == 'push'
+    - name: Setup QEMU
+      run: docker run --rm --privileged multiarch/qemu-user-static:register --reset
+      if: matrix.container.qemu == true
     - name: Download existing container
-      run: ci/getcontainer.sh ${{ env.docker-config-path }}/${{ matrix.container }}
+      run: |
+        "${{ github.workspace }}/ci/getcontainer.sh" "${{ matrix.container.name }}" "${{ matrix.container.dockerfile }}"
       env:
         DOCKER_REGISTRY: ${{ env.docker-registry }}
         GITHUB_TOKEN: ${{ secrets.github_token }}
+      working-directory: ${{ env.docker-config-path }}
       if: github.event_name == 'push'
     - name: Build and publish image
       run: |
-        docker build -t ${{ env.docker-registry-container-sha }} --build-arg BASE=${{ matrix.container.base }} -f ${{ matrix.container }} .
+        if [ "${{ matrix.container.base }}" != "" ]; then
+          BASE_ARG="--build-arg BASE=${{ matrix.container.base }}"
+        fi
+        docker build -t ${{ env.docker-registry-container-sha }} ${BASE_ARG} -f ${{ env.dockerfile }} .
         docker push ${{ env.docker-registry-container-sha }}
       working-directory: ${{ env.docker-config-path }}
       if: github.event_name == 'push' && env.docker-container-exists != 'true'
@@ -55,40 +75,45 @@ jobs:
   # or on the actual hosts (macOS, Windows).
   build:
     name: Build
-    needs: [build_containers]
+    needs: [ build_containers ]
     strategy:
       matrix:
         platform:
         - # Xenial, GCC, OpenSSL
-          image: xenial
+          container:
+            name: xenial
           env:
             CC: gcc
             CMAKE_GENERATOR: Ninja
             CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DREGEX_BACKEND=builtin -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
           os: ubuntu-latest
         - # Xenial, GCC, mbedTLS
-          image: xenial
+          container:
+            name: xenial
           env:
             CC: gcc
             CMAKE_GENERATOR: Ninja
             CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
           os: ubuntu-latest
         - # Xenial, Clang, OpenSSL
-          image: xenial
+          container:
+            name: xenial
           env:
             CC: clang
             CMAKE_GENERATOR: Ninja
             CMAKE_OPTIONS: -DUSE_HTTPS=OpenSSL -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
           os: ubuntu-latest
         - # Xenial, Clang, mbedTLS
-          image: xenial
+          container:
+            name: xenial
           env:
             CC: clang
             CMAKE_OPTIONS: -DUSE_HTTPS=mbedTLS -DUSE_SHA1=HTTPS -DREGEX_BACKEND=pcre -DDEPRECATE_HARD=ON -DUSE_LEAK_CHECKER=valgrind -DUSE_GSSAPI=ON
             CMAKE_GENERATOR: Ninja
           os: ubuntu-latest
         - # Focal, Clang 10, mbedTLS, MemorySanitizer
-          image: focal
+          container:
+            name: focal
           env:
             CC: clang-10
             CFLAGS: -fsanitize=memory -fsanitize-memory-track-origins=2 -fsanitize-blacklist=/home/libgit2/source/script/sanitizers.supp -fno-optimize-sibling-calls -fno-omit-frame-pointer
@@ -99,7 +124,8 @@ jobs:
             ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
           os: ubuntu-latest
         - # Focal, Clang 10, OpenSSL, UndefinedBehaviorSanitizer
-          image: focal
+          container:
+            name: focal
           env:
             CC: clang-10
             CFLAGS: -fsanitize=undefined,nullability -fno-sanitize-recover=undefined,nullability -fsanitize-blacklist=/home/libgit2/source/script/sanitizers.supp -fno-optimize-sibling-calls -fno-omit-frame-pointer
@@ -110,7 +136,8 @@ jobs:
             ASAN_SYMBOLIZER_PATH: /usr/bin/llvm-symbolizer-10
           os: ubuntu-latest
         - # Focal, Clang 10, OpenSSL, ThreadSanitizer
-          image: focal
+          container:
+            name: focal
           env:
             CC: clang-10
             CFLAGS: -fsanitize=thread -fno-optimize-sibling-calls -fno-omit-frame-pointer
@@ -181,21 +208,26 @@ jobs:
       run: ci/setup-${{ matrix.platform.setup-script }}.sh
       shell: bash
       if: matrix.platform.setup-script != ''
+    - name: Setup QEMU
+      run: docker run --rm --privileged multiarch/qemu-user-static:register --reset
+      if: matrix.platform.container.qemu == true
     - name: Download container
-      run: ci/getcontainer.sh ${{ env.docker-config-path }}/${{ matrix.platform.image }}
+      run: |
+        "${{ github.workspace }}/ci/getcontainer.sh" "${{ matrix.platform.container.name }}" "${{ matrix.platform.container.dockerfile }}"
       env:
         DOCKER_REGISTRY: ${{ env.docker-registry }}
         GITHUB_TOKEN: ${{ secrets.github_token }}
-      if: matrix.platform.image != ''
+      working-directory: ${{ env.docker-config-path }}
+      if: matrix.platform.container.name != ''
     - name: Create container
-      run: docker build -t ${{ env.docker-registry-container-sha }} -f ${{ matrix.platform.image }} .
+      run: docker build -t ${{ env.docker-registry-container-sha }} -f ${{ env.dockerfile }} .
       working-directory: ${{ env.docker-config-path }}
-      if: matrix.platform.image != '' && env.docker-container-exists != 'true'
+      if: matrix.platform.container.name != '' && env.docker-container-exists != 'true'
     - name: Build and test
       run: |
         export GITTEST_NEGOTIATE_PASSWORD="${{ secrets.GITTEST_NEGOTIATE_PASSWORD }}"
 
-        if [ -n "${{ matrix.platform.image }}" ]; then
+        if [ -n "${{ matrix.platform.container.name }}" ]; then
           docker run \
               --rm \
               -v "$(pwd):/home/libgit2/source" \
@@ -229,6 +261,13 @@ jobs:
     needs: [build_containers]
     runs-on: ubuntu-latest
     steps:
+    - name: Setup defaults
+      run: |
+        if [ "${{ matrix.container.dockerfile }}" = "" ]; then
+          echo "dockerfile=${{ matrix.container.dockerfile }}" >> $GITHUB_ENV
+        else
+          echo "dockerfile=${{ matrix.container.dockerfile }}" >> $GITHUB_ENV
+        fi
     - name: Check out repository
       uses: actions/checkout@v2
       with:
diff --git a/ci/docker/bionic b/ci/docker/bionic
index 9ecb5da..85bb6ec 100644
--- a/ci/docker/bionic
+++ b/ci/docker/bionic
@@ -1,4 +1,5 @@
-FROM ubuntu:bionic AS apt
+ARG BASE=ubuntu:bionic
+FROM ${BASE} AS apt
 RUN apt-get update && \
     DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
         clang \
diff --git a/ci/docker/docurium b/ci/docker/docurium
index 54a4202..7aa2475 100644
--- a/ci/docker/docurium
+++ b/ci/docker/docurium
@@ -1,3 +1,4 @@
-FROM ubuntu:bionic
+ARG BASE=ubuntu:bionic
+FROM ${BASE}
 RUN apt update && apt install -y cmake pkg-config ruby ruby-dev llvm libclang-dev libssl-dev python-pygments
 RUN gem install docurium
diff --git a/ci/docker/focal b/ci/docker/focal
index c75e85a..c6fefc7 100644
--- a/ci/docker/focal
+++ b/ci/docker/focal
@@ -1,4 +1,5 @@
-FROM ubuntu:focal AS apt
+ARG BASE=ubuntu:focal
+FROM ${BASE} AS apt
 RUN apt-get update && \
     DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
         bzip2 \
diff --git a/ci/docker/xenial b/ci/docker/xenial
index 67867ed..1c8e585 100644
--- a/ci/docker/xenial
+++ b/ci/docker/xenial
@@ -1,4 +1,5 @@
-FROM ubuntu:xenial AS apt
+ARG BASE=ubuntu:xenial
+FROM ${BASE} AS apt
 RUN apt-get update && \
     DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
         bzip2 \
diff --git a/ci/getcontainer.sh b/ci/getcontainer.sh
index b259260..07ef7b8 100755
--- a/ci/getcontainer.sh
+++ b/ci/getcontainer.sh
@@ -2,22 +2,28 @@
 
 set -e
 
-DOCKERFILE_PATH=$1
+IMAGE_NAME=$1
+DOCKERFILE_PATH=$2
 
-if [ "${DOCKERFILE_PATH}" = "" ]; then
-	echo "usage: $0 dockerfile"
+if [ "${IMAGE_NAME}" = "" ]; then
+	echo "usage: $0 image_name [dockerfile]"
 	exit 1
 fi
 
+if [ "${DOCKERFILE_PATH}" = "" ]; then
+	DOCKERFILE_PATH="${IMAGE_NAME}"
+fi
+
 if [ "${DOCKER_REGISTRY}" = "" ]; then
 	echo "DOCKER_REGISTRY environment variable is unset."
 	echo "Not running inside GitHub Actions or misconfigured?"
 	exit 1
 fi
 
-DOCKER_CONTAINER="${GITHUB_REPOSITORY}/$(basename ${DOCKERFILE_PATH})"
+DOCKER_CONTAINER="${GITHUB_REPOSITORY}/${IMAGE_NAME}"
 DOCKER_REGISTRY_CONTAINER="${DOCKER_REGISTRY}/${DOCKER_CONTAINER}"
 
+echo "dockerfile=${DOCKERFILE_PATH}" >> $GITHUB_ENV
 echo "docker-container=${DOCKER_CONTAINER}" >> $GITHUB_ENV
 echo "docker-registry-container=${DOCKER_REGISTRY_CONTAINER}" >> $GITHUB_ENV