avoigt1121
feat(deploy): establish the dev lane — hf-dev remote, dev branch, mirror-hook fix
32b56aa
Raw
History Blame Contribute Delete
3.6 kB
#!/usr/bin/env bash
# Keep the GitHub mirror in step with the deploy (CLAUDE.md "Two remotes", ADR-0007).
#
# `origin` IS the HuggingFace Space: pushing `main` there DEPLOYS. `github` is a mirror that
# only runs CI. Nothing links them, so the mirror silently falls behind every deploy — and a
# stale mirror means Monday's `curation-freshness` job reports on artifacts the Space no longer
# serves. A freshness check that is itself stale is worse than none, because it reads as
# reassurance.
#
# This hook closes that gap at the only moment git offers: when a deploy push is about to
# happen. Install with: make install-hooks
#
# ---------------------------------------------------------------------------------------------
# Two honest limitations, neither of which is worth engineering around:
#
# 1. **The mirror is pushed FIRST.** Git has no post-push hook, so "after the deploy succeeds"
# is not a thing this can be. If the `origin` push then fails (usually a non-fast-forward),
# `github` is briefly AHEAD of the live Space. That self-corrects on the next successful
# deploy, and CI running a superset of production is the milder of the two errors — the one
# this hook exists to prevent is CI running a SUBSET, which looks like a pass.
# 2. **A mirror failure warns; it does not block.** The mirror is CI; `origin` is production.
# Refusing to ship because a secondary remote was unreachable is disproportionate. The
# warning names the one command that fixes it.
#
# Bypass entirely with `git push --no-verify`.
# ---------------------------------------------------------------------------------------------
set -euo pipefail
remote_name="${1:-}"
remote_url="${2:-}"
mirror_remote="${MIRROR_REMOTE:-github}"
dev_remote="${DEV_REMOTE:-hf-dev}"
# The dev Space is also a huggingface.co remote, and `git push hf-dev dev:main` also targets
# refs/heads/main — so it satisfies BOTH tests below. Mirroring it would push dev code onto the
# mirror's `main`, where CI reads it as production: exactly the stale/wrong-CI failure this hook
# exists to prevent, inverted. Excluded by name AND by URL, before the deploy test.
case "$remote_name$remote_url" in
"$dev_remote"*|*-dev|*-dev.git|*-dev/) exit 0 ;;
esac
# Only deploy pushes matter. Match on the URL as well as the name so a push by URL, or a
# differently-named deploy remote, is still recognised.
case "$remote_name$remote_url" in
origin*|*huggingface.co*) ;;
*) exit 0 ;;
esac
# stdin: "<local ref> <local sha> <remote ref> <remote sha>" per ref being pushed.
main_sha=""
while read -r _local_ref local_sha remote_ref _remote_sha; do
[ "$remote_ref" = "refs/heads/main" ] || continue
# All-zero local sha = a branch DELETE. Never mirror that.
case "$local_sha" in *[!0]*) main_sha="$local_sha" ;; esac
done
[ -n "$main_sha" ] || exit 0 # nothing headed for main — not a deploy
if ! git remote get-url "$mirror_remote" >/dev/null 2>&1; then
echo "[pre-push] no '$mirror_remote' remote — the CI mirror will fall behind this deploy." >&2
echo "[pre-push] git remote add $mirror_remote https://github.com/Anne-Voigt/pdac-genomics-agent.git" >&2
exit 0
fi
echo "[pre-push] mirroring ${main_sha:0:7} to '$mirror_remote' so CI matches what is deployed…"
if git push --quiet "$mirror_remote" "$main_sha:refs/heads/main"; then
echo "[pre-push] mirror in sync — proceeding with the deploy."
else
echo "[pre-push] WARNING: mirror push failed. The deploy will proceed; CI is now STALE." >&2
echo "[pre-push] Fix it after the deploy with: git push $mirror_remote main" >&2
fi
exit 0