compounding-test / deploy.sh
apingali
fix: address second-pass review nits (3 storage tests + doc cleanup)
cc13144
#!/usr/bin/env bash
# Deploy gradio-apps/compounding-test/ to a HuggingFace Space via
# `git subtree push`. The monorepo stays the canonical source; the
# Space repo holds only the contents of that one subdirectory.
#
# One-time setup (run by the user before first deploy):
# git remote add hf-compounding-test https://huggingface.co/spaces/<owner>/<space>
# # the remote name MUST be `hf-compounding-test` β€” this script looks for it
#
# Every deploy:
# ./gradio-apps/compounding-test/deploy.sh # push current branch
# ./gradio-apps/compounding-test/deploy.sh --dry-run # sanity checks only
# ./gradio-apps/compounding-test/deploy.sh --force # force-push (first deploy only)
set -euo pipefail
REPO_ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
SPACE_DIR="$REPO_ROOT/gradio-apps/compounding-test"
SPACE_PREFIX="gradio-apps/compounding-test"
REMOTE_NAME="hf-compounding-test"
TARGET_BRANCH="main" # HuggingFace Spaces use `main` as the deploy branch
DRY_RUN=0
FORCE=0
for arg in "$@"; do
case "$arg" in
--dry-run) DRY_RUN=1 ;;
--force) FORCE=1 ;;
*) echo "Unknown flag: $arg" >&2; exit 1 ;;
esac
done
# ---------------------------------------------------------------------------
# Sanity checks (fail fast with clear messages)
# ---------------------------------------------------------------------------
cd "$REPO_ROOT"
# 1. Space directory exists
if [[ ! -d "$SPACE_DIR" ]]; then
echo "βœ— Space directory not found: $SPACE_DIR" >&2
exit 1
fi
# 2. Required files exist at the Space root
for required in app.py requirements.txt README.md; do
if [[ ! -f "$SPACE_DIR/$required" ]]; then
echo "βœ— Missing required file at Space root: $SPACE_PREFIX/$required" >&2
exit 1
fi
done
# 3. README.md has the YAML header HF Spaces needs (sdk, app_file).
# Without these, the Space won't build.
if ! grep -q "^sdk: gradio" "$SPACE_DIR/README.md"; then
echo "βœ— $SPACE_PREFIX/README.md is missing 'sdk: gradio' in its YAML header." >&2
echo " HuggingFace Spaces require this to pick the Gradio runtime." >&2
exit 1
fi
if ! grep -q "^app_file: app.py" "$SPACE_DIR/README.md"; then
echo "βœ— $SPACE_PREFIX/README.md is missing 'app_file: app.py' in its YAML header." >&2
exit 1
fi
# 4. HF remote is configured
if ! git remote get-url "$REMOTE_NAME" >/dev/null 2>&1; then
echo "βœ— Git remote '$REMOTE_NAME' not configured." >&2
echo "" >&2
echo " Add it once with:" >&2
echo " git remote add $REMOTE_NAME https://huggingface.co/spaces/<owner>/<space>" >&2
echo "" >&2
echo " (Replace <owner>/<space> with your actual HF Space path, e.g." >&2
echo " AshwinP/compounding-test.)" >&2
exit 1
fi
REMOTE_URL="$(git remote get-url "$REMOTE_NAME")"
# 5. Working tree is clean within the Space directory. Uncommitted changes
# inside the prefix would be SILENTLY DROPPED by git subtree, which is
# a footgun β€” fail loud instead.
if ! git diff --quiet -- "$SPACE_PREFIX" || ! git diff --cached --quiet -- "$SPACE_PREFIX"; then
echo "βœ— Uncommitted changes inside $SPACE_PREFIX/:" >&2
git status --short -- "$SPACE_PREFIX" >&2
echo "" >&2
echo " Commit (or stash) these before deploying β€” git subtree only pushes" >&2
echo " what's in the commit history, so unstaged work would silently miss" >&2
echo " the deploy." >&2
exit 1
fi
# 6. Tests pass. The parser + provider tests are the gate that protects the
# deployed Space's behavior β€” if they're red, do not deploy.
echo "β†’ Running tests in $SPACE_PREFIX/..."
if command -v python3 >/dev/null 2>&1; then
if ! (cd "$SPACE_DIR" && python3 -m pytest test_diagnose.py -q 2>&1 | tail -5); then
echo "βœ— Tests failed. Fix before deploying." >&2
exit 1
fi
else
echo " (python3 not found β€” skipping test gate)" >&2
fi
# ---------------------------------------------------------------------------
# Report state
# ---------------------------------------------------------------------------
CURRENT_BRANCH="$(git rev-parse --abbrev-ref HEAD)"
CURRENT_SHA="$(git rev-parse --short HEAD)"
echo ""
echo "Ready to deploy:"
echo " source prefix: $SPACE_PREFIX"
echo " source commit: $CURRENT_SHA ($CURRENT_BRANCH)"
echo " HF remote: $REMOTE_NAME ($REMOTE_URL)"
echo " target branch: $TARGET_BRANCH"
echo ""
if [[ "$DRY_RUN" -eq 1 ]]; then
echo "βœ“ Dry run β€” all sanity checks passed. No push performed."
exit 0
fi
# ---------------------------------------------------------------------------
# Push to HuggingFace Space
# ---------------------------------------------------------------------------
#
# Two push modes:
# default: `git subtree push` β€” fast-forward only. Works for every deploy
# after the first one (and for first deploys to a Space that has
# never been initialized server-side).
# --force: `git subtree split` to a temp branch, then `git push --force`
# that branch to the remote's main. Required for the FIRST deploy
# to a freshly-created HF Space, because HF auto-creates an initial
# commit (README placeholder) that our subtree history can't
# fast-forward over. `git subtree push --force` is NOT a valid flag
# combo β€” only the split+push form works.
if [[ "$FORCE" -eq 1 ]]; then
TEMP_BRANCH="hf-deploy-$(date +%s)"
echo "β†’ Splitting $SPACE_PREFIX into temp branch $TEMP_BRANCH..."
git subtree split --prefix="$SPACE_PREFIX" -b "$TEMP_BRANCH" >/dev/null
echo "β†’ Force-pushing $TEMP_BRANCH β†’ $REMOTE_NAME/$TARGET_BRANCH..."
if git push "$REMOTE_NAME" "$TEMP_BRANCH:$TARGET_BRANCH" --force; then
git branch -D "$TEMP_BRANCH" >/dev/null
echo ""
echo "βœ“ Force-deploy pushed. HuggingFace will rebuild the Space shortly."
echo " Track build status at: ${REMOTE_URL%.git}"
else
git branch -D "$TEMP_BRANCH" >/dev/null 2>&1 || true
echo ""
echo "βœ— Force-push failed. Check authentication (huggingface-cli login)" >&2
echo " and Space permissions." >&2
exit 1
fi
else
echo "β†’ Pushing subtree to $REMOTE_NAME/$TARGET_BRANCH..."
if git subtree push --prefix="$SPACE_PREFIX" "$REMOTE_NAME" "$TARGET_BRANCH"; then
echo ""
echo "βœ“ Deploy pushed. HuggingFace will rebuild the Space shortly."
echo " Track build status at: ${REMOTE_URL%.git}"
else
echo ""
echo "βœ— Push rejected (non-fast-forward). If this is the FIRST deploy to" >&2
echo " a freshly-created HF Space, HuggingFace seeded the repo with a" >&2
echo " placeholder README that our subtree history can't fast-forward" >&2
echo " over. Re-run with --force to overwrite it:" >&2
echo "" >&2
echo " $(basename "$0") --force" >&2
echo "" >&2
echo " CAUTION: --force overwrites whatever is currently on the Space's" >&2
echo " main branch. Safe for first deploys; review carefully otherwise." >&2
exit 1
fi
fi