TempuraML's picture
ci: gate Space deploys on CI success + pin action SHAs
5992003
Raw
History Blame Contribute Delete
3.77 kB
name: Deploy
# Continuous deployment to Hugging Face Spaces:
# push to dev -> staging Space (TempuraML/lawn-estimator-dev)
# push to main -> production Space (TempuraML/lawn-estimator)
#
# A deploy = force-push the branch content to the Space's git repo (the Space is
# a mirror; secrets live in HF settings, not git, so a force-push never touches
# them). Self-gating: while the HF_TOKEN secret is absent this skips cleanly
# (Stage B not activated), so it can live on dev/main before the token exists.
on:
push:
branches: [dev, main]
# Docs-only changes shouldn't restart the Space. NOTE: README.md carries the
# Space frontmatter (sdk/app_port) β€” if you change *that*, deploy manually
# (git push to the space remote) since this skips it.
paths-ignore:
- "**.md"
- "docs/**"
- "LICENSE"
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: false # never interrupt a push mid-deploy
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read # checkout
checks: read # the wait-for-CI gate below
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
HF_USERNAME: ${{ vars.HF_USERNAME }}
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
with:
fetch-depth: 0 # full history for the force-push to the Space
# A push to dev/main triggers CI and this workflow in PARALLEL β€” without
# this gate a commit whose CI fails still ships to the Space. Fail closed:
# no green "lint-and-test" check within 20 min = no deploy. Skipped while
# HF_TOKEN is absent (Stage B not activated) so the self-gating still holds.
- name: Wait for CI to pass on this commit
if: env.HF_TOKEN != ''
env:
GH_TOKEN: ${{ github.token }}
run: |
set -euo pipefail
echo "Waiting for CI (lint-and-test) on ${GITHUB_SHA}..."
deadline=$((SECONDS + 1200))
while true; do
status=$(gh api "repos/${GITHUB_REPOSITORY}/commits/${GITHUB_SHA}/check-runs" \
--jq '[.check_runs[] | select(.name == "lint-and-test")] | if length == 0 then "pending:" else "\(.[0].status):\(.[0].conclusion // "")" end')
case "$status" in
completed:success)
echo "CI passed β€” deploying."
break ;;
completed:*)
echo "::error::CI concluded '${status#completed:}' for ${GITHUB_SHA} β€” refusing to deploy."
exit 1 ;;
*)
if [ "$SECONDS" -ge "$deadline" ]; then
echo "::error::Timed out waiting for CI on ${GITHUB_SHA} β€” refusing to deploy."
exit 1
fi
echo "CI is '${status%:}' β€” waiting..."
sleep 20 ;;
esac
done
- name: Deploy to Hugging Face Space
run: |
set -euo pipefail
if [ -z "${HF_TOKEN:-}" ]; then
echo "::notice::HF_TOKEN not set β€” Stage B not activated yet; skipping deploy."
exit 0
fi
if [ -z "${HF_USERNAME:-}" ]; then
echo "::error::Set the HF_USERNAME repo variable (your Hugging Face username) to deploy."
exit 1
fi
if [ "${GITHUB_REF_NAME}" = "main" ]; then
SPACE="TempuraML/lawn-estimator"
echo "Deploying ${GITHUB_SHA} to PRODUCTION Space: ${SPACE}"
else
SPACE="TempuraML/lawn-estimator-dev"
echo "Deploying ${GITHUB_SHA} to STAGING Space: ${SPACE}"
fi
git push --force "https://${HF_USERNAME}:${HF_TOKEN}@huggingface.co/spaces/${SPACE}" "HEAD:main"
echo "Deployed to ${SPACE}."