File size: 4,486 Bytes
89e8390
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#!/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."