231 lines
8.7 KiB
YAML
231 lines
8.7 KiB
YAML
name: Build and Push Docker Images
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
inputs:
|
|
build_cuda_matrix:
|
|
description: 'Build multi-arch CUDA images (12.6.3 default; 13.0.0 explicitly tagged)'
|
|
required: false
|
|
default: true
|
|
type: boolean
|
|
build_dreamverse_matrix:
|
|
description: 'Build the amd64 Dreamverse matrix (backend + UI x CUDA 12.6.3/13.0.0)'
|
|
required: false
|
|
default: false
|
|
type: boolean
|
|
# Auto-rebuild the CUDA images when a repository-controlled image input
|
|
# changes on main. This includes the trusted SM89 kernel artifact's source,
|
|
# metadata/key helper, ABI dependency metadata, and build orchestration.
|
|
# Dreamverse (apps/dreamverse/docker/Dockerfile) and the ROCm Dockerfile stay
|
|
# manual-dispatch only.
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- '.dockerignore'
|
|
- '.github/workflows/_template-build-image.yml'
|
|
- '.github/workflows/infra-build-image.yml'
|
|
- '.gitmodules'
|
|
- 'docker/Dockerfile'
|
|
- 'docker/uv-excludes'
|
|
- 'fastvideo-kernel/**'
|
|
- 'fastvideo/tests/modal/kernel_build_cache.py'
|
|
- 'pyproject.toml'
|
|
|
|
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
|
|
# One static group, no cancellation: every run of this workflow writes the same
|
|
# mutable registry tags (latest, py3.12-latest, ...), so runs must serialize —
|
|
# concurrent push/dispatch runs would race on those tags, and cancelling a run
|
|
# mid-publish can strand the cu126/cu130 tag families at different commits. An
|
|
# in-flight superseded build wastes its runner time, but its tags are then
|
|
# overwritten by the newer queued run. GitHub keeps a single pending run per
|
|
# group: the newest queued run replaces any older queued one.
|
|
concurrency:
|
|
group: infra-build-image
|
|
cancel-in-progress: false
|
|
|
|
jobs:
|
|
# CUDA matrix: Python 3.12 x {12.6.3, 13.0.0} x {amd64, arm64}. Each architecture
|
|
# builds natively and pushes only by digest; publish-cuda-manifests is the sole
|
|
# owner of the shared tags. CUDA 12.6 arm64 targets Hopper (sm_90a / GH200 class),
|
|
# because CUDA 12.6 cannot compile sm_121. CUDA 13 arm64 targets GB10 (sm_121).
|
|
# 12.6.3/cu126 owns the default `py3.12`/`latest` tags and keeps its versioned
|
|
# aliases; 13.0.0/cu130 is published under explicit versioned tags. Flash-attn
|
|
# 2.8.3 comes from the architecture-specific prebuilt releases.
|
|
build-cuda-images:
|
|
# Runs on a manual dispatch when build_cuda_matrix is set, or automatically
|
|
# on an in-scope main push (inputs are null on push). The
|
|
# repository guard keeps fork syncs from auto-building; manual dispatch
|
|
# still works in forks.
|
|
if: ${{ (github.event_name == 'push' && github.repository == 'hao-ai-lab/FastVideo') || github.event.inputs.build_cuda_matrix == 'true' }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
cuda:
|
|
- version: '12.6.3'
|
|
suffix: '-cuda12.6.3'
|
|
torch_backend: 'cu126'
|
|
fa_tag: 'cu126torch2.12'
|
|
cmake_build_parallel_level: '4'
|
|
torch_cuda_arch_list:
|
|
amd64: '9.0a'
|
|
arm64: '9.0a'
|
|
- version: '13.0.0'
|
|
suffix: '-cuda13.0.0'
|
|
torch_backend: 'cu130'
|
|
fa_tag: 'cu130torch2.12'
|
|
cmake_build_parallel_level: '1'
|
|
torch_cuda_arch_list:
|
|
amd64: '9.0a'
|
|
arm64: '12.1'
|
|
architecture:
|
|
- name: amd64
|
|
runner: ubuntu-latest
|
|
- name: arm64
|
|
runner: ubuntu-24.04-arm
|
|
uses: ./.github/workflows/_template-build-image.yml
|
|
with:
|
|
python_version: '3.12'
|
|
dockerfile_path: docker/Dockerfile
|
|
tag_suffix: py3.12${{ matrix.cuda.suffix }}
|
|
runner: ${{ matrix.architecture.runner }}
|
|
architecture: ${{ matrix.architecture.name }}
|
|
push_by_digest: true
|
|
digest_artifact_name: fastvideo-dev-cuda${{ matrix.cuda.version }}-${{ matrix.architecture.name }}
|
|
build_args: |
|
|
PYTHON_VERSION=3.12
|
|
CUDA_VERSION=${{ matrix.cuda.version }}
|
|
UV_TORCH_BACKEND=${{ matrix.cuda.torch_backend }}
|
|
TORCH_CUDA_ARCH_LIST=${{ matrix.cuda.torch_cuda_arch_list[matrix.architecture.name] }}
|
|
CMAKE_BUILD_PARALLEL_LEVEL=${{ matrix.cuda.cmake_build_parallel_level }}
|
|
FLASH_ATTN_WHEEL_TAG=${{ matrix.cuda.fa_tag }}
|
|
FLASH_ATTN_WHEEL_RELEASE=https://github.com/mjun0812/flash-attention-prebuild-wheels/releases/download/v0.9.17
|
|
FLASH_ATTN_WHEEL_RELEASE_ARM64=https://github.com/mjun0812/flash-attention-prebuild-wheels/releases/download/v0.9.22
|
|
secrets: inherit
|
|
|
|
publish-cuda-manifests:
|
|
# !cancelled(): publish lanes whose digests exist even if a sibling build
|
|
# leg failed (the digest-count check fails incomplete lanes); it also
|
|
# bypasses skipped-needs propagation, hence the explicit skipped check.
|
|
if: ${{ !cancelled() && needs.build-cuda-images.result != 'skipped' }}
|
|
needs: build-cuda-images
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
packages: write
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
cuda:
|
|
- version: '12.6.3'
|
|
suffix: '-cuda12.6.3'
|
|
is_default: true
|
|
- version: '13.0.0'
|
|
suffix: '-cuda13.0.0'
|
|
is_default: false
|
|
steps:
|
|
- name: Download architecture digests
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
path: /tmp/digests
|
|
pattern: fastvideo-dev-cuda${{ matrix.cuda.version }}-*
|
|
merge-multiple: true
|
|
|
|
- name: Set up Docker Buildx
|
|
uses: docker/setup-buildx-action@v3
|
|
|
|
- name: Login to GitHub Container Registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: ghcr.io
|
|
username: ${{ github.repository_owner }}
|
|
password: ${{ secrets.GITHUB_TOKEN }}
|
|
|
|
- name: Normalize image reference
|
|
id: image
|
|
env:
|
|
IMAGE: ghcr.io/${{ github.repository }}/fastvideo-dev
|
|
run: echo "name=${IMAGE,,}" >> "${GITHUB_OUTPUT}"
|
|
|
|
- name: Prepare tags
|
|
id: prepare-tags
|
|
env:
|
|
VERSIONED_TAG_PREFIX: py3.12${{ matrix.cuda.suffix }}
|
|
PUBLISH_DEFAULT_TAGS: ${{ matrix.cuda.is_default }}
|
|
run: |
|
|
SHORT_SHA="${GITHUB_SHA::7}"
|
|
TAGS="type=raw,value=${VERSIONED_TAG_PREFIX}-latest\ntype=raw,value=${VERSIONED_TAG_PREFIX}-sha-${SHORT_SHA}"
|
|
if [[ "${PUBLISH_DEFAULT_TAGS}" == "true" ]]; then
|
|
TAGS="type=raw,value=latest\ntype=raw,value=py3.12-latest\ntype=raw,value=py3.12-sha-${SHORT_SHA}\n${TAGS}"
|
|
fi
|
|
{
|
|
echo "tags<<EOF"
|
|
echo -e "${TAGS}"
|
|
echo "EOF"
|
|
} >> "${GITHUB_OUTPUT}"
|
|
|
|
- name: Extract metadata for Docker
|
|
id: meta
|
|
uses: docker/metadata-action@v5
|
|
with:
|
|
images: ${{ steps.image.outputs.name }}
|
|
tags: ${{ steps.prepare-tags.outputs.tags }}
|
|
|
|
- name: Create multi-architecture manifests
|
|
env:
|
|
IMAGE: ${{ steps.image.outputs.name }}
|
|
run: |
|
|
mapfile -t DIGESTS < <(find /tmp/digests -maxdepth 1 -type f -printf '%f\n' | sort)
|
|
if [[ "${#DIGESTS[@]}" -ne 2 ]]; then
|
|
echo "Expected exactly two architecture digests, found ${#DIGESTS[@]}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
mapfile -t TAGS < <(jq -r '.tags[]' <<< "${DOCKER_METADATA_OUTPUT_JSON}")
|
|
TAG_ARGS=()
|
|
for TAG in "${TAGS[@]}"; do
|
|
TAG_ARGS+=(--tag "${TAG}")
|
|
done
|
|
|
|
IMAGE_REFS=()
|
|
for DIGEST in "${DIGESTS[@]}"; do
|
|
IMAGE_REFS+=("${IMAGE}@sha256:${DIGEST}")
|
|
done
|
|
|
|
docker buildx imagetools create "${TAG_ARGS[@]}" "${IMAGE_REFS[@]}"
|
|
docker buildx imagetools inspect "${TAGS[0]}"
|
|
|
|
# Dreamverse matrix: {backend, UI} x {12.6.3, 13.0.0}, Python 3.12. Torch backend
|
|
# matches the base CUDA (cu126 / cu130). Keep these images amd64-only until the
|
|
# required FA4 dependency stack is available and validated on arm64.
|
|
build-dreamverse:
|
|
if: ${{ github.event.inputs.build_dreamverse_matrix == 'true' }}
|
|
strategy:
|
|
fail-fast: false
|
|
matrix:
|
|
cuda:
|
|
- version: '12.6.3'
|
|
torch_backend: 'cu126'
|
|
- version: '13.0.0'
|
|
torch_backend: 'cu130'
|
|
variant:
|
|
- name: backend
|
|
ui: '0'
|
|
- name: ui
|
|
ui: '1'
|
|
uses: ./.github/workflows/_template-build-image.yml
|
|
with:
|
|
python_version: '3.12'
|
|
dockerfile_path: apps/dreamverse/docker/Dockerfile
|
|
tag_suffix: dreamverse-${{ matrix.variant.name }}-cuda${{ matrix.cuda.version }}
|
|
image_name: dreamverse
|
|
build_args: |
|
|
CUDA_VERSION=${{ matrix.cuda.version }}
|
|
UV_TORCH_BACKEND=${{ matrix.cuda.torch_backend }}
|
|
BUILD_DREAMVERSE_UI=${{ matrix.variant.ui }}
|
|
include_latest_tags: false
|
|
secrets: inherit
|