Spaces:
Sleeping
Sleeping
Download .github/workflows/sync-to-hf-space.yml from polats/opencode-cloud: direct link, hf CLI and curl.
- Browser
- Download file 4.78 kB
-
https://huggingface.co/spaces/polats/opencode-cloud/resolve/main/.github/workflows/sync-to-hf-space.yml
- Command line
-
hf download hf://spaces/polats/opencode-cloud/.github/workflows/sync-to-hf-space.yml
-
curl -L -o sync-to-hf-space.yml https://huggingface.co/spaces/polats/opencode-cloud/resolve/main/.github/workflows/sync-to-hf-space.yml
4.78 kB
| name: Sync to Hugging Face Space | |
| on: | |
| push: | |
| branches: [main] | |
| workflow_dispatch: | |
| # Never let two syncs race each other onto the same Space. | |
| concurrency: | |
| group: hf-space-sync | |
| cancel-in-progress: false | |
| jobs: | |
| # Build and boot the image here first. A Dockerfile that fails on the Space | |
| # leaves it sitting in BUILD_ERROR, so it is much cheaper to find out on a | |
| # runner than in production. | |
| verify: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - name: Build image | |
| run: docker build -t opencode-cloud:ci . | |
| - name: Refuses to start without a password | |
| run: | | |
| if docker run --rm opencode-cloud:ci; then | |
| echo "::error::Container started without OPENCODE_SERVER_PASSWORD set" | |
| exit 1 | |
| fi | |
| echo "OK: container refused to start unauthenticated" | |
| - name: Serves an authenticated API and the web UI | |
| run: | | |
| PW="ci-$RANDOM-$RANDOM" | |
| docker run -d --name oc-ci -p 7860:7860 -e OPENCODE_SERVER_PASSWORD="$PW" opencode-cloud:ci | |
| for i in $(seq 1 40); do | |
| code=$(curl -s -m 3 -o /dev/null -w "%{http_code}" http://127.0.0.1:7860/api/health || true) | |
| [ "$code" = "401" ] && break | |
| sleep 3 | |
| done | |
| echo "--- container log ---" | |
| docker logs oc-ci | |
| if [ "$code" != "401" ]; then | |
| echo "::error::Server never came up (last status: ${code:-none})" | |
| exit 1 | |
| fi | |
| echo "OK: unauthenticated request rejected with 401" | |
| body=$(curl -s -m 10 -u "opencode:$PW" http://127.0.0.1:7860/api/health) | |
| if [ "$body" != '{"healthy":true}' ]; then | |
| echo "::error::Authenticated health check returned: $body" | |
| exit 1 | |
| fi | |
| echo "OK: authenticated health check returned $body" | |
| if ! curl -s -m 30 -u "opencode:$PW" http://127.0.0.1:7860/ | grep -q "<title>"; then | |
| echo "::error::Web UI was not served on /" | |
| exit 1 | |
| fi | |
| echo "OK: web UI served on /" | |
| - name: Stop container | |
| if: always() | |
| run: docker rm -f oc-ci || true | |
| sync: | |
| needs: verify | |
| runs-on: ubuntu-latest | |
| env: | |
| # Defaults to this GitHub repo's owner/name, which is also the Space id. | |
| # Override with a repo variable (or secret) named HF_SPACE. | |
| HF_SPACE: ${{ vars.HF_SPACE || secrets.HF_SPACE || github.repository }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| with: | |
| # Full history: the force-push below cannot be made from a shallow clone. | |
| fetch-depth: 0 | |
| lfs: true | |
| - name: Push to the Space | |
| env: | |
| HF_TOKEN: ${{ secrets.HF_TOKEN }} | |
| run: | | |
| if [ -z "$HF_TOKEN" ]; then | |
| echo "::error::HF_TOKEN secret is not set (Settings -> Secrets and variables -> Actions)" | |
| exit 1 | |
| fi | |
| # Any HF username works alongside a token; derive it so there is one | |
| # less secret to keep in sync, and so a bad token fails here with a | |
| # clear message instead of a confusing git error. | |
| user=$(curl -s -f -H "Authorization: Bearer $HF_TOKEN" \ | |
| https://huggingface.co/api/whoami-v2 | jq -r '.name // empty') | |
| if [ -z "$user" ]; then | |
| echo "::error::HF_TOKEN was rejected by huggingface.co (expired, or not a write token?)" | |
| exit 1 | |
| fi | |
| echo "Authenticated to Hugging Face as $user; syncing to spaces/$HF_SPACE" | |
| # GitHub is the source of truth: force-push so a hand-edit made in the | |
| # Space's web UI cannot block the sync. Anything committed only on the | |
| # Space side is discarded. | |
| git push --force "https://${user}:${HF_TOKEN}@huggingface.co/spaces/${HF_SPACE}" \ | |
| "HEAD:refs/heads/main" 2>&1 | sed "s/${HF_TOKEN}/***/g" | |
| - name: Wait for the Space to come back up | |
| env: | |
| HF_TOKEN: ${{ secrets.HF_TOKEN }} | |
| run: | | |
| for i in $(seq 1 60); do | |
| stage=$(curl -s -m 20 -H "Authorization: Bearer $HF_TOKEN" \ | |
| "https://huggingface.co/api/spaces/${HF_SPACE}" | jq -r '.runtime.stage // "UNKNOWN"') | |
| echo "[$i] $stage" | |
| case "$stage" in | |
| RUNNING) | |
| echo "Space is running." | |
| exit 0 | |
| ;; | |
| BUILD_ERROR|RUNTIME_ERROR|CONFIG_ERROR) | |
| echo "::error::Space ended in $stage — check the build logs at https://huggingface.co/spaces/${HF_SPACE}" | |
| exit 1 | |
| ;; | |
| esac | |
| sleep 15 | |
| done | |
| echo "::warning::Space did not reach RUNNING within 15 minutes; last stage: $stage" | |