Files
BYW-VoiceHub/.github/workflows/docker-build.yml
T

223 lines
8.7 KiB
YAML

name: Build and Push Docker Image
on:
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch:
inputs:
reason:
description: 'Reason for manual trigger'
required: false
default: 'Manual trigger'
env:
REGISTRY: ghcr.io
jobs:
# 阶段1:优先构建并推送 amd64 架构,立即可用
build-amd64:
if: github.repository == 'laoshuikaixue/VoiceHub' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: '0'
- name: Prepare lowercase names
id: names
run: |
echo "image-name=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
echo "actor-name=$(echo '${{ github.actor }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
- name: Extract version from package.json
id: extract-version
run: |
FULL_VERSION=$(node -p "require('./package.json').version")
MAJOR_MINOR_VERSION=$(echo "$FULL_VERSION" | sed -E 's/^([0-9]+\.[0-9]+)\.[0-9]+$/\1/')
echo "full-version=$FULL_VERSION" >> $GITHUB_OUTPUT
echo "major-minor-version=$MAJOR_MINOR_VERSION" >> $GITHUB_OUTPUT
echo "Extracted full version: $FULL_VERSION"
echo "Extracted major.minor version: $MAJOR_MINOR_VERSION"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to the Container registry
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ steps.names.outputs.actor-name }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY }}/${{ steps.names.outputs.image-name }}
tags: |
# 正式标签 - amd64 构建完成后立即可用
type=raw,value=latest,enable={{is_default_branch}}
type=ref,event=branch
type=ref,event=pr
type=raw,value=${{ steps.extract-version.outputs.full-version }}
type=raw,value=${{ steps.extract-version.outputs.major-minor-version }}
# 架构后缀标签 - 用于后续多架构合并
type=raw,value=latest-amd64,enable={{is_default_branch}}
type=raw,value=${{ steps.extract-version.outputs.full-version }}-amd64
type=raw,value=${{ steps.extract-version.outputs.major-minor-version }}-amd64
- name: Build and push amd64 image
uses: docker/build-push-action@v7
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64
cache-from: type=gha,scope=amd64
cache-to: type=gha,mode=max,scope=amd64
# 阶段2:并行构建其余架构,各自推送带后缀的独立标签
build-other-arches:
if: github.repository == 'laoshuikaixue/VoiceHub' || github.event_name == 'workflow_dispatch'
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
strategy:
matrix:
arch:
- { platform: linux/arm64, suffix: -arm64 }
- { platform: linux/arm/v7, suffix: -armv7 }
- { platform: linux/arm/v6, suffix: -armv6 }
- { platform: linux/ppc64le, suffix: -ppc64le }
- { platform: linux/s390x, suffix: -s390x }
fail-fast: false
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: '0'
- name: Prepare lowercase names
id: names
run: |
echo "image-name=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
echo "actor-name=$(echo '${{ github.actor }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
- name: Extract version from package.json
id: extract-version
run: |
FULL_VERSION=$(node -p "require('./package.json').version")
MAJOR_MINOR_VERSION=$(echo "$FULL_VERSION" | sed -E 's/^([0-9]+\.[0-9]+)\.[0-9]+$/\1/')
echo "full-version=$FULL_VERSION" >> $GITHUB_OUTPUT
echo "major-minor-version=$MAJOR_MINOR_VERSION" >> $GITHUB_OUTPUT
- name: Set up QEMU
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to the Container registry
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ steps.names.outputs.actor-name }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v6
with:
images: ${{ env.REGISTRY }}/${{ steps.names.outputs.image-name }}
tags: |
type=raw,value=latest${{ matrix.arch.suffix }},enable={{is_default_branch}}
type=raw,value=${{ steps.extract-version.outputs.full-version }}${{ matrix.arch.suffix }}
type=raw,value=${{ steps.extract-version.outputs.major-minor-version }}${{ matrix.arch.suffix }}
- name: Build and push ${{ matrix.arch.platform }} image
uses: docker/build-push-action@v7
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
platforms: ${{ matrix.arch.platform }}
cache-from: type=gha,scope=${{ matrix.arch.suffix }}
cache-to: type=gha,mode=max,scope=${{ matrix.arch.suffix }}
# 阶段3:所有架构构建完成后,合并为多架构 manifest 清单并推送正式标签
merge-manifests:
if: (github.repository == 'laoshuikaixue/VoiceHub' || github.event_name == 'workflow_dispatch') && github.event_name != 'pull_request'
runs-on: ubuntu-latest
needs: [build-amd64, build-other-arches]
permissions:
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v6
- name: Prepare lowercase names
id: names
run: |
echo "image-name=$(echo '${{ github.repository }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
echo "actor-name=$(echo '${{ github.actor }}' | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
- name: Extract version from package.json
id: extract-version
run: |
FULL_VERSION=$(node -p "require('./package.json').version")
MAJOR_MINOR_VERSION=$(echo "$FULL_VERSION" | sed -E 's/^([0-9]+\.[0-9]+)\.[0-9]+$/\1/')
echo "full-version=$FULL_VERSION" >> $GITHUB_OUTPUT
echo "major-minor-version=$MAJOR_MINOR_VERSION" >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
- name: Log in to the Container registry
uses: docker/login-action@v4
with:
registry: ${{ env.REGISTRY }}
username: ${{ steps.names.outputs.actor-name }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push multi-architecture manifest lists
env:
IMAGE_BASE: ${{ env.REGISTRY }}/${{ steps.names.outputs.image-name }}
FULL_VER: ${{ steps.extract-version.outputs.full-version }}
MAJOR_MINOR_VER: ${{ steps.extract-version.outputs.major-minor-version }}
run: |
# 所有架构后缀列表
ARCH_SUFFIXES=("-amd64" "-arm64" "-armv7" "-armv6" "-ppc64le" "-s390x")
# 生成指定标签的所有架构镜像参数
build_arch_args() {
local tag=$1
local args=""
for suffix in "${ARCH_SUFFIXES[@]}"; do
args="$args ${IMAGE_BASE}:${tag}${suffix}"
done
echo "$args"
}
# 合并 latest 标签(仅默认分支)
if [ "${{ github.ref == 'refs/heads/main' }}" = "true" ]; then
echo "Merging multi-arch manifest for latest tag"
docker buildx imagetools create -t "${IMAGE_BASE}:latest" $(build_arch_args "latest")
fi
# 合并完整版本号标签
echo "Merging multi-arch manifest for ${FULL_VER} tag"
docker buildx imagetools create -t "${IMAGE_BASE}:${FULL_VER}" $(build_arch_args "${FULL_VER}")
# 合并主次版本号标签
echo "Merging multi-arch manifest for ${MAJOR_MINOR_VER} tag"
docker buildx imagetools create -t "${IMAGE_BASE}:${MAJOR_MINOR_VER}" $(build_arch_args "${MAJOR_MINOR_VER}")