Spaces:
Sleeping
Sleeping
| name: CI / Lint + Deploy | |
| on: | |
| push: | |
| branches: ["main", "master"] | |
| pull_request: | |
| branches: ["main", "master"] | |
| workflow_dispatch: | |
| jobs: | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # 1. CI β syntax + import smoke test | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| ci: | |
| name: Syntax & Import Check | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.11 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| # Install CPU-only torch to keep CI fast | |
| pip install torch torchvision --index-url https://download.pytorch.org/whl/cpu | |
| pip install -r requirements.txt | |
| - name: Compile-check all Python modules | |
| run: | | |
| python -m py_compile \ | |
| scripts/train_chestmnist.py \ | |
| backend/main.py \ | |
| frontend/app.py \ | |
| model_utils.py | |
| - name: Import smoke test (no model files needed) | |
| run: | | |
| python - <<'PY' | |
| import ast, pathlib | |
| for f in ["scripts/train_chestmnist.py", "backend/main.py", "frontend/app.py", "model_utils.py"]: | |
| ast.parse(pathlib.Path(f).read_text()) | |
| print(f" {f} OK") | |
| print("All imports parseable.") | |
| PY | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # 2. Deploy β push code to Hugging Face Space (on main branch only) | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| deploy: | |
| name: Deploy to Hugging Face Spaces | |
| if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master') && github.event_name == 'push' | |
| needs: ci | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.11 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install huggingface_hub | |
| run: pip install huggingface_hub | |
| - name: Push Space to Hugging Face Hub | |
| env: | |
| HF_TOKEN: ${{ secrets.HF_TOKEN }} | |
| HF_SPACE_REPO: ${{ secrets.HF_SPACE_REPO }} | |
| GITHUB_SHA: ${{ github.sha }} | |
| run: | | |
| python - <<'PY' | |
| import os | |
| from huggingface_hub import HfApi | |
| token = os.environ["HF_TOKEN"] | |
| space_repo = os.environ["HF_SPACE_REPO"] # e.g. "your-username/pneumoops" | |
| sha_tag = f"build-{os.environ['GITHUB_SHA'][:7]}" | |
| api = HfApi(token=token) | |
| api.create_repo(repo_id=space_repo, repo_type="space", space_sdk="docker", exist_ok=True) | |
| api.upload_folder( | |
| repo_id=space_repo, | |
| repo_type="space", | |
| folder_path=".", | |
| commit_message=f"Deploy {sha_tag}", | |
| ignore_patterns=[ | |
| ".git/*", "__pycache__/*", "*.pyc", | |
| ".venv/*", "venv/*", | |
| "data/hf_cache/*", | |
| ], | |
| ) | |
| try: | |
| api.create_tag(repo_id=space_repo, repo_type="space", tag=sha_tag) | |
| except Exception: | |
| pass # tag already exists | |
| print(f"Deployed {sha_tag} β https://huggingface.co/spaces/{space_repo}") | |
| PY | |
| - name: Upload model artifacts to HF Model Hub | |
| # Only runs if HF_MODEL_REPO secret is set | |
| if: ${{ env.HF_MODEL_REPO != '' }} | |
| env: | |
| HF_TOKEN: ${{ secrets.HF_TOKEN }} | |
| HF_MODEL_REPO: ${{ secrets.HF_MODEL_REPO }} | |
| GITHUB_SHA: ${{ github.sha }} | |
| run: | | |
| python - <<'PY' | |
| import os | |
| from huggingface_hub import HfApi | |
| from pathlib import Path | |
| token = os.environ["HF_TOKEN"] | |
| model_repo = os.environ["HF_MODEL_REPO"] | |
| sha_tag = f"build-{os.environ['GITHUB_SHA'][:7]}" | |
| api = HfApi(token=token) | |
| api.create_repo(repo_id=model_repo, repo_type="model", exist_ok=True) | |
| model_dir = Path("models/chestmnist_mobilenetv3") | |
| if model_dir.exists(): | |
| api.upload_folder( | |
| repo_id=model_repo, | |
| repo_type="model", | |
| folder_path=str(model_dir), | |
| commit_message=f"Upload model {sha_tag}", | |
| ) | |
| print(f"Model artifacts uploaded β https://huggingface.co/models/{model_repo}") | |
| PY | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # 3. Deploy β push backend+frontend to Railway (on main branch only) | |
| # βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| deploy-railway: | |
| name: Deploy to Railway | |
| if: (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master') && github.event_name == 'push' | |
| needs: ci | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Railway CLI | |
| run: npm install -g @railway/cli | |
| - name: Deploy to Railway | |
| env: | |
| RAILWAY_TOKEN: ${{ secrets.RAILWAY_TOKEN }} | |
| run: railway up --service pneumoops-backend --detach | |