Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 47 additions & 3 deletions .github/workflows/docker-build-workflow.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# Registry names must be lowercase, and the repository owner is not guaranteed to be.
- name: Resolve image name
env:
IMAGE_NAME: ${{ matrix.image_name }}
run: printf 'GHCR_IMAGE=ghcr.io/%s/%s\n' "${GITHUB_REPOSITORY_OWNER,,}" "$IMAGE_NAME" >> "$GITHUB_ENV"

# Build and push Docker images for each target
- name: Build and push Docker images
uses: docker/build-push-action@v5
Expand All @@ -53,7 +59,45 @@ jobs:
file: ${{ matrix.file }}
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:${{ github.sha }}
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:${{ inputs.tag }}
${{ env.GHCR_IMAGE }}:${{ github.sha }}
${{ env.GHCR_IMAGE }}:${{ inputs.tag }}
platforms: linux/amd64,linux/arm64
target: ${{ matrix.target }}
target: ${{ matrix.target }}

# After the repository moves to another owner, deployments still pull the old
# GHCR namespace. Copying each published tag there keeps them updating until the
# deprecation window closes. Copies are cross-repo blob mounts within GHCR, so no
# image data is rebuilt or re-uploaded.
#
# Set the LEGACY_GHCR_OWNER variable and the LEGACY_GHCR_TOKEN secret (a token with
# write:packages for that owner) to turn this on. It stays off when either is unset,
# and while the owner still matches the one publishing the images.
- name: Mirror tags to the legacy namespace
if: ${{ vars.LEGACY_GHCR_OWNER != '' }}
continue-on-error: true
env:
LEGACY_OWNER: ${{ vars.LEGACY_GHCR_OWNER }}
LEGACY_TOKEN: ${{ secrets.LEGACY_GHCR_TOKEN }}
TAGS: "${{ github.sha }} ${{ inputs.tag }}"
run: |
set -euo pipefail

legacy_owner="${LEGACY_OWNER,,}"
if [ "$legacy_owner" = "${GITHUB_REPOSITORY_OWNER,,}" ]; then
echo "Legacy owner matches the current owner; nothing to mirror."
exit 0
fi
if [ -z "$LEGACY_TOKEN" ]; then
echo "::warning::LEGACY_GHCR_OWNER is set but LEGACY_GHCR_TOKEN is not; skipping the mirror."
exit 0
fi

# The pull side needs this login too: it replaces the GITHUB_TOKEN credential
# for ghcr.io, and both namespaces are read with it.
echo "$LEGACY_TOKEN" | docker login ghcr.io -u "$legacy_owner" --password-stdin

legacy_image="ghcr.io/${legacy_owner}/${GHCR_IMAGE##*/}"
for tag in $TAGS; do
echo "Mirroring ${GHCR_IMAGE}:${tag} -> ${legacy_image}:${tag}"
docker buildx imagetools create -t "${legacy_image}:${tag}" "${GHCR_IMAGE}:${tag}"
done
48 changes: 46 additions & 2 deletions .github/workflows/images.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

# Registry names must be lowercase, and the repository owner is not guaranteed to be.
- name: Resolve image name
env:
IMAGE_NAME: ${{ matrix.image_name }}
run: printf 'GHCR_IMAGE=ghcr.io/%s/%s\n' "${GITHUB_REPOSITORY_OWNER,,}" "$IMAGE_NAME" >> "$GITHUB_ENV"

# Build and push Docker images for each target
- name: Build and push Docker images
uses: docker/build-push-action@v5
Expand All @@ -65,9 +71,47 @@ jobs:
file: ${{ matrix.file }}
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:${{ github.sha }}
ghcr.io/${{ github.repository_owner }}/${{ matrix.image_name }}:latest
${{ env.GHCR_IMAGE }}:${{ github.sha }}
${{ env.GHCR_IMAGE }}:latest
platforms: linux/amd64,linux/arm64
target: ${{ matrix.target }}
cache-from: type=gha
cache-to: type=gha,mode=max

# After the repository moves to another owner, deployments still pull the old
# GHCR namespace. Copying each published tag there keeps them updating until the
# deprecation window closes. Copies are cross-repo blob mounts within GHCR, so no
# image data is rebuilt or re-uploaded.
#
# Set the LEGACY_GHCR_OWNER variable and the LEGACY_GHCR_TOKEN secret (a token with
# write:packages for that owner) to turn this on. It stays off when either is unset,
# and while the owner still matches the one publishing the images.
- name: Mirror tags to the legacy namespace
if: ${{ vars.LEGACY_GHCR_OWNER != '' }}
continue-on-error: true
env:
LEGACY_OWNER: ${{ vars.LEGACY_GHCR_OWNER }}
LEGACY_TOKEN: ${{ secrets.LEGACY_GHCR_TOKEN }}
TAGS: "${{ github.sha }} latest"
run: |
set -euo pipefail

legacy_owner="${LEGACY_OWNER,,}"
if [ "$legacy_owner" = "${GITHUB_REPOSITORY_OWNER,,}" ]; then
echo "Legacy owner matches the current owner; nothing to mirror."
exit 0
fi
if [ -z "$LEGACY_TOKEN" ]; then
echo "::warning::LEGACY_GHCR_OWNER is set but LEGACY_GHCR_TOKEN is not; skipping the mirror."
exit 0
fi

# The pull side needs this login too: it replaces the GITHUB_TOKEN credential
# for ghcr.io, and both namespaces are read with it.
echo "$LEGACY_TOKEN" | docker login ghcr.io -u "$legacy_owner" --password-stdin

legacy_image="ghcr.io/${legacy_owner}/${GHCR_IMAGE##*/}"
for tag in $TAGS; do
echo "Mirroring ${GHCR_IMAGE}:${tag} -> ${legacy_image}:${tag}"
docker buildx imagetools create -t "${legacy_image}:${tag}" "${GHCR_IMAGE}:${tag}"
done
3 changes: 3 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,8 @@ permissions:
jobs:
call-docker-build:
uses: ./.github/workflows/docker-build-workflow.yaml
# The mirror step reads LEGACY_GHCR_TOKEN, and a called workflow gets no
# secrets unless they are passed.
secrets: inherit
with:
tag: ${{ github.ref_name }}
Loading