mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2026-01-14 21:54:22 -06:00
Chore: Build the ARM64 image using the native ARM64 runner (#11720)
This commit is contained in:
225
.github/workflows/ci-docker.yml
vendored
225
.github/workflows/ci-docker.yml
vendored
@@ -15,100 +15,219 @@ on:
|
|||||||
concurrency:
|
concurrency:
|
||||||
group: docker-${{ github.event.pull_request.number || github.ref }}
|
group: docker-${{ github.event.pull_request.number || github.ref }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
env:
|
||||||
|
REGISTRY: ghcr.io
|
||||||
jobs:
|
jobs:
|
||||||
build-docker-image:
|
build-arch:
|
||||||
name: Build Docker Image
|
name: Build ${{ matrix.arch }}
|
||||||
runs-on: ubuntu-24.04
|
strategy:
|
||||||
env:
|
fail-fast: false
|
||||||
CAN_PUSH: ${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }}
|
matrix:
|
||||||
|
include:
|
||||||
|
- runner: ubuntu-24.04
|
||||||
|
arch: amd64
|
||||||
|
platform: linux/amd64
|
||||||
|
- runner: ubuntu-24.04-arm
|
||||||
|
arch: arm64
|
||||||
|
platform: linux/arm64
|
||||||
|
runs-on: ${{ matrix.runner }}
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
outputs:
|
||||||
|
can-push: ${{ steps.check-push.outputs.can-push }}
|
||||||
|
push-external: ${{ steps.check-push.outputs.push-external }}
|
||||||
|
repository: ${{ steps.repo.outputs.name }}
|
||||||
|
ref-name: ${{ steps.ref.outputs.name }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6.0.1
|
||||||
- name: Determine ref name
|
- name: Determine ref name
|
||||||
id: ref
|
id: ref
|
||||||
run: |
|
run: |
|
||||||
echo "name=${GITHUB_HEAD_REF:-$GITHUB_REF_NAME}" >> $GITHUB_OUTPUT
|
ref_name="${GITHUB_HEAD_REF:-$GITHUB_REF_NAME}"
|
||||||
- name: Check external registry push
|
# Sanitize by replacing / with - for cache keys
|
||||||
id: push-external
|
cache_ref="${ref_name//\//-}"
|
||||||
|
|
||||||
|
echo "ref_name=${ref_name}"
|
||||||
|
echo "cache_ref=${cache_ref}"
|
||||||
|
|
||||||
|
echo "name=${ref_name}" >> $GITHUB_OUTPUT
|
||||||
|
echo "cache-ref=${cache_ref}" >> $GITHUB_OUTPUT
|
||||||
|
- name: Check push permissions
|
||||||
|
id: check-push
|
||||||
env:
|
env:
|
||||||
REF_NAME: ${{ steps.ref.outputs.name }}
|
REF_NAME: ${{ steps.ref.outputs.name }}
|
||||||
run: |
|
run: |
|
||||||
# If we cannot push (e.g. fork PR), explicitly disable external push and exit
|
# can-push: Can we push to GHCR?
|
||||||
if [[ "$CAN_PUSH" != "true" ]]; then
|
# True for: pushes, or PRs from the same repo (not forks)
|
||||||
echo "enable=false" >> $GITHUB_OUTPUT
|
can_push=${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }}
|
||||||
exit 0
|
echo "can-push=${can_push}"
|
||||||
fi
|
echo "can-push=${can_push}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
# Only push to Docker Hub / Quay from main repo on specific branches/tags
|
# push-external: Should we also push to Docker Hub and Quay.io?
|
||||||
if [[ "${{ github.repository_owner }}" == "paperless-ngx" ]]; then
|
# Only for main repo on dev/beta branches or version tags
|
||||||
case "$REF_NAME" in
|
push_external="false"
|
||||||
|
if [[ "${can_push}" == "true" && "${{ github.repository_owner }}" == "paperless-ngx" ]]; then
|
||||||
|
case "${REF_NAME}" in
|
||||||
dev|beta)
|
dev|beta)
|
||||||
echo "enable=true" >> $GITHUB_OUTPUT
|
push_external="true"
|
||||||
exit 0
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
case "$GITHUB_REF" in
|
case "${{ github.ref }}" in
|
||||||
refs/tags/v*|*beta.rc*)
|
refs/tags/v*|*beta.rc*)
|
||||||
echo "enable=true" >> $GITHUB_OUTPUT
|
push_external="true"
|
||||||
exit 0
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
echo "enable=false" >> $GITHUB_OUTPUT
|
echo "push-external=${push_external}"
|
||||||
|
echo "push-external=${push_external}" >> $GITHUB_OUTPUT
|
||||||
|
- name: Set repository name
|
||||||
|
id: repo
|
||||||
|
run: |
|
||||||
|
repo_name="${{ github.repository }}"
|
||||||
|
repo_name="${repo_name,,}"
|
||||||
|
|
||||||
|
echo "repository=${repo_name}"
|
||||||
|
echo "name=${repo_name}" >> $GITHUB_OUTPUT
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3.12.0
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3.6.0
|
||||||
|
with:
|
||||||
|
registry: ${{ env.REGISTRY }}
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Docker metadata
|
- name: Docker metadata
|
||||||
id: docker-meta
|
id: docker-meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5.10.0
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
ghcr.io/${{ github.repository }}
|
${{ env.REGISTRY }}/${{ steps.repo.outputs.name }}
|
||||||
name=paperlessngx/paperless-ngx,enable=${{ steps.push-external.outputs.enable }}
|
|
||||||
name=quay.io/paperlessngx/paperless-ngx,enable=${{ steps.push-external.outputs.enable }}
|
|
||||||
tags: |
|
tags: |
|
||||||
type=ref,event=branch
|
type=ref,event=branch
|
||||||
type=raw,value=${{ steps.ref.outputs.name }},enable=${{ github.event_name == 'pull_request' }}
|
type=raw,value=${{ steps.ref.outputs.name }},enable=${{ github.event_name == 'pull_request' }}
|
||||||
type=semver,pattern={{version}}
|
type=semver,pattern={{version}}
|
||||||
type=semver,pattern={{major}}.{{minor}}
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
|
- name: Build and push by digest
|
||||||
|
id: build
|
||||||
|
uses: docker/build-push-action@v6.18.0
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
platforms: ${{ matrix.platform }}
|
||||||
|
labels: ${{ steps.docker-meta.outputs.labels }}
|
||||||
|
build-args: |
|
||||||
|
PNGX_TAG_VERSION=${{ steps.docker-meta.outputs.version }}
|
||||||
|
outputs: type=image,name=${{ env.REGISTRY }}/${{ steps.repo.outputs.name }},push-by-digest=true,name-canonical=true,push=${{ steps.check-push.outputs.can-push }}
|
||||||
|
cache-from: |
|
||||||
|
type=registry,ref=${{ env.REGISTRY }}/${{ steps.repo.outputs.name }}/cache/app:${{ steps.ref.outputs.cache-ref }}-${{ matrix.arch }}
|
||||||
|
type=registry,ref=${{ env.REGISTRY }}/${{ steps.repo.outputs.name }}/cache/app:dev-${{ matrix.arch }}
|
||||||
|
cache-to: ${{ steps.check-push.outputs.can-push == 'true' && format('type=registry,mode=max,ref={0}/{1}/cache/app:{2}-{3}', env.REGISTRY, steps.repo.outputs.name, steps.ref.outputs.cache-ref, matrix.arch) || '' }}
|
||||||
|
- name: Export digest
|
||||||
|
if: steps.check-push.outputs.can-push == 'true'
|
||||||
|
run: |
|
||||||
|
mkdir -p /tmp/digests
|
||||||
|
digest="${{ steps.build.outputs.digest }}"
|
||||||
|
echo "digest=${digest}"
|
||||||
|
touch "/tmp/digests/${digest#sha256:}"
|
||||||
|
- name: Upload digest
|
||||||
|
if: steps.check-push.outputs.can-push == 'true'
|
||||||
|
uses: actions/upload-artifact@v6.0.0
|
||||||
|
with:
|
||||||
|
name: digests-${{ matrix.arch }}
|
||||||
|
path: /tmp/digests/*
|
||||||
|
if-no-files-found: error
|
||||||
|
retention-days: 1
|
||||||
|
merge-and-push:
|
||||||
|
name: Merge and Push Manifest
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
needs: build-arch
|
||||||
|
if: needs.build-arch.outputs.can-push == 'true'
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
steps:
|
||||||
|
- name: Download digests
|
||||||
|
uses: actions/download-artifact@v7.0.0
|
||||||
|
with:
|
||||||
|
path: /tmp/digests
|
||||||
|
pattern: digests-*
|
||||||
|
merge-multiple: true
|
||||||
|
- name: List digests
|
||||||
|
run: |
|
||||||
|
echo "Downloaded digests:"
|
||||||
|
ls -la /tmp/digests/
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v3
|
uses: docker/setup-buildx-action@v3.12.0
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
with:
|
|
||||||
platforms: arm64
|
|
||||||
- name: Login to GitHub Container Registry
|
- name: Login to GitHub Container Registry
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3.6.0
|
||||||
with:
|
with:
|
||||||
registry: ghcr.io
|
registry: ${{ env.REGISTRY }}
|
||||||
username: ${{ github.actor }}
|
username: ${{ github.actor }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
- name: Login to Docker Hub
|
- name: Login to Docker Hub
|
||||||
if: steps.push-external.outputs.enable == 'true'
|
if: needs.build-arch.outputs.push-external == 'true'
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3.6.0
|
||||||
with:
|
with:
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
- name: Login to Quay.io
|
- name: Login to Quay.io
|
||||||
if: steps.push-external.outputs.enable == 'true'
|
if: needs.build-arch.outputs.push-external == 'true'
|
||||||
uses: docker/login-action@v3
|
uses: docker/login-action@v3.6.0
|
||||||
with:
|
with:
|
||||||
registry: quay.io
|
registry: quay.io
|
||||||
username: ${{ secrets.QUAY_USERNAME }}
|
username: ${{ secrets.QUAY_USERNAME }}
|
||||||
password: ${{ secrets.QUAY_ROBOT_TOKEN }}
|
password: ${{ secrets.QUAY_ROBOT_TOKEN }}
|
||||||
- name: Build and push
|
- name: Docker metadata
|
||||||
uses: docker/build-push-action@v6
|
id: docker-meta
|
||||||
|
uses: docker/metadata-action@v5.10.0
|
||||||
with:
|
with:
|
||||||
context: .
|
images: |
|
||||||
file: ./Dockerfile
|
${{ env.REGISTRY }}/${{ needs.build-arch.outputs.repository }}
|
||||||
platforms: linux/amd64,linux/arm64
|
tags: |
|
||||||
push: ${{ env.CAN_PUSH == 'true' }}
|
type=ref,event=branch
|
||||||
tags: ${{ steps.docker-meta.outputs.tags }}
|
type=raw,value=${{ needs.build-arch.outputs.ref-name }},enable=${{ github.event_name == 'pull_request' }}
|
||||||
labels: ${{ steps.docker-meta.outputs.labels }}
|
type=semver,pattern={{version}}
|
||||||
build-args: |
|
type=semver,pattern={{major}}.{{minor}}
|
||||||
PNGX_TAG_VERSION=${{ steps.docker-meta.outputs.version }}
|
- name: Create manifest list and push
|
||||||
cache-from: |
|
working-directory: /tmp/digests
|
||||||
type=registry,ref=ghcr.io/${{ github.repository }}/cache/app:${{ steps.ref.outputs.name }}
|
env:
|
||||||
type=registry,ref=ghcr.io/${{ github.repository }}/cache/app:dev
|
REPOSITORY: ${{ needs.build-arch.outputs.repository }}
|
||||||
cache-to: ${{ env.CAN_PUSH == 'true' && format('type=registry,mode=max,ref=ghcr.io/{0}/cache/app:{1}', github.repository, steps.ref.outputs.name) || '' }}
|
run: |
|
||||||
|
tags=$(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "${DOCKER_METADATA_OUTPUT_JSON}")
|
||||||
|
|
||||||
|
digests=""
|
||||||
|
for digest in *; do
|
||||||
|
digests+="${{ env.REGISTRY }}/${REPOSITORY}@sha256:${digest} "
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Creating manifest with tags: ${tags}"
|
||||||
|
echo "From digests: ${digests}"
|
||||||
|
|
||||||
|
docker buildx imagetools create ${tags} ${digests}
|
||||||
- name: Inspect image
|
- name: Inspect image
|
||||||
if: env.CAN_PUSH == 'true'
|
|
||||||
run: |
|
run: |
|
||||||
docker buildx imagetools inspect ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
|
docker buildx imagetools inspect ${{ fromJSON(steps.docker-meta.outputs.json).tags[0] }}
|
||||||
|
- name: Copy to Docker Hub
|
||||||
|
if: needs.build-arch.outputs.push-external == 'true'
|
||||||
|
env:
|
||||||
|
TAGS: ${{ steps.docker-meta.outputs.tags }}
|
||||||
|
GHCR_REPO: ${{ env.REGISTRY }}/${{ needs.build-arch.outputs.repository }}
|
||||||
|
run: |
|
||||||
|
for tag in ${TAGS}; do
|
||||||
|
dockerhub_tag="${tag/${GHCR_REPO}/paperlessngx/paperless-ngx}"
|
||||||
|
echo "Copying ${tag} to ${dockerhub_tag}"
|
||||||
|
docker buildx imagetools create --tag "${dockerhub_tag}" "${tag}"
|
||||||
|
done
|
||||||
|
- name: Copy to Quay.io
|
||||||
|
if: needs.build-arch.outputs.push-external == 'true'
|
||||||
|
env:
|
||||||
|
TAGS: ${{ steps.docker-meta.outputs.tags }}
|
||||||
|
GHCR_REPO: ${{ env.REGISTRY }}/${{ needs.build-arch.outputs.repository }}
|
||||||
|
run: |
|
||||||
|
for tag in ${TAGS}; do
|
||||||
|
quay_tag="${tag/${GHCR_REPO}/quay.io/paperlessngx/paperless-ngx}"
|
||||||
|
echo "Copying ${tag} to ${quay_tag}"
|
||||||
|
docker buildx imagetools create --tag "${quay_tag}" "${tag}"
|
||||||
|
done
|
||||||
|
|||||||
Reference in New Issue
Block a user