Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 84 additions & 0 deletions .github/workflows/deploy-huggingface.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
name: Deploy to HuggingFace Space

# Redeploys the HuggingFace Docker Space on every merge to main (a merged
# PR pushes to main). Mirrors the manual flow in deploy/huggingface/SETUP.md:
# HF's git endpoint rejects the >10 MiB .xiidm blobs that sit in branch
# *history*, so we push ONE squashed, history-free commit of the current
# tree (large binaries ride along via Git LFS).
#
# Required repo configuration (Settings → Secrets and variables → Actions):
# - secret HF_TOKEN : a HuggingFace WRITE access token with access to the Space
# - variable HF_SPACE : the Space path, e.g. "your-user/co-study4grid-game"
# - variable HF_USERNAME : (optional) the token owner's HF username — only
# needed when the Space lives under an ORG and so
# differs from the owner part of HF_SPACE.
#
# The job no-ops (does not fail) when HF_TOKEN / HF_SPACE are absent, so the
# workflow is inert until you opt in by setting them.

on:
push:
branches: [ main ]
workflow_dispatch: {}

# Never run two deploys at once; the latest merge wins.
concurrency:
group: huggingface-space-deploy
cancel-in-progress: true

jobs:
deploy:
name: Push snapshot to HF Space
runs-on: ubuntu-latest
steps:
- name: Check the deploy is configured
id: guard
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
HF_SPACE: ${{ vars.HF_SPACE }}
run: |
if [ -z "$HF_TOKEN" ] || [ -z "$HF_SPACE" ]; then
echo "::notice::HF_TOKEN secret and/or HF_SPACE variable not set — skipping deploy."
echo "configured=false" >> "$GITHUB_OUTPUT"
else
echo "configured=true" >> "$GITHUB_OUTPUT"
fi

- name: Checkout current tree + LFS objects
if: steps.guard.outputs.configured == 'true'
uses: actions/checkout@v4
with:
lfs: true
fetch-depth: 1 # an orphan snapshot only needs the current tree

- name: Configure git + LFS
if: steps.guard.outputs.configured == 'true'
run: |
git lfs install --local
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"

- name: Build a history-free snapshot
if: steps.guard.outputs.configured == 'true'
run: |
cp deploy/huggingface/README.md README.md # HF needs the frontmatter at repo root
git checkout --orphan hf-deploy
git add -A
# Drop inert local dev artifacts from the deployed snapshot.
git rm -q --cached --ignore-unmatch \
.claude/plan.md inspect_action.py profiling_patch_results.json || true
git commit -q -m "Deploy ${GITHUB_SHA::7}"
test "$(git rev-list --count HEAD)" -eq 1 # sanity: exactly one commit

- name: Push to the HuggingFace Space
if: steps.guard.outputs.configured == 'true'
env:
HF_TOKEN: ${{ secrets.HF_TOKEN }}
HF_SPACE: ${{ vars.HF_SPACE }}
HF_USERNAME: ${{ vars.HF_USERNAME }}
run: |
user="${HF_USERNAME:-${HF_SPACE%%/*}}"
# The token is a GitHub secret → masked in logs even inside the URL.
git remote add space "https://${user}:${HF_TOKEN}@huggingface.co/spaces/${HF_SPACE}"
git -c protocol.version=0 push -f space hf-deploy:main
echo "::notice::Pushed snapshot of ${GITHUB_SHA::7} to spaces/${HF_SPACE}; HF will rebuild."
22 changes: 22 additions & 0 deletions deploy/huggingface/SETUP.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,28 @@ git add --renormalize . && git commit -m "migrate binaries to LFS"
reference studies (Medium difficulty). Build without that flag for the bare
workspace.

## Automated redeploy on merge to `main` (GitHub Action)

`.github/workflows/deploy-huggingface.yml` runs the same orphan-snapshot push
automatically on every merge to `main` (and on manual `workflow_dispatch`). It
checks out the current tree with LFS, squashes it to one history-free commit,
and force-pushes it to the Space's `main`.

Opt in by setting, in the GitHub repo **Settings → Secrets and variables →
Actions**:

| Kind | Name | Value |
|---|---|---|
| Secret | `HF_TOKEN` | a HuggingFace **write** access token with access to the Space |
| Variable | `HF_SPACE` | the Space path, e.g. `your-user/co-study4grid-game` |
| Variable | `HF_USERNAME` | *(optional)* the token owner's HF username — only when the Space is under an **org** and so differs from the owner part of `HF_SPACE` |

The job is inert (it logs a notice and exits cleanly) until both `HF_TOKEN` and
`HF_SPACE` are set, so merging the workflow doesn't break anything before you
opt in. The push reuses LFS objects already on the Space, so repeat deploys only
upload what changed. If you want the deploy gated on green tests, change the
trigger to a `workflow_run` on the **Tests** workflow instead of `push`.

## Test the image locally first (recommended)

```bash
Expand Down
Loading