@@ -2,48 +2,121 @@ name: CI/CD
22
33on :
44 push :
5- branches :
6- - main
5+ branches : [main]
76 paths :
87 - ' runner/**'
98 - ' app.py'
109 - ' tests/**'
1110 - ' pyproject.toml'
12- - ' .github/workflows/ci-cd.yml'
13- tags :
14- - ' v*'
11+ - ' .github/workflows/**'
12+ tags : ['v*']
13+ pull_request :
14+ branches : [main]
15+ paths :
16+ - ' runner/**'
17+ - ' app.py'
18+ - ' tests/**'
19+ - ' pyproject.toml'
20+ - ' .github/workflows/**'
1521
1622jobs :
23+ # ── Stage 1: CI Gate (every PR + push) ──────────────────────────────
24+ ci :
25+ name : Lint & Test
26+ runs-on : ubuntu-latest
27+ steps :
28+ - name : Checkout
29+ uses : actions/checkout@v4
30+
31+ - name : Setup Python
32+ uses : actions/setup-python@v5
33+ with :
34+ python-version : " 3.10"
35+
36+ - name : Install dependencies
37+ run : |
38+ python -m pip install --upgrade pip
39+ pip install -e ".[dev]"
40+
41+ - name : Lint
42+ run : ruff check runner/ app.py tests/
43+
44+ - name : Test
45+ run : pytest tests/ -v
46+
47+ # ── Stage 2: Deploy (push to main / tags only) ──────────────────────
1748 deploy :
18- name : Deploy
49+ name : Deploy to Modal
50+ needs : ci
51+ if : github.event_name == 'push'
1952 runs-on : ubuntu-latest
53+ timeout-minutes : 5
2054 concurrency :
2155 group : modal-production-deploy
2256 cancel-in-progress : false
2357 env :
2458 MODAL_TOKEN_ID : ${{ secrets.MODAL_TOKEN_ID }}
2559 MODAL_TOKEN_SECRET : ${{ secrets.MODAL_TOKEN_SECRET }}
26-
2760 steps :
28- - name : Checkout Repository
61+ - name : Checkout
2962 uses : actions/checkout@v4
3063
31- - name : Install Python
64+ - name : Setup Python
3265 uses : actions/setup-python@v5
3366 with :
3467 python-version : " 3.10"
3568
36- - name : Install Dependencies
69+ - name : Install dependencies
3770 run : |
3871 python -m pip install --upgrade pip
3972 pip install -e ".[dev]"
4073
41- - name : Run tests
42- run : pytest tests/ -v
74+ - name : Deploy
75+ run : modal deploy app.py
4376
44- - name : Lint with ruff
45- run : ruff check runner/ app.py tests/
77+ - name : Wait for propagation
78+ run : |
79+ echo "Waiting 5s for Modal deployment to propagate..."
80+ sleep 5
4681
47- - name : Deploy job
82+ # ── Stage 3: Smoke Test (confirms runner is alive) ──────────────────
83+ smoke-test :
84+ name : Smoke Test
85+ needs : deploy
86+ runs-on : [self-hosted, modal, "job-${{ github.run_id }}-smoke"]
87+ timeout-minutes : 5
88+ steps :
89+ - name : Verify runner is healthy
4890 run : |
49- modal deploy app.py
91+ echo "Runner is healthy"
92+ uname -a
93+ echo "Smoke test passed at $(date)"
94+
95+ # ── Stage 4: Integration Tests (parallel, on Modal runner) ──────────
96+ test-basic :
97+ name : Integration - Basic
98+ needs : smoke-test
99+ uses : ./.github/workflows/test.yml
100+
101+ test-docker :
102+ name : Integration - Docker
103+ needs : smoke-test
104+ uses : ./.github/workflows/test-docker.yml
105+
106+ test-concurrency :
107+ name : Integration - Concurrency
108+ needs : smoke-test
109+ uses : ./.github/workflows/test-concurrency.yml
110+
111+ test-concurrency-groups :
112+ name : Integration - Concurrency Groups
113+ needs : smoke-test
114+ uses : ./.github/workflows/test-dummy-concurrency.yml
115+ with :
116+ max_parallel : ' 2'
117+ job_count : ' 5'
118+
119+ test-matrix :
120+ name : Integration - Matrix
121+ needs : smoke-test
122+ uses : ./.github/workflows/matrix-example.yml
0 commit comments