Merge remote-tracking branch 'origin/docker-blackwell-build' into pr-jupyter-studio-ux

This commit is contained in:
Daniel Han 2026-06-26 10:52:28 +00:00
commit 2e4699c920
5 changed files with 173 additions and 45 deletions

View file

@ -48,6 +48,10 @@ on:
description: 'unslothai/llama.cpp prebuilt release tag to bake (blank = newest)'
required: false
default: ''
notebooks_ref:
description: 'unslothai/notebooks git ref to bake (resolved to one commit)'
required: false
default: 'main'
env:
REGISTRY: docker.io
@ -85,6 +89,12 @@ jobs:
contents: read
outputs:
llama_tag: ${{ steps.llama.outputs.tag }}
# One zoo ref + one notebooks commit, resolved here so BOTH arch legs of
# the base build (and the Studio build) bake the identical bits. Resolving
# them per-leg would let upstream advance between the amd64 and arm64
# builds, putting different content under one published tag.
zoo_ref: ${{ steps.zoo_ref.outputs.ref }}
notebooks_commit: ${{ steps.notebooks.outputs.commit }}
steps:
- name: Resolve llama.cpp prebuilt tag
id: llama
@ -100,6 +110,46 @@ jobs:
echo "tag=${TAG:-latest}" >> "$GITHUB_OUTPUT"
echo "llama.cpp prebuilt tag: ${TAG:-latest}"
# Mirror the unsloth tag into the zoo ONLY when that tag actually exists
# there. unsloth's v* tags are Studio releases the zoo never cuts (the zoo
# repo currently has no tags at all), so blindly mirroring github.ref_name
# made every tag publish fail inside the Dockerfile's zoo install. Resolved
# once here and forwarded to the base build AND the Studio build, so the
# full image's Studio venv runs the same zoo as the base image.
- name: Resolve unsloth-zoo ref
id: zoo_ref
run: |
REF="${{ github.event.inputs.unsloth_zoo_ref }}"
if [ -z "$REF" ] && [ "${{ startsWith(github.ref, 'refs/tags/') }}" = "true" ]; then
if git ls-remote --exit-code --tags https://github.com/unslothai/unsloth-zoo \
"refs/tags/${{ github.ref_name }}" >/dev/null 2>&1; then
REF="${{ github.ref_name }}"
fi
fi
echo "ref=${REF:-main}" >> "$GITHUB_OUTPUT"
echo "unsloth-zoo ref: ${REF:-main}"
# Freeze unslothai/notebooks to ONE concrete commit so both arch legs (and
# release reruns) bake the identical baked-notebook templates and
# .unsloth_template_commit, even if upstream advances mid-build. A 40-char
# sha input is already frozen; a branch/tag (default main) is resolved to
# its current sha via ls-remote, falling back to the bare ref on a lookup
# miss so the Dockerfile can still fetch it by name.
- name: Resolve unsloth/notebooks commit
id: notebooks
env:
INPUT_REF: ${{ github.event.inputs.notebooks_ref }}
run: |
REF="${INPUT_REF:-main}"
if printf '%s' "$REF" | grep -Eq '^[0-9a-f]{40}$'; then
SHA="$REF"
else
SHA="$(git ls-remote https://github.com/unslothai/notebooks "$REF" | awk 'NR==1{print $1}')"
[ -n "$SHA" ] || SHA="$REF"
fi
echo "commit=${SHA}" >> "$GITHUB_OUTPUT"
echo "notebooks commit: ${SHA}"
# ---------------------------------------------------------------------------
# Per-arch build. The matrix fans out two parallel jobs on the matching
# native runner. Each pushes a single-arch image *by digest* (no human-
@ -164,24 +214,6 @@ jobs:
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
# Mirror the unsloth tag into the zoo ONLY when that tag actually
# exists there. unsloth's v* tags are Studio releases the zoo never
# cuts (the zoo repo currently has no tags at all), so blindly
# mirroring github.ref_name made every tag publish fail inside the
# Dockerfile's zoo install.
- name: Resolve unsloth-zoo ref
id: zoo_ref
run: |
REF="${{ github.event.inputs.unsloth_zoo_ref }}"
if [ -z "$REF" ] && [ "${{ startsWith(github.ref, 'refs/tags/') }}" = "true" ]; then
if git ls-remote --exit-code --tags https://github.com/unslothai/unsloth-zoo \
"refs/tags/${{ github.ref_name }}" >/dev/null 2>&1; then
REF="${{ github.ref_name }}"
fi
fi
echo "ref=${REF:-main}" >> "$GITHUB_OUTPUT"
echo "unsloth-zoo ref: ${REF:-main}"
- name: Build and push (per-arch by digest)
id: build
uses: docker/build-push-action@v6
@ -202,18 +234,21 @@ jobs:
# pushes bake the tag's source ref (e.g. v1.2.3) so the published
# image actually contains that release; branch + scheduled runs bake
# the triggering commit SHA; any other event falls back to main.
# UNSLOTH_ZOO_REF (from the resolve step above): explicit dispatch
# input, else the pushed tag IF the zoo repo has it, else main -- a
# branch SHA does not exist in the zoo repo.
# LLAMA_PREBUILT_TAG (from the prepare job): one concrete tag shared
# by both arch legs so the published manifest is reproducible.
# UNSLOTH_ZOO_REF (from the prepare job): explicit dispatch input,
# else the pushed tag IF the zoo repo has it, else main -- a branch
# SHA does not exist in the zoo repo. Resolved once in `prepare` and
# shared with the Studio build so both venvs run the same zoo.
# LLAMA_PREBUILT_TAG / UNSLOTH_NOTEBOOKS_REF (from the prepare job):
# one concrete tag / commit shared by both arch legs so the
# published manifest is byte-reproducible across platforms.
build-args: |
CUDA_VERSION=12.8.1
UBUNTU_VERSION=24.04
PYTHON_VERSION=3.12
UNSLOTH_REF=${{ github.event.inputs.unsloth_ref || (startsWith(github.ref, 'refs/tags/') && github.ref_name) || github.sha || 'main' }}
UNSLOTH_ZOO_REF=${{ steps.zoo_ref.outputs.ref }}
UNSLOTH_ZOO_REF=${{ needs.prepare.outputs.zoo_ref }}
LLAMA_PREBUILT_TAG=${{ needs.prepare.outputs.llama_tag }}
UNSLOTH_NOTEBOOKS_REF=${{ needs.prepare.outputs.notebooks_commit }}
# Stash the per-arch digest as an artifact for the merge job to pick up.
# Filenames need to be unique across the matrix; `platform` contains a
@ -319,7 +354,9 @@ jobs:
# that is the long pole, hence the larger timeout.
# ---------------------------------------------------------------------------
build-studio:
needs: merge
# `merge` for the freshly-published base manifest digest; `prepare` for the
# one resolved zoo ref (job outputs only flow through direct `needs`).
needs: [prepare, merge]
strategy:
fail-fast: false
matrix:
@ -382,11 +419,15 @@ jobs:
cache-to: type=gha,scope=studio-${{ matrix.platform }},mode=min
outputs: type=image,name=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }},push-by-digest=true,name-canonical=true,push=true
# UNSLOTH_STUDIO_REF mirrors the base job's UNSLOTH_REF resolution so the
# Studio tree matches the unsloth baked into the base venv. (Prose stays
# out of build-args -- forwarded lines must be KEY=VALUE only.)
# Studio tree matches the unsloth baked into the base venv.
# UNSLOTH_STUDIO_ZOO_REF is the SAME resolved zoo ref the base build
# baked, so install.sh --local overlays the Studio venv with that zoo
# instead of always tracking main. (Prose stays out of build-args --
# forwarded lines must be KEY=VALUE only.)
build-args: |
BASE_IMAGE=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}@${{ needs.merge.outputs.digest }}
UNSLOTH_STUDIO_REF=${{ github.event.inputs.unsloth_ref || (startsWith(github.ref, 'refs/tags/') && github.ref_name) || github.sha || 'main' }}
UNSLOTH_STUDIO_ZOO_REF=${{ needs.prepare.outputs.zoo_ref }}
- name: Export digest
run: |