#!/usr/bin/env bash # Release bcc-ui-theme as a wheel on Hugging Face. # # Mirrors biodata-registry/scripts/release.sh, and for the same reasons: # # Why a wheel, not git: HF's git server cannot serve pip's partial clone # (--filter=blob:none), so `pip install git+https://huggingface.co/...` # fails on a Space build. A wheel over the resolve (HTTPS) URL installs. # # Why git-LFS and not `hf upload`: the HF API token is read-only and returns # 403 on upload. The wheel ships as an LFS-tracked file committed at the repo # root. Each wheel needs its OWN .gitattributes line — the entries are # per-filename, not a *.whl glob — or a binary lands in git proper, silently. # And the LFS OBJECT must be pushed BEFORE the ref, or the push is rejected # with "LFS pointer pointed to a file that does not exist". # # Why one commit: the wheel ships with its own source, so a release commit # can never declare a different version than the wheel it carries. That # really happened in biodata-registry (83f95f9 carries 0.1.14 while its # pyproject reads 0.1.13). # # Run after bumping `version` in pyproject.toml. Requires: uv, git-lfs. set -euo pipefail cd "$(dirname "$0")/.." REPO="anne-voigt/bcc-ui-theme" command -v uv >/dev/null || { echo "error: uv required (https://docs.astral.sh/uv/)" >&2; exit 1; } git lfs version >/dev/null 2>&1 || { echo "error: git-lfs required (brew install git-lfs && git lfs install)" >&2; exit 1; } VERSION="$(grep -m1 '^version' pyproject.toml | sed 's/.*"\(.*\)".*/\1/')" [ -n "$VERSION" ] || { echo "error: could not read version from pyproject.toml" >&2; exit 1; } BASE="bcc_ui_theme-$VERSION-py3-none-any.whl" BRANCH="$(git rev-parse --abbrev-ref HEAD)" echo "==> preflight (version $VERSION on branch $BRANCH)" git diff --quiet && git diff --cached --quiet || { echo "error: working tree has uncommitted changes — commit them before releasing." >&2 echo " the wheel must be reproducible from the commit that gets pushed." >&2 exit 1 } [ "$BRANCH" = "main" ] || { echo "error: releases are cut from main (on '$BRANCH'). Merge to main first." >&2 exit 1 } # THE compatibility gate. A theme that constructs on one gradio version and not # the other is the whole failure mode this package exists to prevent, so a # release cannot skip it — there is no SKIP_ escape hatch on purpose. echo "==> suite on BOTH pinned gradio versions (5.50.0 / 6.18.0)" make test-both || { echo "error: the suite is not green on both gradio versions — fix before releasing." >&2 exit 1 } git fetch origin --quiet || true if git cat-file -e "origin/main:$BASE" 2>/dev/null; then echo "error: $BASE already exists on origin/main — bump 'version' in pyproject.toml." >&2 exit 1 fi echo "==> building wheel" rm -rf dist uv build --wheel >/dev/null [ -f "dist/$BASE" ] || { echo "error: expected dist/$BASE, got: $(ls dist/)" >&2; exit 1; } SHA="$(shasum -a 256 "dist/$BASE" | cut -d' ' -f1)" SIZE="$(wc -c < "dist/$BASE" | tr -d ' ')" echo " dist/$BASE ($SIZE B, sha256 $SHA)" echo "==> staging the wheel as a git-LFS file at the repo root" cp "dist/$BASE" "$BASE" if ! grep -qF "$BASE filter=lfs" .gitattributes 2>/dev/null; then echo "$BASE filter=lfs diff=lfs merge=lfs -text" >> .gitattributes echo " added the .gitattributes entry for $BASE" fi git add .gitattributes "$BASE" # Verify it really staged as a pointer, not as a raw binary. if ! git show ":$BASE" 2>/dev/null | head -1 | grep -q "version https://git-lfs"; then echo "error: $BASE staged as a raw binary, not an LFS pointer." >&2 echo " check .gitattributes and that 'git lfs install' has been run." >&2 exit 1 fi echo " ok — staged as an LFS pointer" git commit -q -m "release: bcc-ui-theme $VERSION" echo " release commit $(git rev-parse --short HEAD) (wheel + its own source)" echo "==> uploading the LFS object BEFORE the ref (or the push is rejected)" git lfs push origin main git push origin main COMMIT="$(git rev-parse HEAD)" echo echo "==> released. Pin line for each consumer's requirements.in / requirements.txt:" echo echo "bcc-ui-theme @ https://huggingface.co/$REPO/resolve/$COMMIT/$BASE" echo echo "Then, per consumer:" echo " uv-compiled repos : uv pip compile requirements.in -o requirements.txt --python-version <3.13|3.11>" echo " hand-pinned repos : edit requirements.txt directly (no .in exists)" echo "See docs/ADOPTION.md for which repo is which, and adopt on dev Spaces first."