LTX-2.5: 21B joint video+audio DiT and the generalized video seam #62
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: containers | |
| # Published container images -- ENG-RELEASE-CONTAINERS, issue #170. | |
| # Design: .agents/specs/container-images.md | |
| # | |
| # Authority is separated by stage, exactly as release.yml separates it: | |
| # | |
| # plan contents: read resolve version and lanes, validate the tag | |
| # verify contents: read build + validate every lane x arch. NO registry | |
| # write exists in this job, so a pull request | |
| # cannot publish even if a step tried to. | |
| # publish packages: write tags only. Builds, validates the image it is | |
| # about to push, THEN pushes by digest. The bytes | |
| # that were validated are the bytes that ship. | |
| # manifest packages: write join the per-arch digests into :<version>-<lane> | |
| # attest id-token: write provenance over the manifest digest | |
| # promote packages: write move :latest-<lane> only after everything is green | |
| # | |
| # Pull requests and manual dispatch stop after verify. | |
| on: | |
| push: | |
| tags: ['v*'] | |
| # main publishes moving :main-<lane> images. Only container INFRASTRUCTURE | |
| # paths trigger it: main takes dozens of pushes a day and three lanes on two | |
| # architectures each time is prohibitive, so product changes ride the | |
| # nightly below and container changes rebuild immediately. | |
| branches: [main] | |
| paths: | |
| - 'docker/**' | |
| - 'release/container-matrix.json' | |
| - 'scripts/validate-container-image.py' | |
| - 'scripts/container_tags.py' | |
| - 'scripts/build-cpu-release.sh' | |
| - 'scripts/build-linux-accelerator-release.sh' | |
| - '.github/workflows/containers.yml' | |
| schedule: | |
| # Nightly, so a main image is never more than a day behind the tree. | |
| - cron: '0 4 * * *' | |
| pull_request: | |
| workflow_dispatch: | |
| inputs: | |
| full_matrix: | |
| description: >- | |
| Build every lane on both architectures, including the ten-SM fat cuda | |
| lane that pull requests skip for cost. Use this to prove a lane that | |
| is not in the pull-request matrix. | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: read | |
| env: | |
| REGISTRY_PACKAGE: ghcr.io/mudler/vllm.cpp | |
| jobs: | |
| plan: | |
| permissions: | |
| contents: read | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.plan.outputs.version }} | |
| is_release: ${{ steps.plan.outputs.is_release }} | |
| is_main: ${{ steps.plan.outputs.is_main }} | |
| publishes: ${{ steps.plan.outputs.publishes }} | |
| verify_matrix: ${{ steps.matrix.outputs.verify }} | |
| publish_matrix: ${{ steps.matrix.outputs.publish }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Resolve the version and validate it against the tag | |
| id: plan | |
| run: | | |
| set -euo pipefail | |
| version=$(sed -n 's/^project(vllm_cpp VERSION \([^ ]*\).*/\1/p' CMakeLists.txt) | |
| test -n "$version" | |
| if [ "${GITHUB_REF_TYPE}" = "tag" ]; then | |
| # The tag is untrusted input until it matches the tree. | |
| test "${GITHUB_REF_NAME}" = "v${version}" | |
| echo "is_release=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "is_release=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| # A main publish is a push to main or the nightly -- never a pull | |
| # request, which has no credentials and must not reach a registry. | |
| is_main=false | |
| if [ "${GITHUB_REF_TYPE}" != "tag" ] \ | |
| && [ "${GITHUB_REF_NAME}" = "main" ] \ | |
| && [ "${GITHUB_EVENT_NAME}" != "pull_request" ]; then | |
| is_main=true | |
| fi | |
| echo "is_main=${is_main}" >> "$GITHUB_OUTPUT" | |
| if [ "${is_main}" = "true" ] || [ "${GITHUB_REF_TYPE}" = "tag" ]; then | |
| echo "publishes=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "publishes=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo "version=${version}" >> "$GITHUB_OUTPUT" | |
| - name: Gate the container matrix against the Dockerfile | |
| run: python3 scripts/check-container-matrix.py | |
| - name: Resolve the lane x architecture build matrices | |
| id: matrix | |
| run: | | |
| set -euo pipefail | |
| # A release run builds every lane on both architectures. A pull | |
| # request builds the reduced set the matrix opts in, because a ten-SM | |
| # fat CUDA image does not fit a hosted runner budget per push. Nothing | |
| # is published without the full set: publish rebuilds and revalidates | |
| # each lane immediately before pushing it. | |
| if [ "${{ steps.plan.outputs.is_release }}" = "true" ] \ | |
| || [ "${{ inputs.full_matrix }}" = "true" ]; then | |
| echo "verify=$(python3 scripts/container_tags.py --build-matrix --release)" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "verify=$(python3 scripts/container_tags.py --build-matrix)" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo "publish=$(python3 scripts/container_tags.py --build-matrix --release)" >> "$GITHUB_OUTPUT" | |
| - name: Gate this workflow against its own contract | |
| run: python3 scripts/check-container-workflow.py | |
| verify: | |
| needs: plan | |
| permissions: | |
| contents: read | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: ${{ fromJSON(needs.plan.outputs.verify_matrix) }} | |
| runs-on: ${{ matrix.runner }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: docker/setup-buildx-action@v3 | |
| - name: Build the lane image for this architecture | |
| run: | | |
| set -euo pipefail | |
| docker buildx build \ | |
| --file docker/Dockerfile \ | |
| --target "${{ matrix.lane }}" \ | |
| --platform "${{ matrix.platform }}" \ | |
| --build-arg "VERSION=${{ needs.plan.outputs.version }}" \ | |
| --build-arg "SOURCE_SHA=${GITHUB_SHA}" \ | |
| --build-arg "SOURCE_DATE_EPOCH=$(git show -s --format=%ct HEAD)" \ | |
| --build-arg "EVIDENCE_URL=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \ | |
| --build-arg "JOBS=$(nproc)" \ | |
| --tag "vllm-cpp-verify:${{ matrix.lane }}" \ | |
| --load \ | |
| . | |
| - name: Validate the built image | |
| run: | | |
| python3 scripts/validate-container-image.py \ | |
| --image "vllm-cpp-verify:${{ matrix.lane }}" \ | |
| --lane "${{ matrix.lane }}" \ | |
| --version "${{ needs.plan.outputs.version }}" \ | |
| --expect-revision "${GITHUB_SHA}" | |
| publish: | |
| needs: [plan, verify] | |
| if: needs.plan.outputs.publishes == 'true' | |
| permissions: | |
| contents: read | |
| packages: write | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: ${{ fromJSON(needs.plan.outputs.publish_matrix) }} | |
| runs-on: ${{ matrix.runner }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: docker/setup-buildx-action@v3 | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Refuse to overwrite an existing immutable tag | |
| # Version tags only. :main-<lane> moves by design and is skipped here; | |
| # what must never happen is a republished :<version>-<lane>. | |
| if: needs.plan.outputs.is_release == 'true' | |
| run: | | |
| set -euo pipefail | |
| tag="${REGISTRY_PACKAGE}:${{ needs.plan.outputs.version }}-${{ matrix.lane }}" | |
| if docker buildx imagetools inspect "$tag" >/dev/null 2>&1; then | |
| echo "::error::${tag} already exists; version tags are immutable" >&2 | |
| exit 1 | |
| fi | |
| - name: Build the exact image this job will push | |
| run: | | |
| set -euo pipefail | |
| docker buildx build \ | |
| --file docker/Dockerfile \ | |
| --target "${{ matrix.lane }}" \ | |
| --platform "${{ matrix.platform }}" \ | |
| --build-arg "VERSION=${{ needs.plan.outputs.version }}" \ | |
| --build-arg "SOURCE_SHA=${GITHUB_SHA}" \ | |
| --build-arg "SOURCE_DATE_EPOCH=$(git show -s --format=%ct HEAD)" \ | |
| --build-arg "EVIDENCE_URL=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}" \ | |
| --build-arg "JOBS=$(nproc)" \ | |
| --tag "vllm-cpp-publish:${{ matrix.lane }}" \ | |
| --load \ | |
| . | |
| - name: Validate the image immediately before pushing it | |
| run: | | |
| python3 scripts/validate-container-image.py \ | |
| --image "vllm-cpp-publish:${{ matrix.lane }}" \ | |
| --lane "${{ matrix.lane }}" \ | |
| --version "${{ needs.plan.outputs.version }}" \ | |
| --expect-revision "${GITHUB_SHA}" | |
| - name: Push by digest | |
| id: push | |
| run: | | |
| set -euo pipefail | |
| docker tag "vllm-cpp-publish:${{ matrix.lane }}" "${REGISTRY_PACKAGE}:stage" | |
| docker push "${REGISTRY_PACKAGE}:stage" | |
| # `docker push --quiet` prints the image REFERENCE, not the digest, so | |
| # read back what the registry actually stored. | |
| digest=$(docker image inspect "${REGISTRY_PACKAGE}:stage" \ | |
| --format '{{index .RepoDigests 0}}' | sed 's/.*@//') | |
| case "$digest" in sha256:*) ;; *) echo "::error::no digest" >&2; exit 1 ;; esac | |
| echo "digest=${digest}" >> "$GITHUB_OUTPUT" | |
| - name: Record the exact digest for the manifest stage | |
| run: | | |
| mkdir -p digests | |
| arch=$(echo "${{ matrix.platform }}" | tr '/' '-') | |
| echo "${{ steps.push.outputs.digest }}" > "digests/${{ matrix.lane }}-${arch}" | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: container-digest-${{ matrix.lane }}-${{ strategy.job-index }} | |
| path: digests/* | |
| if-no-files-found: error | |
| retention-days: 7 | |
| manifest: | |
| needs: [plan, publish] | |
| if: needs.plan.outputs.publishes == 'true' | |
| permissions: | |
| contents: read | |
| packages: write | |
| runs-on: ubuntu-latest | |
| outputs: | |
| digests: ${{ steps.create.outputs.digests }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/download-artifact@v4 | |
| with: | |
| pattern: container-digest-* | |
| path: digests | |
| merge-multiple: true | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Join the per-architecture digests into one manifest per lane | |
| id: create | |
| run: | | |
| set -euo pipefail | |
| version="${{ needs.plan.outputs.version }}" | |
| for lane in cpu vulkan cuda; do | |
| refs="" | |
| for file in digests/${lane}-linux-*; do | |
| refs="${refs} ${REGISTRY_PACKAGE}@$(cat "$file")" | |
| done | |
| test -n "${refs}" | |
| if [ "${{ needs.plan.outputs.is_release }}" = "true" ]; then | |
| tag="${REGISTRY_PACKAGE}:${version}-${lane}" | |
| else | |
| # A main image is a moving convenience tag, never a version. | |
| tag="${REGISTRY_PACKAGE}:main-${lane}" | |
| fi | |
| docker buildx imagetools create --tag "${tag}" ${refs} | |
| done | |
| attest: | |
| needs: [plan, manifest] | |
| if: needs.plan.outputs.publishes == 'true' | |
| permissions: | |
| contents: read | |
| id-token: write | |
| attestations: write | |
| packages: read | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Resolve the manifest digest for each lane | |
| id: resolve | |
| run: | | |
| set -euo pipefail | |
| version="${{ needs.plan.outputs.version }}" | |
| if [ "${{ needs.plan.outputs.is_release }}" = "true" ]; then prefix="${version}-"; else prefix="main-"; fi | |
| for lane in cpu vulkan cuda; do | |
| digest=$(docker buildx imagetools inspect \ | |
| "${REGISTRY_PACKAGE}:${prefix}${lane}" --format '{{json .Manifest.Digest}}' | tr -d '"') | |
| echo "${lane}=${digest}" >> "$GITHUB_OUTPUT" | |
| done | |
| - uses: actions/attest-build-provenance@v2 | |
| with: | |
| subject-name: ${{ env.REGISTRY_PACKAGE }} | |
| subject-digest: ${{ steps.resolve.outputs.cpu }} | |
| push-to-registry: true | |
| - uses: actions/attest-build-provenance@v2 | |
| with: | |
| subject-name: ${{ env.REGISTRY_PACKAGE }} | |
| subject-digest: ${{ steps.resolve.outputs.vulkan }} | |
| push-to-registry: true | |
| - uses: actions/attest-build-provenance@v2 | |
| with: | |
| subject-name: ${{ env.REGISTRY_PACKAGE }} | |
| subject-digest: ${{ steps.resolve.outputs.cuda }} | |
| push-to-registry: true | |
| promote: | |
| needs: [plan, attest] | |
| if: needs.plan.outputs.is_release == 'true' | |
| permissions: | |
| contents: read | |
| packages: write | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Move the lane pointers, and :latest to the default lane | |
| run: | | |
| set -euo pipefail | |
| python3 scripts/container_tags.py \ | |
| --version "${{ needs.plan.outputs.version }}" --moving > moving-tags.txt | |
| test -s moving-tags.txt | |
| while read -r source target; do | |
| docker buildx imagetools create --tag "$target" "$source" | |
| done < moving-tags.txt |