mirror of
https://github.com/Cockatrice/Cockatrice.git
synced 2026-11-05 09:33:25 -08:00
Add a workflow_dispatch trigger that builds an existing release tag with the current workflow and publishes it to GHCR under that tag name (optionally also as latest). This allows republishing a release whose image failed to publish, since re-running the original run reuses the workflow file from the release tag. Dispatched runs check out the given tag, publish like stable releases, and use their own concurrency group so pushes to master can't cancel them. Co-authored-by: Michael Hogg <3495076+jedinerd@users.noreply.github.com>
197 lines
7 KiB
YAML
197 lines
7 KiB
YAML
name: Build Docker
|
|
|
|
permissions:
|
|
contents: read # needed to checkout repo
|
|
packages: write # needed for interacting with GHCR
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- master
|
|
pull_request:
|
|
branches:
|
|
- master
|
|
paths:
|
|
- '.github/workflows/docker-release.yml'
|
|
- '.dockerignore'
|
|
- 'Dockerfile'
|
|
- 'docker-compose.yml'
|
|
- 'docker-compose.yml.windows'
|
|
release:
|
|
types:
|
|
- released # publishing of stable releases
|
|
workflow_dispatch: # (re)publish the image for an existing stable release
|
|
inputs:
|
|
tag:
|
|
description: 'Existing release tag to build and publish (e.g. 2026-10-03-Release-3.1.0)'
|
|
required: true
|
|
type: string
|
|
latest:
|
|
description: 'Also update the "latest" tag'
|
|
required: true
|
|
type: boolean
|
|
default: true
|
|
|
|
# Cancel earlier, unfinished runs of this workflow on the same branch (unless publishing)
|
|
concurrency:
|
|
group: "${{ github.workflow }} @ ${{ inputs.tag || github.ref_name }}"
|
|
cancel-in-progress: ${{ github.event_name != 'release' && github.event_name != 'workflow_dispatch' }}
|
|
|
|
env:
|
|
GHCR_IMAGE: ghcr.io/cockatrice/servatrice
|
|
OCI_DESCRIPTION: Server for Cockatrice, a cross-platform virtual tabletop for multiplayer card games
|
|
OCI_TITLE: Servatrice
|
|
OCI_URL: https://cockatrice.github.io/
|
|
|
|
jobs:
|
|
# Create one platform-specific image and publish its OCI image manifest per matrix job
|
|
build:
|
|
name: "Servatrice (${{ matrix.label }})"
|
|
if: github.repository_owner == 'Cockatrice'
|
|
runs-on: ${{ matrix.runner }}
|
|
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
include:
|
|
- label: x86
|
|
platform: linux/amd64
|
|
runner: ubuntu-latest # https://github.com/actions/runner-images
|
|
|
|
- label: arm
|
|
platform: linux/arm64
|
|
runner: ubuntu-24.04-arm # https://github.com/actions/runner-images/blob/main/images/ubuntu/Ubuntu2404-Arm64-Readme.md, replace with "ubuntu-latest-arm" once available
|
|
|
|
env:
|
|
CACHE_SCOPE: servatrice-${{ matrix.label }}
|
|
|
|
steps:
|
|
- name: "Checkout"
|
|
uses: actions/checkout@v7
|
|
with:
|
|
ref: ${{ case(github.event_name == 'workflow_dispatch', format('refs/tags/{0}', inputs.tag), '') }}
|
|
|
|
- name: "Set up Docker buildx"
|
|
uses: docker/setup-buildx-action@v4
|
|
|
|
- name: "Login to GitHub Container Registry (GHCR)"
|
|
if: (github.event_name == 'release' && github.event.release.prerelease == false) || github.event_name == 'workflow_dispatch'
|
|
id: login
|
|
uses: docker/login-action@v4
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.actor }}
|
|
password: ${{ github.token }}
|
|
|
|
# Don't push for non-publishing triggers
|
|
- name: "Build image"
|
|
if: steps.login.outcome != 'success'
|
|
uses: docker/build-push-action@v7
|
|
with:
|
|
cache-from: type=gha,scope=${{ env.CACHE_SCOPE }}
|
|
cache-to: ${{ case(github.ref == 'refs/heads/master', format('type=gha,mode=max,scope={0}', env.CACHE_SCOPE), '') }}
|
|
context: .
|
|
platforms: ${{ matrix.platform }}
|
|
push: false
|
|
|
|
# Add OCI labels and push single-platform image by digest (without tags)
|
|
- name: "Build image and push by digest"
|
|
if: steps.login.outcome == 'success'
|
|
id: build
|
|
uses: docker/build-push-action@v7
|
|
with:
|
|
cache-from: type=gha,scope=${{ env.CACHE_SCOPE }}
|
|
cache-to: type=gha,mode=max,scope=${{ env.CACHE_SCOPE }}
|
|
context: .
|
|
labels: |
|
|
org.opencontainers.image.description=${{ env.OCI_DESCRIPTION }}
|
|
org.opencontainers.image.title=${{ env.OCI_TITLE }}
|
|
org.opencontainers.image.url=${{ env.OCI_URL }}
|
|
outputs: type=image,name=${{ env.GHCR_IMAGE }},name-canonical=true,push=true,push-by-digest=true
|
|
platforms: ${{ matrix.platform }}
|
|
provenance: mode=max # Do not pass secrets as build arguments with this option
|
|
sbom: true
|
|
|
|
- name: "Export digest"
|
|
if: steps.login.outcome == 'success'
|
|
env:
|
|
DIGEST: ${{ steps.build.outputs.digest }}
|
|
run: |
|
|
mkdir -p "$RUNNER_TEMP/digests"
|
|
touch "$RUNNER_TEMP/digests/${DIGEST#sha256:}"
|
|
|
|
- name: "Upload digest"
|
|
if: steps.login.outcome == 'success'
|
|
uses: actions/upload-artifact@v7
|
|
with:
|
|
if-no-files-found: error
|
|
name: digest-${{ matrix.label }}
|
|
path: ${{ runner.temp }}/digests/*
|
|
retention-days: 1
|
|
|
|
|
|
# Create an OCI image index from the platform-specific image manifests
|
|
index:
|
|
name: "Publish multi-platform Servatrice image"
|
|
if: github.repository_owner == 'Cockatrice' && ((github.event_name == 'release' && github.event.release.prerelease == false) || github.event_name == 'workflow_dispatch')
|
|
needs: build
|
|
runs-on: ubuntu-slim # https://github.com/actions/runner-images/blob/main/images/ubuntu-slim/ubuntu-slim-Readme.md
|
|
|
|
steps:
|
|
- name: "Download digests"
|
|
uses: actions/download-artifact@v8
|
|
with:
|
|
path: ${{ runner.temp }}/digests
|
|
pattern: digest-*
|
|
merge-multiple: true
|
|
|
|
- name: "Login to GitHub Container Registry (GHCR)"
|
|
uses: docker/login-action@v4
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.actor }}
|
|
password: ${{ github.token }}
|
|
|
|
- name: "Docker metadata"
|
|
id: metadata
|
|
uses: docker/metadata-action@v6
|
|
with:
|
|
images: ${{ env.GHCR_IMAGE }}
|
|
flavor: |
|
|
latest=auto
|
|
# if semver, also: type=semver,pattern={{version}} / {{major}}.{{minor}}
|
|
tags: |
|
|
type=ref,event=tag
|
|
type=raw,value=${{ inputs.tag }},enable=${{ github.event_name == 'workflow_dispatch' }}
|
|
type=raw,value=latest,enable=${{ github.event_name == 'workflow_dispatch' && inputs.latest }}
|
|
|
|
# Add OCI annotations to image index and publish tags
|
|
- name: "Create image index"
|
|
env:
|
|
DOCKER_TAGS: ${{ steps.metadata.outputs.tags }}
|
|
working-directory: ${{ runner.temp }}/digests
|
|
run: |
|
|
TAG_ARGS=()
|
|
while IFS= read -r tag; do
|
|
TAG_ARGS+=(--tag "$tag")
|
|
done <<< "$DOCKER_TAGS"
|
|
|
|
DIGEST_ARGS=()
|
|
for digest in *; do
|
|
DIGEST_ARGS+=("$GHCR_IMAGE@sha256:$digest")
|
|
done
|
|
|
|
docker buildx imagetools create \
|
|
--prefer-index=true \
|
|
--annotation "index:org.opencontainers.image.description=$OCI_DESCRIPTION" \
|
|
--annotation "index:org.opencontainers.image.title=$OCI_TITLE" \
|
|
--annotation "index:org.opencontainers.image.url=$OCI_URL" \
|
|
"${TAG_ARGS[@]}" \
|
|
"${DIGEST_ARGS[@]}"
|
|
|
|
- name: "Inspect images"
|
|
env:
|
|
GITHUB_TAG: ${{ inputs.tag || github.ref_name }}
|
|
run: |
|
|
docker buildx imagetools inspect "$GHCR_IMAGE:latest"
|
|
docker buildx imagetools inspect "$GHCR_IMAGE:$GITHUB_TAG"
|