Continuous Deployment (CD) #26
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Continuous Deployment (CD) | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| model_name: | |
| description: "Model to deploy" | |
| required: true | |
| type: choice | |
| options: | |
| - all | |
| - smollm3-pruna | |
| - phi4-reasoning-plus-unsloth | |
| - flux-fast-lora-hotswap | |
| - flux-fast-lora-hotswap-img2img | |
| - gemma-torchao | |
| permissions: | |
| contents: read | |
| env: | |
| PYTHON_VERSION: "3.12" | |
| jobs: | |
| # -------------------------------------------------- | |
| # 🎯 Setup (resolve model matrix) | |
| # -------------------------------------------------- | |
| setup: | |
| runs-on: ubuntu-22.04 | |
| outputs: | |
| models: ${{ steps.matrix.outputs.models }} | |
| steps: | |
| - id: matrix | |
| run: | | |
| if [ "${{ github.event.inputs.model_name }}" = "all" ]; then | |
| echo 'models=["smollm3-pruna","phi4-reasoning-plus-unsloth","flux-fast-lora-hotswap","flux-fast-lora-hotswap-img2img","gemma-torchao"]' >> $GITHUB_OUTPUT | |
| else | |
| echo 'models=["${{ github.event.inputs.model_name }}"]' >> $GITHUB_OUTPUT | |
| fi | |
| # -------------------------------------------------- | |
| # ✅ CI | |
| # -------------------------------------------------- | |
| ci: | |
| name: ✅ CI (${{ matrix.model }}) | |
| needs: setup | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 30 | |
| strategy: | |
| matrix: | |
| model: ${{ fromJson(needs.setup.outputs.models) }} | |
| fail-fast: false | |
| env: | |
| MODEL_NAME: ${{ matrix.model }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ matrix.model }}-${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }} | |
| - run: make install-deps | |
| - run: make ci | |
| # -------------------------------------------------- | |
| # 🚀 Deploy | |
| # -------------------------------------------------- | |
| deploy: | |
| name: 🚀 Deploy (${{ matrix.model }}) | |
| needs: [setup, ci] | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 60 | |
| strategy: | |
| matrix: | |
| model: ${{ fromJson(needs.setup.outputs.models) }} | |
| fail-fast: false | |
| outputs: | |
| candidate_model_id: ${{ steps.deploy.outputs.candidate_model_id }} | |
| env: | |
| MODEL_NAME: ${{ matrix.model }} | |
| REPLICATE_API_TOKEN: ${{ secrets.REPLICATE_API_TOKEN }} | |
| HF_TOKEN: ${{ secrets.HF_TOKEN }} | |
| steps: | |
| - uses: jlumbroso/free-disk-space@main | |
| with: | |
| tool-cache: true | |
| large-packages: true | |
| android: true | |
| dotnet: true | |
| haskell: true | |
| docker-images: true | |
| swap-storage: true | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Setup Cog | |
| uses: replicate/setup-cog@v2 | |
| with: | |
| cog-version: "v0.16.9" | |
| token: ${{ secrets.REPLICATE_CLI_AUTH_TOKEN }} | |
| - uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ matrix.model }}-${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }} | |
| - run: make install-deps | |
| - name: Deploy model | |
| id: deploy | |
| env: | |
| MODEL_NAME: ${{ matrix.model }} | |
| REPLICATE_CLI_AUTH_TOKEN: ${{ secrets.REPLICATE_CLI_AUTH_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| echo "🚀 Deploying ${MODEL_NAME}…" | |
| DEPLOY_LOG=$(make deploy) | |
| echo "$DEPLOY_LOG" | |
| VERSION_ID=$(echo "$DEPLOY_LOG" | grep -Eo 'sha256:[a-f0-9]{64}' | head -n1 | sed 's/^sha256://') | |
| if [ -z "$VERSION_ID" ]; then | |
| echo "❌ Failed to extract version hash from deploy output" | |
| exit 1 | |
| fi | |
| MODEL_ID="paragekbote/${MODEL_NAME}:${VERSION_ID}" | |
| echo "candidate_model_id=${MODEL_ID}" >> "$GITHUB_OUTPUT" | |
| echo "✅ Deployed candidate: ${MODEL_ID}" | |
| # -------------------------------------------------- | |
| # 🧪 Integration | |
| # -------------------------------------------------- | |
| integration: | |
| name: 🧪 Run Integration Tests (${{ matrix.model }}) | |
| needs: [setup, deploy] | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 30 | |
| strategy: | |
| matrix: | |
| model: ${{ fromJson(needs.setup.outputs.models) }} | |
| fail-fast: false | |
| env: | |
| MODEL_NAME: ${{ matrix.model }} | |
| REPLICATE_API_TOKEN: ${{ secrets.REPLICATE_API_TOKEN }} | |
| CANDIDATE_MODEL_ID: ${{ needs.deploy.outputs.candidate_model_id }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ matrix.model }}-${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }} | |
| - run: make install-deps | |
| - run: make integration | |
| # -------------------------------------------------- | |
| # 🐦 Canary | |
| # -------------------------------------------------- | |
| canary: | |
| name: 🐦 Run Canary Tests (${{ matrix.model }}) | |
| needs: [setup, deploy, integration] | |
| runs-on: ubuntu-22.04 | |
| timeout-minutes: 45 | |
| strategy: | |
| matrix: | |
| model: ${{ fromJson(needs.setup.outputs.models) }} | |
| fail-fast: false | |
| env: | |
| MODEL_NAME: ${{ matrix.model }} | |
| REPLICATE_API_TOKEN: ${{ secrets.REPLICATE_API_TOKEN }} | |
| CANDIDATE_MODEL_ID: ${{ needs.deploy.outputs.candidate_model_id }} | |
| steps: | |
| - uses: actions/checkout@v5 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ matrix.model }}-${{ runner.os }}-pip-${{ hashFiles('pyproject.toml') }} | |
| - name: Verify candidate model id | |
| run: | | |
| if [ -z "${CANDIDATE_MODEL_ID}" ]; then | |
| echo "ERROR: CANDIDATE_MODEL_ID is not set" | |
| exit 1 | |
| fi | |
| - run: make install-deps | |
| - run: make canary | |
| # -------------------------------------------------- | |
| # 🎉 Summary | |
| # -------------------------------------------------- | |
| summary: | |
| name: Summary | |
| needs: [deploy, integration, canary] | |
| runs-on: ubuntu-22.04 | |
| if: always() | |
| steps: | |
| - run: | | |
| echo "## 🚀 Deployment Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "**Model:** ${{ github.event.inputs.model_name }}" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "- 🚀 Deploy: ${{ needs.deploy.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- 🧪 Integration: ${{ needs.integration.result }}" >> $GITHUB_STEP_SUMMARY | |
| echo "- 🐦 Canary: ${{ needs.canary.result }}" >> $GITHUB_STEP_SUMMARY |