1
+ name : CI/CD Pipeline
2
+
3
+ on :
4
+ push :
5
+ branches : [ main, develop ]
6
+ pull_request :
7
+ branches : [ main ]
8
+ workflow_dispatch :
9
+
10
+ env :
11
+ DOCKER_BUILDKIT : 1
12
+ COMPOSE_DOCKER_CLI_BUILD : 1
13
+ PYTHON_VERSION : 3.12.7
14
+
15
+ jobs :
16
+ test :
17
+ name : Test Suite
18
+ runs-on : ubuntu-latest
19
+
20
+ services :
21
+ postgres :
22
+ image : postgres:15-alpine
23
+ env :
24
+ POSTGRES_PASSWORD : test_password
25
+ POSTGRES_DB : test_db
26
+ options : >-
27
+ --health-cmd pg_isready
28
+ --health-interval 10s
29
+ --health-timeout 5s
30
+ --health-retries 5
31
+ ports :
32
+ - 5432:5432
33
+
34
+ redis :
35
+ image : redis:7-alpine
36
+ options : >-
37
+ --health-cmd "redis-cli ping"
38
+ --health-interval 10s
39
+ --health-timeout 5s
40
+ --health-retries 5
41
+ ports :
42
+ - 6379:6379
43
+
44
+ steps :
45
+ - name : Checkout code
46
+ uses : actions/checkout@v4
47
+
48
+ - name : Set up Python
49
+ uses : actions/setup-python@v4
50
+ with :
51
+ python-version : ${{ env.PYTHON_VERSION }}
52
+
53
+ - name : Cache pip dependencies
54
+ uses : actions/cache@v3
55
+ with :
56
+ path : ~/.cache/pip
57
+ key : ${{ runner.os }}-pip-${{ hashFiles('**/requirements*.txt') }}
58
+ restore-keys : |
59
+ ${{ runner.os }}-pip-
60
+
61
+ - name : Install dependencies
62
+ run : |
63
+ python -m pip install --upgrade pip
64
+ pip install -r requirements.txt
65
+ pip install -r requirements-dev.txt
66
+ pip install pytest pytest-asyncio pytest-cov
67
+
68
+ - name : Create test environment file
69
+ run : |
70
+ cat > .env.test << EOF
71
+ DATABASE_URL=postgresql://postgres:test_password@localhost:5432/test_db
72
+ REDIS_URL=redis://localhost:6379
73
+ SECRET_KEY=test_secret_key_for_testing_only
74
+ ENABLE_API_KEYS=true
75
+ LOG_LEVEL=INFO
76
+ TESTING=true
77
+ EOF
78
+
79
+ - name : Run database migrations
80
+ run : |
81
+ export $(cat .env.test | xargs)
82
+ alembic upgrade head
83
+
84
+ - name : Run tests with coverage
85
+ run : |
86
+ export $(cat .env.test | xargs)
87
+ pytest --cov=api --cov-report=xml --cov-report=html --cov-report=term-missing -v
88
+
89
+ - name : Upload coverage to Codecov
90
+ uses : codecov/codecov-action@v3
91
+ with :
92
+ file : ./coverage.xml
93
+ flags : unittests
94
+ name : codecov-umbrella
95
+ fail_ci_if_error : false
96
+
97
+ - name : Generate coverage report
98
+ run : |
99
+ echo "## Test Coverage Report" >> $GITHUB_STEP_SUMMARY
100
+ echo "$(coverage report)" >> $GITHUB_STEP_SUMMARY
101
+
102
+ - name : Archive test results
103
+ uses : actions/upload-artifact@v3
104
+ if : always()
105
+ with :
106
+ name : test-results
107
+ path : |
108
+ htmlcov/
109
+ coverage.xml
110
+ pytest-report.xml
111
+
112
+ lint :
113
+ name : Code Quality
114
+ runs-on : ubuntu-latest
115
+
116
+ steps :
117
+ - name : Checkout code
118
+ uses : actions/checkout@v4
119
+
120
+ - name : Set up Python
121
+ uses : actions/setup-python@v4
122
+ with :
123
+ python-version : ${{ env.PYTHON_VERSION }}
124
+
125
+ - name : Install linting tools
126
+ run : |
127
+ python -m pip install --upgrade pip
128
+ pip install black flake8 mypy isort bandit safety
129
+
130
+ - name : Run Black (code formatting)
131
+ run : black --check --diff api/ tests/
132
+
133
+ - name : Run isort (import sorting)
134
+ run : isort --check-only --diff api/ tests/
135
+
136
+ - name : Run flake8 (linting)
137
+ run : flake8 api/ tests/
138
+
139
+ - name : Run mypy (type checking)
140
+ run : mypy api/
141
+
142
+ - name : Run bandit (security)
143
+ run : bandit -r api/
144
+
145
+ - name : Run safety (dependency security)
146
+ run : safety check
147
+
148
+ build :
149
+ name : Build Docker Images
150
+ runs-on : ubuntu-latest
151
+ needs : [test, lint]
152
+
153
+ strategy :
154
+ matrix :
155
+ component : [api, worker-cpu, worker-gpu]
156
+ include :
157
+ - component : api
158
+ dockerfile : docker/api/Dockerfile
159
+ context : .
160
+ build_args : |
161
+ PYTHON_VERSION=${{ env.PYTHON_VERSION }}
162
+ - component : worker-cpu
163
+ dockerfile : docker/worker/Dockerfile
164
+ context : .
165
+ build_args : |
166
+ PYTHON_VERSION=${{ env.PYTHON_VERSION }}
167
+ WORKER_TYPE=cpu
168
+ - component : worker-gpu
169
+ dockerfile : docker/worker/Dockerfile
170
+ context : .
171
+ build_args : |
172
+ PYTHON_VERSION=${{ env.PYTHON_VERSION }}
173
+ WORKER_TYPE=gpu
174
+
175
+ steps :
176
+ - name : Checkout code
177
+ uses : actions/checkout@v4
178
+
179
+ - name : Set up Docker Buildx
180
+ uses : docker/setup-buildx-action@v3
181
+
182
+ - name : Login to Container Registry
183
+ if : github.ref == 'refs/heads/main'
184
+ uses : docker/login-action@v3
185
+ with :
186
+ registry : ghcr.io
187
+ username : ${{ github.actor }}
188
+ password : ${{ secrets.GITHUB_TOKEN }}
189
+
190
+ - name : Extract metadata
191
+ id : meta
192
+ uses : docker/metadata-action@v5
193
+ with :
194
+ images : ghcr.io/${{ github.repository }}/${{ matrix.component }}
195
+ tags : |
196
+ type=ref,event=branch
197
+ type=ref,event=pr
198
+ type=sha,prefix={{branch}}-
199
+ type=raw,value=latest,enable={{is_default_branch}}
200
+
201
+ - name : Build and push
202
+ uses : docker/build-push-action@v5
203
+ with :
204
+ context : ${{ matrix.context }}
205
+ file : ${{ matrix.dockerfile }}
206
+ build-args : ${{ matrix.build_args }}
207
+ push : ${{ github.ref == 'refs/heads/main' }}
208
+ tags : ${{ steps.meta.outputs.tags }}
209
+ labels : ${{ steps.meta.outputs.labels }}
210
+ cache-from : type=gha
211
+ cache-to : type=gha,mode=max
212
+ platforms : linux/amd64,linux/arm64
213
+
214
+ security-scan :
215
+ name : Security Scan
216
+ runs-on : ubuntu-latest
217
+ needs : build
218
+ if : github.ref == 'refs/heads/main'
219
+
220
+ steps :
221
+ - name : Checkout code
222
+ uses : actions/checkout@v4
223
+
224
+ - name : Run Trivy vulnerability scanner
225
+ uses : aquasecurity/trivy-action@master
226
+ with :
227
+ image-ref : ghcr.io/${{ github.repository }}/api:latest
228
+ format : ' sarif'
229
+ output : ' trivy-results.sarif'
230
+
231
+ - name : Upload Trivy scan results
232
+ uses : github/codeql-action/upload-sarif@v2
233
+ with :
234
+ sarif_file : ' trivy-results.sarif'
235
+
236
+ integration-test :
237
+ name : Integration Tests
238
+ runs-on : ubuntu-latest
239
+ needs : build
240
+
241
+ steps :
242
+ - name : Checkout code
243
+ uses : actions/checkout@v4
244
+
245
+ - name : Set up Docker Buildx
246
+ uses : docker/setup-buildx-action@v3
247
+
248
+ - name : Build test environment
249
+ run : |
250
+ docker-compose -f docker-compose.yml -f docker-compose.test.yml build
251
+
252
+ - name : Run integration tests
253
+ run : |
254
+ docker-compose -f docker-compose.yml -f docker-compose.test.yml up -d
255
+ sleep 30
256
+
257
+ # Run API health check
258
+ curl -f http://localhost:8000/api/v1/health || exit 1
259
+
260
+ # Run basic API tests
261
+ python -m pytest tests/integration/ -v
262
+
263
+ - name : Cleanup
264
+ if : always()
265
+ run : |
266
+ docker-compose -f docker-compose.yml -f docker-compose.test.yml down -v
267
+
268
+ deploy-staging :
269
+ name : Deploy to Staging
270
+ runs-on : ubuntu-latest
271
+ needs : [test, lint, build, integration-test]
272
+ if : github.ref == 'refs/heads/develop'
273
+ environment : staging
274
+
275
+ steps :
276
+ - name : Checkout code
277
+ uses : actions/checkout@v4
278
+
279
+ - name : Deploy to staging
280
+ run : |
281
+ echo "Deploying to staging environment..."
282
+ # Add deployment commands here
283
+ # Example: kubectl apply -f k8s/staging/
284
+
285
+ - name : Run staging tests
286
+ run : |
287
+ echo "Running staging tests..."
288
+ # Add staging test commands here
289
+
290
+ - name : Notify deployment
291
+ if : always()
292
+ run : |
293
+ echo "Staging deployment completed"
294
+
295
+ deploy-production :
296
+ name : Deploy to Production
297
+ runs-on : ubuntu-latest
298
+ needs : [test, lint, build, integration-test, security-scan]
299
+ if : github.ref == 'refs/heads/main'
300
+ environment : production
301
+
302
+ steps :
303
+ - name : Checkout code
304
+ uses : actions/checkout@v4
305
+
306
+ - name : Deploy to production
307
+ run : |
308
+ echo "Deploying to production environment..."
309
+ # Add production deployment commands here
310
+ # Example: kubectl apply -f k8s/production/
311
+
312
+ - name : Run production smoke tests
313
+ run : |
314
+ echo "Running production smoke tests..."
315
+ # Add production smoke test commands here
316
+
317
+ - name : Create deployment issue
318
+ if : failure()
319
+ uses : actions/github-script@v6
320
+ with :
321
+ script : |
322
+ github.rest.issues.create({
323
+ owner: context.repo.owner,
324
+ repo: context.repo.repo,
325
+ title: 'Production deployment failed',
326
+ body: 'Production deployment failed. Please check the logs and take necessary action.',
327
+ labels: ['bug', 'production', 'deployment']
328
+ })
329
+
330
+ - name : Notify deployment
331
+ if : always()
332
+ run : |
333
+ echo "Production deployment completed"
334
+
335
+ backup-database :
336
+ name : Database Backup
337
+ runs-on : ubuntu-latest
338
+ if : github.ref == 'refs/heads/main'
339
+
340
+ steps :
341
+ - name : Checkout code
342
+ uses : actions/checkout@v4
343
+
344
+ - name : Run database backup
345
+ run : |
346
+ echo "Running database backup..."
347
+ # Add database backup commands here
348
+ # Example: ./scripts/backup-database.sh
349
+
350
+ - name : Upload backup artifacts
351
+ uses : actions/upload-artifact@v3
352
+ with :
353
+ name : database-backup
354
+ path : backups/
355
+ retention-days : 7
356
+
357
+ performance-test :
358
+ name : Performance Tests
359
+ runs-on : ubuntu-latest
360
+ needs : build
361
+ if : github.ref == 'refs/heads/main'
362
+
363
+ steps :
364
+ - name : Checkout code
365
+ uses : actions/checkout@v4
366
+
367
+ - name : Run performance tests
368
+ run : |
369
+ echo "Running performance tests..."
370
+ # Add performance test commands here
371
+ # Example: locust -f tests/performance/locustfile.py
372
+
373
+ - name : Generate performance report
374
+ run : |
375
+ echo "Generating performance report..."
376
+ # Add performance report generation here
377
+
378
+ notify :
379
+ name : Notify Results
380
+ runs-on : ubuntu-latest
381
+ needs : [test, lint, build, integration-test]
382
+ if : always()
383
+
384
+ steps :
385
+ - name : Notify success
386
+ if : needs.test.result == 'success' && needs.lint.result == 'success' && needs.build.result == 'success'
387
+ run : |
388
+ echo "All CI/CD jobs completed successfully!"
389
+
390
+ - name : Notify failure
391
+ if : needs.test.result == 'failure' || needs.lint.result == 'failure' || needs.build.result == 'failure'
392
+ run : |
393
+ echo "Some CI/CD jobs failed. Please check the logs."
394
+ exit 1
0 commit comments