Spaces:
Running
Running
| 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}." | |