run: |
[[ "${REF}" == "master" ]] || git describe --tags --exact-match
- build:
- name: build docker image for a product
+ prepare-runner-os-list:
+ name: generate runner list
runs-on: ubuntu-24.04
- needs: validate-push-image
outputs:
- image-digest: ${{ steps.build-image.outputs.digest }}
+ runnerlist: ${{ steps.get-runnerlist.outputs.runnerlist }}
+ steps:
+ - run: sudo apt-get update && sudo apt-get -y install jo
+ - id: get-runnerlist
+ run: |
+ runner_os_arch=()
+ [[ -n "${{ contains(inputs.platforms, 'amd64') || '' }}" ]] && runner_os_arch+=($(jo arch=linux/amd64 runner=ubuntu-24.04))
+ [[ -n "${{ contains(inputs.platforms, 'arm64') || '' }}" ]] && runner_os_arch+=($(jo arch=linux/arm64 runner=ubuntu-24.04-arm))
+ echo "runnerlist=$(jo -a ${runner_os_arch[@]})" >> "$GITHUB_OUTPUT"
+ # Fail if there are no runners for the requested architecture
+ if [[ -z "${runner_os_arch[@]}" ]]; then
+ echo "No runners available for ${{ inputs.platforms }}" && exit 1
+ fi
+
+ build:
+ name: build ${{ matrix.platform.arch }} docker image for a product
+ runs-on: ${{ matrix.platform.runner }}
+ needs:
+ - validate-push-image
+ - prepare-runner-os-list
+ strategy:
+ fail-fast: false
+ matrix:
+ platform: ${{ fromJson(needs.prepare-runner-os-list.outputs.runnerlist) }}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{ inputs.ref }}
persist-credentials: false
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v3
- with:
- platforms: linux/arm64/v8
- name: Set up Docker Buildx for multi-platform builds
uses: docker/setup-buildx-action@v3
- with:
- platforms: ${{ inputs.platforms }}
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
- name: Login to Docker Hub
if: ${{ inputs.push }}
uses: docker/login-action@v3
uses: docker/metadata-action@v5
with:
images: ${{ secrets.DOCKERHUB_ORGANIZATION_NAME || 'powerdns' }}/${{ inputs.image-name }}
- tags: ${{ inputs.image-tags }}
- name: Build and load powerdns product images
id: build-image
uses: docker/build-push-action@v6
with:
context: .
file: Dockerfile-${{ inputs.product }}
- platforms: ${{ inputs.platforms }}
+ platforms: ${{ matrix.platform.arch }}
push: ${{ inputs.push }}
sbom: true
- tags: ${{ steps.meta.outputs.tags }}
+ tags: ${{ secrets.DOCKERHUB_ORGANIZATION_NAME || 'powerdns' }}/${{ inputs.image-name }}
build-args: ${{ inputs.build-args }}
+ outputs: type=image,push-by-digest=true,name-canonical=true
- name: Update repo description
if: ${{ inputs.push }}
uses: peter-evans/dockerhub-description@v4
password: ${{ secrets.DOCKERHUB_TOKEN }}
repository: ${{ secrets.DOCKERHUB_ORGANIZATION_NAME }}/${{ inputs.image-name }}
short-description: ${{ inputs.image-description }}
+ - name: Export output digest
+ run: |
+ mkdir -p ${{ runner.temp }}/digests
+ digest="${{ steps.build-image.outputs.digest }}"
+ touch "${{ runner.temp }}/digests/${digest#sha256:}"
+ # generate suffix for digest file
+ platform=${{ matrix.platform.arch }}
+ echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
+ - name: Upload digest
+ uses: actions/upload-artifact@v4
+ with:
+ name: digests-${{ inputs.product }}-${{ env.PLATFORM_PAIR }}
+ path: ${{ runner.temp }}/digests/*
+ if-no-files-found: error
+ retention-days: 1
- prepare-test-runner-os-list:
- name: generate runner list
+ publish-tag:
+ name: Generate and publish tag for multi-platform image
+ runs-on: ubuntu-24.04
if: ${{ inputs.push }}
needs: build
- runs-on: ubuntu-24.04
outputs:
- runnerlist: ${{ steps.get-runnerlist.outputs.runnerlist }}
- skiptests: ${{ steps.get-runnerlist.outputs.skiptests }}
+ image-digest: ${{ steps.get-image-digest.outputs.image-digest }}
steps:
- - run: sudo apt-get update && sudo apt-get -y install jo
- - id: get-runnerlist
+ - name: Download digests
+ uses: actions/download-artifact@v4
+ with:
+ path: ${{ runner.temp }}/digests
+ pattern: digests-${{ inputs.product }}-*
+ merge-multiple: true
+ - name: Login to Docker Hub
+ if: ${{ inputs.push }}
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+ - name: Docker meta
+ id: meta
+ uses: docker/metadata-action@v5
+ with:
+ images: ${{ secrets.DOCKERHUB_ORGANIZATION_NAME }}/${{ inputs.image-name }}
+ tags: ${{ inputs.image-tags }}
+ - name: Create manifest list and push
+ working-directory: ${{ runner.temp }}/digests
run: |
- runner_os=()
- [[ -n "${{ contains(inputs.platforms, 'amd64') && 'ubuntu-24.04' || '' }}" ]] && runner_os+=('ubuntu-24.04')
- [[ -n "${{ vars.ARM64_USE_UBICLOUD == '1' && contains(inputs.platforms, 'arm64') || '' }}" ]] && runner_os+=('ubicloud-standard-2-arm')
- echo "runnerlist=$(jo -a ${runner_os[@]})" >> "$GITHUB_OUTPUT"
- # Skip tests if no runner is suitable for running them. Set a default runner to avoid CI failure
- if [[ -z "${runner_os[@]}" ]]; then
- echo "runnerlist=$(jo -a ubuntu-24.04)" >> "$GITHUB_OUTPUT"
- echo "skiptests=1" >> "$GITHUB_OUTPUT"
- fi
+ docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \
+ $(printf '${{ secrets.DOCKERHUB_ORGANIZATION_NAME }}/${{ inputs.image-name }}@sha256:%s ' *)
+ - name: Get image digest
+ id: get-image-digest
+ run: |
+ echo "image-digest=$(docker buildx imagetools inspect ${{ secrets.DOCKERHUB_ORGANIZATION_NAME }}/${{ inputs.image-name }}:${{ steps.meta.outputs.version }} --format="{{json .Manifest}}" | jq -r .digest)" >> "$GITHUB_OUTPUT"
test-uploaded-images:
- name: test uploaded images
- if: ${{ inputs.push && ! needs.prepare-test-runner-os-list.outputs.skiptests }}
- needs: [build, prepare-test-runner-os-list]
- runs-on: ${{ matrix.runner-os }}
+ name: test ${{ matrix.platform.arch }} uploaded images
+ if: ${{ inputs.push }}
+ needs:
+ - prepare-runner-os-list
+ - publish-tag
+ runs-on: ${{ matrix.platform.runner }}
strategy:
matrix:
- runner-os: ${{ fromJson(needs.prepare-test-runner-os-list.outputs.runnerlist )}}
+ platform: ${{ fromJson(needs.prepare-runner-os-list.outputs.runnerlist) }}
fail-fast: false
env:
INPUT_IMAGE_NAME: ${{ inputs.image-name }}
image_name="${{ secrets.DOCKERHUB_ORGANIZATION_NAME }}/${INPUT_IMAGE_NAME}"
for tag in `echo "${INPUT_IMAGE_TAGS}" | tr '\n' ' '`; do
echo 'Testing: '${image_name}':'${tag};
- # pdns-auth image returns a 134 exit code
- docker run ${image_name}:${tag} --version || [ "$?" == "134" ]
+ # recent pdns-auth images of tags older than 4.9.x image return a exit code 99
+ docker run ${image_name}:${tag} --version || [ "$?" == "99" ]
done
- name: Check image digest matches
env:
- EXPECTED_DIGEST: ${{ needs.build.outputs.image-digest }}
+ EXPECTED_DIGEST: ${{ needs.publish-tag.outputs.image-digest }}
run: |
image_name="${{ secrets.DOCKERHUB_ORGANIZATION_NAME }}/${INPUT_IMAGE_NAME}"
for tag in `echo "${INPUT_IMAGE_TAGS}" | tr '\n' ' '`; do