feat: import Chinese-localized Buzz source snapshot
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
Signed-off-by: cls_宁波本机 <908705107@qq.com>
This commit is contained in:
@@ -0,0 +1,495 @@
|
||||
name: Docker image
|
||||
|
||||
# Builds and publishes the public Buzz relay images as ghcr.io/block/buzz.
|
||||
# Normal tags contain stripped binaries; matching debug-* tags contain the same
|
||||
# optimized binaries with line-table debug information for native profilers.
|
||||
#
|
||||
# Strategy: each architecture builds on its native runner (ubuntu-24.04 for
|
||||
# amd64, ubuntu-24.04-arm for arm64), pushes to GHCR by digest, then a final
|
||||
# job stitches the per-arch digests into a single multi-arch manifest.
|
||||
# This avoids QEMU emulation (~10× slower for Rust) at zero cost on free
|
||||
# GitHub-hosted runners.
|
||||
#
|
||||
# Versioning: the relay is versioned independently of the desktop app via
|
||||
# its own `relay-v*` tags (see `just release-relay`). Desktop `v*` tags and
|
||||
# agent `sprig-v*` tags do NOT publish this image — only `relay-v*` does, so
|
||||
# the relay image version tracks crates/buzz-relay/Cargo.toml, never desktop.
|
||||
#
|
||||
# Triggers:
|
||||
# - push to main → :main + :sha-<7>
|
||||
# + :debug-main + :debug-sha-<7>
|
||||
# - push tags relay-v*.*.* → :{version} + :{major}.{minor} + :{major}
|
||||
# + matching :debug-* tags
|
||||
# (+ :latest/:debug-latest for stable releases)
|
||||
# - pull_request → build only (no push), cache stays warm
|
||||
# - workflow_dispatch → manual relay-tag rescue at the tag itself
|
||||
#
|
||||
# Why workflow_dispatch carries a version input:
|
||||
# Normal releases arrive through the push:tags trigger above. The input is
|
||||
# retained only for an operator to rerun publication manually at an immutable
|
||||
# relay tag. The workflow rejects a dispatch whose github.ref, checked-out
|
||||
# HEAD, and relay-v tag do not resolve to one commit.
|
||||
# On the rescue path inputs.version is already bare (e.g. 0.3.0), so the
|
||||
# match=^relay-v(.*)$ regex simply no-ops (it warns, leaving the value
|
||||
# intact) and the bare version flows straight to the semver parser. On a
|
||||
# real push event value= is empty and the match strips relay-v from the ref.
|
||||
#
|
||||
# The :latest tag tracks the latest STABLE relay release: metadata-action's
|
||||
# `flavor.latest=auto` (its default) emits :latest only for non-prerelease
|
||||
# semver, so relay-v0.3.0-rc.1 publishes :0.3.0-rc.1 without moving :latest,
|
||||
# and main pushes (no semver tag) never produce :latest.
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
tags: ["relay-v[0-9]*"]
|
||||
pull_request:
|
||||
paths:
|
||||
- "Dockerfile"
|
||||
- "Dockerfile.push-gateway"
|
||||
- ".dockerignore"
|
||||
- ".github/workflows/docker.yml"
|
||||
- "Cargo.toml"
|
||||
- "Cargo.lock"
|
||||
- "rust-toolchain.toml"
|
||||
- "crates/**"
|
||||
- "web/**"
|
||||
- "package.json"
|
||||
- "pnpm-lock.yaml"
|
||||
- "pnpm-workspace.yaml"
|
||||
- "patches/**"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
description: "Semver version e.g. 0.3.0 (no relay-v prefix) — for relay-tag rescue dispatch"
|
||||
required: true
|
||||
|
||||
# One image build per ref; cancel superseded PR builds, but never cancel
|
||||
# tag/main builds (publishing must not be aborted mid-flight).
|
||||
concurrency:
|
||||
group: docker-${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: ${{ github.ref_type == 'branch' && github.event_name == 'pull_request' }}
|
||||
|
||||
permissions: {}
|
||||
|
||||
env:
|
||||
# Single source of truth for the image name. Set GHCR_IMAGE as a repo
|
||||
# variable to override (e.g., for forks that want to push to their own
|
||||
# namespace without forking this file).
|
||||
IMAGE_NAME: ${{ vars.GHCR_IMAGE != '' && vars.GHCR_IMAGE || 'ghcr.io/block/buzz' }}
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Build (${{ matrix.platform }})
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 60
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write # push to GHCR
|
||||
id-token: write # OIDC for build provenance attestation
|
||||
attestations: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-24.04
|
||||
arch: amd64
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
arch: arm64
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
|
||||
- name: Verify tag-bound release source
|
||||
if: github.ref_type == 'tag' || github.event_name == 'workflow_dispatch'
|
||||
env:
|
||||
INPUT_VERSION: ${{ inputs.version }}
|
||||
run: |
|
||||
VERSION="${INPUT_VERSION:-${GITHUB_REF_NAME#relay-v}}"
|
||||
scripts/verify-release-ref.sh relay-v "$VERSION"
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
||||
with:
|
||||
# Default parallelism of 4 OOMs the 7GB GitHub runner during Rust
|
||||
# compiles (see moby/buildkit#3969). Vaultwarden hit this; we will
|
||||
# too without the cap.
|
||||
buildkitd-config-inline: |
|
||||
[worker.oci]
|
||||
max-parallelism = 2
|
||||
|
||||
- name: Log in to GHCR
|
||||
# Skip on pull_request from forks — no GHCR creds, build-only.
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
|
||||
with:
|
||||
images: ${{ env.IMAGE_NAME }}
|
||||
# Tag matrix — every main commit gets sha-<7>, relay releases get the
|
||||
# full semver family. The semver entries carry match=^relay-v(.*)$
|
||||
# because metadata-action does NOT strip a `relay-v` prefix on its
|
||||
# own — it only strips refs/tags/, then runs the raw ref through
|
||||
# semver.valid(), which rejects "relay-v0.3.0". The match capture
|
||||
# group feeds the bare version to the semver parser. value= supplies
|
||||
# the version on a manual rescue dispatch (github.ref is `main`
|
||||
# there, not the tag): it is already bare, so match no-ops (warns,
|
||||
# value intact) and the bare version validates as-is. On push value=
|
||||
# is empty, so the ref drives it and match strips relay-v — push
|
||||
# behavior is unchanged. Pull requests get nothing (push: false
|
||||
# below). :latest is intentionally absent — flavor.latest defaults to
|
||||
# `auto`, which adds :latest for stable semver tags only (not
|
||||
# prereleases, not main pushes).
|
||||
tags: |
|
||||
type=ref,event=branch,enable=${{ github.event_name != 'workflow_dispatch' || inputs.version == '' }}
|
||||
type=sha,prefix=sha-,format=short,enable=${{ github.event_name != 'workflow_dispatch' || inputs.version == '' }}
|
||||
type=semver,pattern={{version}},match=^relay-v(.*)$,value=${{ inputs.version }}
|
||||
type=semver,pattern={{major}}.{{minor}},match=^relay-v(.*)$,value=${{ inputs.version }}
|
||||
type=semver,pattern={{major}},match=^relay-v(.*)$,value=${{ inputs.version }}
|
||||
labels: |
|
||||
org.opencontainers.image.title=Buzz
|
||||
org.opencontainers.image.description=WebSocket relay server for the Buzz communications platform
|
||||
org.opencontainers.image.licenses=Apache-2.0
|
||||
|
||||
- name: Build and push release image by digest
|
||||
id: build-release
|
||||
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
target: runtime
|
||||
platforms: ${{ matrix.platform }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
# Push by digest, not by tag — the merge job assembles the tags
|
||||
# into one multi-arch manifest. This is what makes the native-arm
|
||||
# matrix possible.
|
||||
outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }}
|
||||
cache-from: |
|
||||
type=registry,ref=${{ env.IMAGE_NAME }}-buildcache:${{ matrix.arch }}
|
||||
cache-to: |
|
||||
${{ (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && format('type=registry,ref={0}-buildcache:{1},mode=max,compression=zstd', env.IMAGE_NAME, matrix.arch) || '' }}
|
||||
|
||||
- name: Build and push debug image by digest
|
||||
id: build-debug
|
||||
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
target: runtime-debug
|
||||
platforms: ${{ matrix.platform }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
outputs: type=image,name=${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }}
|
||||
cache-from: |
|
||||
type=registry,ref=${{ env.IMAGE_NAME }}-buildcache:${{ matrix.arch }}
|
||||
|
||||
- name: Export release and debug digests
|
||||
if: github.event_name != 'pull_request'
|
||||
env:
|
||||
RELEASE_DIGEST: ${{ steps.build-release.outputs.digest }}
|
||||
DEBUG_DIGEST: ${{ steps.build-debug.outputs.digest }}
|
||||
run: |
|
||||
mkdir -p /tmp/digests-release /tmp/digests-debug
|
||||
touch "/tmp/digests-release/${RELEASE_DIGEST#sha256:}"
|
||||
touch "/tmp/digests-debug/${DEBUG_DIGEST#sha256:}"
|
||||
|
||||
- name: Upload release digest
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: digests-release-${{ matrix.arch }}
|
||||
path: /tmp/digests-release/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
- name: Upload debug digest
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: digests-debug-${{ matrix.arch }}
|
||||
path: /tmp/digests-debug/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
merge:
|
||||
name: Merge ${{ matrix.variant }} multi-arch manifest
|
||||
if: github.event_name != 'pull_request'
|
||||
runs-on: ubuntu-24.04
|
||||
needs: build
|
||||
timeout-minutes: 15
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write # push the merged manifest
|
||||
id-token: write # OIDC for provenance attestation on the manifest
|
||||
attestations: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- variant: release
|
||||
tag_prefix: ""
|
||||
- variant: debug
|
||||
tag_prefix: debug-
|
||||
|
||||
steps:
|
||||
- name: Download all per-arch digests
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: /tmp/digests
|
||||
pattern: digests-${{ matrix.variant }}-*
|
||||
merge-multiple: true
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
||||
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
|
||||
with:
|
||||
images: ${{ env.IMAGE_NAME }}
|
||||
# Must mirror the build job's tag matrix exactly — the merge job
|
||||
# re-derives tags to stamp them onto the multi-arch manifest. See
|
||||
# the build job's `meta` step for why match=^relay-v(.*)$, why
|
||||
# value=${{ inputs.version }} carries the rescue-dispatch version,
|
||||
# and why :latest is left to flavor.latest=auto.
|
||||
flavor: |
|
||||
latest=auto
|
||||
prefix=${{ matrix.tag_prefix }},onlatest=true
|
||||
tags: |
|
||||
type=ref,event=branch,enable=${{ github.event_name != 'workflow_dispatch' || inputs.version == '' }}
|
||||
type=sha,prefix=${{ matrix.tag_prefix }}sha-,format=short,enable=${{ github.event_name != 'workflow_dispatch' || inputs.version == '' }}
|
||||
type=semver,pattern={{version}},match=^relay-v(.*)$,value=${{ inputs.version }}
|
||||
type=semver,pattern={{major}}.{{minor}},match=^relay-v(.*)$,value=${{ inputs.version }}
|
||||
type=semver,pattern={{major}},match=^relay-v(.*)$,value=${{ inputs.version }}
|
||||
|
||||
- name: Create and push manifest list
|
||||
id: manifest
|
||||
working-directory: /tmp/digests
|
||||
env:
|
||||
IMAGE_NAME: ${{ env.IMAGE_NAME }}
|
||||
META_TAGS: ${{ steps.meta.outputs.tags }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
# Build -t flags from the metadata-action output.
|
||||
tags=()
|
||||
while IFS= read -r tag; do
|
||||
[ -n "$tag" ] && tags+=("-t" "$tag")
|
||||
done <<< "$META_TAGS"
|
||||
|
||||
# Build the digest refs from the per-arch artifacts.
|
||||
digests=()
|
||||
for digest in *; do
|
||||
digests+=("${IMAGE_NAME}@sha256:${digest}")
|
||||
done
|
||||
|
||||
docker buildx imagetools create "${tags[@]}" "${digests[@]}"
|
||||
|
||||
# Capture the merged manifest digest for the attestation step.
|
||||
first_tag=$(echo "$META_TAGS" | head -n1)
|
||||
merged_digest=$(docker buildx imagetools inspect "$first_tag" \
|
||||
--format '{{json .Manifest}}' | jq -r '.digest')
|
||||
echo "digest=${merged_digest}" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Attest provenance for the merged image
|
||||
# Sigstore-signed in-toto attestation, verifiable with:
|
||||
# gh attestation verify oci://ghcr.io/block/buzz:<tag> --owner block
|
||||
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
|
||||
with:
|
||||
subject-name: ${{ env.IMAGE_NAME }}
|
||||
subject-digest: ${{ steps.manifest.outputs.digest }}
|
||||
push-to-registry: true
|
||||
|
||||
- name: Summary
|
||||
env:
|
||||
IMAGE_NAME: ${{ env.IMAGE_NAME }}
|
||||
VARIANT: ${{ matrix.variant }}
|
||||
MERGED_DIGEST: ${{ steps.manifest.outputs.digest }}
|
||||
META_TAGS: ${{ steps.meta.outputs.tags }}
|
||||
run: |
|
||||
{
|
||||
echo "### Published \`${IMAGE_NAME}\` (${VARIANT})"
|
||||
echo
|
||||
echo "**Digest:** \`${MERGED_DIGEST}\`"
|
||||
echo
|
||||
echo "**Tags:**"
|
||||
echo '```'
|
||||
echo "${META_TAGS}"
|
||||
echo '```'
|
||||
echo
|
||||
echo "Verify provenance:"
|
||||
echo '```'
|
||||
echo "gh attestation verify oci://${IMAGE_NAME}@${MERGED_DIGEST} --owner block"
|
||||
echo '```'
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
push-gateway-build:
|
||||
name: Build public push gateway (${{ matrix.platform }})
|
||||
runs-on: ${{ matrix.runner }}
|
||||
timeout-minutes: 60
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- platform: linux/amd64
|
||||
runner: ubuntu-24.04
|
||||
arch: amd64
|
||||
- platform: linux/arm64
|
||||
runner: ubuntu-24.04-arm
|
||||
arch: arm64
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
persist-credentials: false
|
||||
- name: Verify tag-bound release source
|
||||
if: github.ref_type == 'tag' || github.event_name == 'workflow_dispatch'
|
||||
env:
|
||||
INPUT_VERSION: ${{ inputs.version }}
|
||||
run: |
|
||||
VERSION="${INPUT_VERSION:-${GITHUB_REF_NAME#relay-v}}"
|
||||
scripts/verify-release-ref.sh relay-v "$VERSION"
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
||||
with:
|
||||
buildkitd-config-inline: |
|
||||
[worker.oci]
|
||||
max-parallelism = 2
|
||||
- name: Log in to GHCR
|
||||
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
|
||||
with:
|
||||
images: ghcr.io/block/buzz-push-gateway
|
||||
labels: |
|
||||
org.opencontainers.image.title=Buzz Push Gateway
|
||||
org.opencontainers.image.description=Capability-gated APNs last hop for Buzz
|
||||
org.opencontainers.image.licenses=Apache-2.0
|
||||
- name: Build and push by digest
|
||||
id: build
|
||||
uses: docker/build-push-action@f9f3042f7e2789586610d6e8b85c8f03e5195baf # v7.2.0
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile.push-gateway
|
||||
platforms: ${{ matrix.platform }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
outputs: type=image,name=ghcr.io/block/buzz-push-gateway,push-by-digest=true,name-canonical=true,push=${{ github.event_name != 'pull_request' }}
|
||||
cache-from: type=registry,ref=ghcr.io/block/buzz-push-gateway-buildcache:${{ matrix.arch }}
|
||||
cache-to: ${{ (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) && format('type=registry,ref=ghcr.io/block/buzz-push-gateway-buildcache:{0},mode=max,compression=zstd', matrix.arch) || '' }}
|
||||
- name: Export digest
|
||||
if: github.event_name != 'pull_request'
|
||||
env:
|
||||
DIGEST: ${{ steps.build.outputs.digest }}
|
||||
run: mkdir -p /tmp/gateway-digests && touch "/tmp/gateway-digests/${DIGEST#sha256:}"
|
||||
- name: Upload digest
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
|
||||
with:
|
||||
name: gateway-digests-${{ matrix.arch }}
|
||||
path: /tmp/gateway-digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
|
||||
push-gateway-merge:
|
||||
name: Publish public push gateway image
|
||||
if: github.event_name != 'pull_request'
|
||||
runs-on: ubuntu-24.04
|
||||
needs: push-gateway-build
|
||||
timeout-minutes: 15
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
id-token: write
|
||||
attestations: write
|
||||
steps:
|
||||
- name: Download per-arch digests
|
||||
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
|
||||
with:
|
||||
path: /tmp/gateway-digests
|
||||
pattern: gateway-digests-*
|
||||
merge-multiple: true
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4.1.0
|
||||
- name: Log in to GHCR
|
||||
uses: docker/login-action@650006c6eb7dba73a995cc03b0b2d7f5ca915bee # v4.2.0
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Extract metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@80c7e94dd9b9319bd5eb7a0e0fe9291e23a2a2e9 # v6.1.0
|
||||
with:
|
||||
images: ghcr.io/block/buzz-push-gateway
|
||||
tags: |
|
||||
type=ref,event=branch,enable=${{ github.event_name != 'workflow_dispatch' || inputs.version == '' }}
|
||||
type=sha,prefix=sha-,format=short,enable=${{ github.event_name != 'workflow_dispatch' || inputs.version == '' }}
|
||||
type=semver,pattern={{version}},match=^relay-v(.*)$,value=${{ inputs.version }}
|
||||
type=semver,pattern={{major}}.{{minor}},match=^relay-v(.*)$,value=${{ inputs.version }}
|
||||
- name: Merge and publish manifest
|
||||
id: manifest
|
||||
working-directory: /tmp/gateway-digests
|
||||
env:
|
||||
META_TAGS: ${{ steps.meta.outputs.tags }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
tags=(); while IFS= read -r tag; do [ -n "$tag" ] && tags+=("-t" "$tag"); done <<< "$META_TAGS"
|
||||
digests=(); for digest in *; do digests+=("ghcr.io/block/buzz-push-gateway@sha256:${digest}"); done
|
||||
docker buildx imagetools create "${tags[@]}" "${digests[@]}"
|
||||
first_tag=$(echo "$META_TAGS" | head -n1)
|
||||
digest=$(docker buildx imagetools inspect "$first_tag" --format '{{json .Manifest}}' | jq -r '.digest')
|
||||
echo "digest=${digest}" >> "$GITHUB_OUTPUT"
|
||||
- name: Attest gateway image provenance
|
||||
uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
|
||||
with:
|
||||
subject-name: ghcr.io/block/buzz-push-gateway
|
||||
subject-digest: ${{ steps.manifest.outputs.digest }}
|
||||
push-to-registry: true
|
||||
- name: Gateway publication summary
|
||||
env:
|
||||
GATEWAY_DIGEST: ${{ steps.manifest.outputs.digest }}
|
||||
GATEWAY_TAGS: ${{ steps.meta.outputs.tags }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
{
|
||||
echo "### Published \`ghcr.io/block/buzz-push-gateway\`"
|
||||
echo
|
||||
printf "**Digest:** \`%s\`\n" "$GATEWAY_DIGEST"
|
||||
echo
|
||||
echo '**Tags:**'
|
||||
echo "\`\`\`"
|
||||
printf '%s\n' "$GATEWAY_TAGS"
|
||||
echo "\`\`\`"
|
||||
echo
|
||||
echo 'Verify provenance before deployment:'
|
||||
echo "\`\`\`"
|
||||
printf 'gh attestation verify oci://ghcr.io/block/buzz-push-gateway@%s --owner block\n' "$GATEWAY_DIGEST"
|
||||
echo "\`\`\`"
|
||||
} >> "$GITHUB_STEP_SUMMARY"
|
||||
Reference in New Issue
Block a user