name: Docker
on:
push:
branches:
- main
tags:
- '**'
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: {}
defaults:
run:
shell: bash -xeuo pipefail {0}
env:
DOCKERHUB_USERNAME: zhongruoyu
DOCKERHUB_REPOSITORY: zhongruoyu/shortener
GHCR_USERNAME: zhongruoyu
GHCR_REPOSITORY: ghcr.io/zhongruoyu/shortener
BUILD_CACHE_REPOSITORY: ghcr.io/zhongruoyu/shortener/cache
jobs:
build:
strategy:
fail-fast: false
matrix:
arch:
- x86_64
- aarch64
include:
- { arch: x86_64, runs-on: ubuntu-latest }
- { arch: aarch64, runs-on: ubuntu-24.04-arm }
runs-on: ${{ matrix.runs-on }}
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd with:
persist-credentials: false
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd - name: Login to Docker Hub
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref_type == 'tag')
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 with:
username: ${{ env.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref_type == 'tag')
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 with:
registry: ghcr.io
username: ${{ env.GHCR_USERNAME }}
password: ${{ github.token }}
- name: Set up build
id: setup
run: |
cache_from=""
cache_to=""
outputs=()
if [[ "$GITHUB_EVENT_NAME" = "push" ]]; then
if [[ "$GITHUB_REF_TYPE" = "branch" ]]; then
cache_from="type=registry,ref=$BUILD_CACHE_REPOSITORY:$ARCH"
if [[ "$GITHUB_REF" = "refs/heads/main" ]]; then
cache_to="type=registry,ref=$BUILD_CACHE_REPOSITORY:$ARCH,mode=max"
fi
fi
if [[ "$GITHUB_REF" = "refs/heads/main" || "$GITHUB_REF_TYPE" = "tag" ]]; then
outputs+=(
"type=image,name=$DOCKERHUB_REPOSITORY,name-canonical=true,push=true,push-by-digest=true"
"type=image,name=$GHCR_REPOSITORY,name-canonical=true,push=true,push-by-digest=true"
)
fi
fi
{
echo "cache_from=$cache_from"
echo "cache_to=$cache_to"
echo "outputs<<OUTPUTS"
if [[ ${#outputs[@]} -gt 0 ]]; then
printf '%s\n' "${outputs[@]}"
fi
echo "OUTPUTS"
} >> "$GITHUB_OUTPUT"
env:
ARCH: ${{ matrix.arch }}
- name: Build and push Docker image by digest
id: build
uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f with:
context: .
platforms: linux/${{ matrix.arch }}
cache-from: ${{ steps.setup.outputs.cache_from }}
cache-to: ${{ steps.setup.outputs.cache_to }}
outputs: ${{ steps.setup.outputs.outputs }}
- name: Export digest
run: |
mkdir -p "$RUNNER_TEMP"/digests
echo "${DIGEST#sha256:}" > "$RUNNER_TEMP"/digests/"$ARCH"
env:
DIGEST: ${{ steps.build.outputs.digest }}
ARCH: ${{ matrix.arch }}
- name: Upload digest
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a with:
name: digests-${{ matrix.arch }}
path: ${{ runner.temp }}/digests/*
merge:
if: github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref_type == 'tag')
needs: build
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd - name: Login to Docker Hub
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 with:
username: ${{ env.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Login to GitHub Container Registry
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 with:
registry: ghcr.io
username: ${{ env.GHCR_USERNAME }}
password: ${{ github.token }}
- name: Download digests
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c with:
path: ${{ runner.temp }}/digests
pattern: digests-*
merge-multiple: true
- name: Create manifest list and push
run: |
tags=()
case "$GITHUB_REF_TYPE" in
"branch")
tags+=(
"$DOCKERHUB_REPOSITORY:main"
"$DOCKERHUB_REPOSITORY:$GITHUB_SHA"
"$GHCR_REPOSITORY:main"
"$GHCR_REPOSITORY:$GITHUB_SHA"
)
;;
"tag")
tags+=(
"$DOCKERHUB_REPOSITORY:latest"
"$DOCKERHUB_REPOSITORY:$GITHUB_REF_NAME"
"$GHCR_REPOSITORY:latest"
"$GHCR_REPOSITORY:$GITHUB_REF_NAME"
)
;;
esac
tag_args=()
for tag in "${tags[@]}"; do
tag_args+=(--tag="$tag")
done
images=(
"$GHCR_REPOSITORY@sha256:$(cat "$RUNNER_TEMP"/digests/x86_64)"
"$GHCR_REPOSITORY@sha256:$(cat "$RUNNER_TEMP"/digests/aarch64)"
)
docker buildx imagetools create "${tag_args[@]}" "${images[@]}"