CoolFace
Apppublic

S-Dreamer/CodeCraftLab

sourceHugging Facemitupdated 4mo agoView on Hugging Face
0likes
hf-sync.yml152 linesDownload Raw Back to root
1name: HF ↔ GitHub Sync2 3# Trigger on every push to main (GitHub → HF direction)4# and hourly to pull any HF-side changes back (HF → GitHub direction)5on:6  push:7    branches: [main]8  schedule:9    - cron: '0 * * * *'   # hourly HF pull-check10  workflow_dispatch:11    inputs:12      force_direction:13        description: 'Force sync direction (hf-wins | gh-wins | auto)'14        required: false15        default: 'auto'16 17env:18  HF_REPO_TYPE: space          # model | dataset | space19  HF_REPO: ${{ vars.HF_REPO }} # e.g. your-org/codecraftlab20 21jobs:22  sync:23    name: Sync HuggingFace ↔ GitHub24    runs-on: ubuntu-latest25    permissions:26      contents: write27 28    steps:29      - name: Checkout (full history)30        uses: actions/checkout@v431        with:32          fetch-depth: 033          token: ${{ secrets.GITHUB_TOKEN }}34 35      - name: Configure git identity36        run: |37          git config user.email "sync-bot@codecraftlab.noreply"38          git config user.name "CodeCraftLab Sync Bot"39 40      - name: Install git-lfs41        run: |42          sudo apt-get install -y git-lfs43          git lfs install44 45      - name: Add HuggingFace remote46        run: |47          git remote add hf \48            "https://user:${{ secrets.HF_TOKEN }}@huggingface.co/${HF_REPO_TYPE}s/${HF_REPO}"49          git fetch hf --prune50 51      - name: Detect divergence and resolve52        id: sync53        env:54          FORCE_DIRECTION: ${{ github.event.inputs.force_direction || 'auto' }}55        run: |56          set -euo pipefail57 58          HF_HEAD=$(git rev-parse hf/main 2>/dev/null || echo "NONE")59          GH_HEAD=$(git rev-parse HEAD)60 61          if [ "$HF_HEAD" = "NONE" ]; then62            echo "action=push-to-hf" >> "$GITHUB_OUTPUT"63            echo "reason=HF remote has no main branch — initial push"64            exit 065          fi66 67          BASE=$(git merge-base HEAD hf/main 2>/dev/null || echo "NONE")68 69          if [ "$FORCE_DIRECTION" = "hf-wins" ]; then70            echo "action=hf-wins" >> "$GITHUB_OUTPUT"71            echo "reason=Forced HF-wins override"72          elif [ "$FORCE_DIRECTION" = "gh-wins" ]; then73            echo "action=push-to-hf" >> "$GITHUB_OUTPUT"74            echo "reason=Forced GH-wins override"75          elif [ "$HF_HEAD" = "$GH_HEAD" ]; then76            echo "action=in-sync" >> "$GITHUB_OUTPUT"77            echo "reason=Already in sync"78          elif [ "$BASE" = "$GH_HEAD" ]; then79            # HF is ahead — pull HF → GitHub80            echo "action=hf-wins" >> "$GITHUB_OUTPUT"81            echo "reason=GitHub is behind HF — fast-forward"82          elif [ "$BASE" = "$HF_HEAD" ]; then83            # GitHub is ahead — push GitHub → HF84            echo "action=push-to-hf" >> "$GITHUB_OUTPUT"85            echo "reason=HF is behind GitHub — pushing"86          else87            # Both diverged — HF is source of truth88            echo "action=hf-wins" >> "$GITHUB_OUTPUT"89            echo "reason=CONFLICT: both diverged — HF wins (source of truth)"90          fi91 92      - name: "[In-sync] Nothing to do"93        if: steps.sync.outputs.action == 'in-sync'94        run: echo "✅ HF and GitHub are in sync — no action required."95 96      - name: "[Push] GitHub → HuggingFace"97        if: steps.sync.outputs.action == 'push-to-hf'98        run: |99          echo "📤 Pushing GitHub → HuggingFace"100          git push hf main101 102      - name: "[HF Wins] HuggingFace → GitHub"103        if: steps.sync.outputs.action == 'hf-wins'104        run: |105          echo "📥 HuggingFace wins — overwriting GitHub main"106          git reset --hard hf/main107          git push origin main --force-with-lease || git push origin main --force108 109      - name: Summary110        if: always()111        run: |112          echo "### Sync Result" >> "$GITHUB_STEP_SUMMARY"113          echo "- **Action:** ${{ steps.sync.outputs.action }}" >> "$GITHUB_STEP_SUMMARY"114          echo "- **Trigger:** ${{ github.event_name }}" >> "$GITHUB_STEP_SUMMARY"115          echo "- **Branch:** main" >> "$GITHUB_STEP_SUMMARY"116 117  # ------------------------------------------------------------------118  # Validate HF Space config on every push119  # ------------------------------------------------------------------120  validate-space-config:121    name: Validate HF Space README config122    runs-on: ubuntu-latest123    steps:124      - uses: actions/checkout@v4125 126      - name: Check README frontmatter127        run: |128          python3 - <<'EOF'129          import re, sys130 131          with open("README.md") as f:132              content = f.read()133 134          match = re.match(r"^---\n(.*?)\n---", content, re.DOTALL)135          if not match:136              print("❌ README is missing HF Space YAML frontmatter")137              sys.exit(1)138 139          frontmatter = match.group(1)140          required_keys = ["title", "sdk", "app_port", "license"]141          missing = [k for k in required_keys if k + ":" not in frontmatter]142          if missing:143              print(f"❌ Missing frontmatter keys: {missing}")144              sys.exit(1)145 146          if "sdk: streamlit" in frontmatter:147              print("❌ sdk is still 'streamlit' — should be 'docker' for FastAPI")148              sys.exit(1)149 150          print("✅ HF Space frontmatter is valid")151          EOF152