1
+ name : Stable Build and Test
2
+
3
+ on :
4
+ push :
5
+ branches : [ main, develop ]
6
+ paths :
7
+ - ' docker/**'
8
+ - ' requirements*.txt'
9
+ - ' .python-version'
10
+ - ' docker-compose*.yml'
11
+ pull_request :
12
+ branches : [ main ]
13
+ paths :
14
+ - ' docker/**'
15
+ - ' requirements*.txt'
16
+ - ' .python-version'
17
+ - ' docker-compose*.yml'
18
+ workflow_dispatch :
19
+ inputs :
20
+ python_version :
21
+ description : ' Python version to test'
22
+ required : false
23
+ default : ' 3.12.7'
24
+ type : string
25
+
26
+ env :
27
+ PYTHON_VERSION : ${{ github.event.inputs.python_version || '3.12.7' }}
28
+ DOCKER_BUILDKIT : 1
29
+ COMPOSE_DOCKER_CLI_BUILD : 1
30
+
31
+ jobs :
32
+ validate-python-version :
33
+ name : Validate Python Version Consistency
34
+ runs-on : ubuntu-latest
35
+
36
+ steps :
37
+ - name : Checkout code
38
+ uses : actions/checkout@v4
39
+
40
+ - name : Check Python version pinning
41
+ run : |
42
+ echo "Checking Python version consistency..."
43
+
44
+ # Check .python-version file
45
+ if [ -f ".python-version" ]; then
46
+ PINNED_VERSION=$(cat .python-version)
47
+ echo "Pinned Python version: $PINNED_VERSION"
48
+
49
+ if [ "$PINNED_VERSION" != "$PYTHON_VERSION" ]; then
50
+ echo "❌ Python version mismatch!"
51
+ echo "Pinned: $PINNED_VERSION"
52
+ echo "Target: $PYTHON_VERSION"
53
+ exit 1
54
+ fi
55
+ else
56
+ echo "⚠️ .python-version file not found"
57
+ fi
58
+
59
+ # Check Dockerfiles for consistency
60
+ echo "Checking Dockerfiles for Python version references..."
61
+
62
+ # This ensures all Dockerfiles use ARG for Python version
63
+ if grep -r "python:3\." docker/ | grep -v "ARG\|${PYTHON_VERSION}"; then
64
+ echo "❌ Found hardcoded Python versions in Dockerfiles"
65
+ exit 1
66
+ fi
67
+
68
+ echo "✅ Python version consistency validated"
69
+
70
+ build-matrix :
71
+ name : Build Test Matrix
72
+ runs-on : ubuntu-latest
73
+ needs : validate-python-version
74
+ strategy :
75
+ matrix :
76
+ component : [api, worker-cpu, worker-gpu]
77
+ include :
78
+ - component : api
79
+ dockerfile : docker/api/Dockerfile.new
80
+ build_args : |
81
+ PYTHON_VERSION=${{ env.PYTHON_VERSION }}
82
+ - component : worker-cpu
83
+ dockerfile : docker/worker/Dockerfile
84
+ build_args : |
85
+ PYTHON_VERSION=${{ env.PYTHON_VERSION }}
86
+ WORKER_TYPE=cpu
87
+ - component : worker-gpu
88
+ dockerfile : docker/worker/Dockerfile
89
+ build_args : |
90
+ PYTHON_VERSION=${{ env.PYTHON_VERSION }}
91
+ WORKER_TYPE=gpu
92
+
93
+ steps :
94
+ - name : Checkout code
95
+ uses : actions/checkout@v4
96
+
97
+ - name : Set up Docker Buildx
98
+ uses : docker/setup-buildx-action@v3
99
+
100
+ - name : Build ${{ matrix.component }}
101
+ uses : docker/build-push-action@v5
102
+ with :
103
+ context : .
104
+ file : ${{ matrix.dockerfile }}
105
+ build-args : ${{ matrix.build_args }}
106
+ tags : ffmpeg-${{ matrix.component }}:test
107
+ load : true
108
+ cache-from : type=gha
109
+ cache-to : type=gha,mode=max
110
+
111
+ - name : Test ${{ matrix.component }} dependencies
112
+ run : |
113
+ echo "Testing critical dependencies in ${{ matrix.component }}..."
114
+
115
+ # Test psycopg2-binary (the main fix)
116
+ docker run --rm ffmpeg-${{ matrix.component }}:test python -c "
117
+ import psycopg2
118
+ print(f'✅ psycopg2-binary: {psycopg2.__version__}')
119
+ "
120
+
121
+ # Test other critical dependencies
122
+ if [ "${{ matrix.component }}" = "api" ]; then
123
+ docker run --rm ffmpeg-${{ matrix.component }}:test python -c "
124
+ import fastapi, sqlalchemy, asyncpg
125
+ print(f'✅ FastAPI: {fastapi.__version__}')
126
+ print(f'✅ SQLAlchemy: {sqlalchemy.__version__}')
127
+ print(f'✅ asyncpg: {asyncpg.__version__}')
128
+ "
129
+ fi
130
+
131
+ if [[ "${{ matrix.component }}" == worker* ]]; then
132
+ docker run --rm ffmpeg-${{ matrix.component }}:test python -c "
133
+ import celery, redis
134
+ print(f'✅ Celery: {celery.__version__}')
135
+ print(f'✅ Redis: {redis.__version__}')
136
+ "
137
+ fi
138
+
139
+ echo "✅ All dependencies verified for ${{ matrix.component }}"
140
+
141
+ test-ffmpeg :
142
+ name : Test FFmpeg Installation
143
+ runs-on : ubuntu-latest
144
+ needs : build-matrix
145
+
146
+ steps :
147
+ - name : Checkout code
148
+ uses : actions/checkout@v4
149
+
150
+ - name : Set up Docker Buildx
151
+ uses : docker/setup-buildx-action@v3
152
+
153
+ - name : Build API container
154
+ uses : docker/build-push-action@v5
155
+ with :
156
+ context : .
157
+ file : docker/api/Dockerfile.new
158
+ build-args : |
159
+ PYTHON_VERSION=${{ env.PYTHON_VERSION }}
160
+ tags : ffmpeg-api:ffmpeg-test
161
+ load : true
162
+
163
+ - name : Test FFmpeg functionality
164
+ run : |
165
+ echo "Testing FFmpeg installation and basic functionality..."
166
+
167
+ # Test FFmpeg version
168
+ docker run --rm ffmpeg-api:ffmpeg-test ffmpeg -version | head -1
169
+
170
+ # Test FFmpeg basic functionality with a simple command
171
+ docker run --rm ffmpeg-api:ffmpeg-test ffmpeg -f lavfi -i testsrc=duration=1:size=320x240:rate=1 -t 1 test.mp4
172
+
173
+ echo "✅ FFmpeg installation and basic functionality verified"
174
+
175
+ integration-test :
176
+ name : Integration Test
177
+ runs-on : ubuntu-latest
178
+ needs : [build-matrix, test-ffmpeg]
179
+
180
+ steps :
181
+ - name : Checkout code
182
+ uses : actions/checkout@v4
183
+
184
+ - name : Create test environment
185
+ run : |
186
+ # Create minimal test environment
187
+ cat > test.env << EOF
188
+ DATABASE_URL=sqlite:///test.db
189
+ REDIS_URL=redis://redis:6379
190
+ ENABLE_API_KEYS=false
191
+ LOG_LEVEL=INFO
192
+ EOF
193
+
194
+ - name : Test with Docker Compose
195
+ run : |
196
+ # Use stable compose configuration
197
+ docker-compose -f docker-compose.yml -f docker-compose.stable.yml build
198
+
199
+ # Start services
200
+ docker-compose -f docker-compose.yml -f docker-compose.stable.yml up -d
201
+
202
+ # Wait for services to be ready
203
+ sleep 30
204
+
205
+ # Test API health endpoint
206
+ curl -f http://localhost:8000/api/v1/health || exit 1
207
+
208
+ echo "✅ Integration test passed"
209
+
210
+ - name : Cleanup
211
+ if : always()
212
+ run : |
213
+ docker-compose -f docker-compose.yml -f docker-compose.stable.yml down -v || true
214
+
215
+ security-scan :
216
+ name : Security Scan
217
+ runs-on : ubuntu-latest
218
+ needs : build-matrix
219
+
220
+ steps :
221
+ - name : Checkout code
222
+ uses : actions/checkout@v4
223
+
224
+ - name : Build API for scanning
225
+ uses : docker/build-push-action@v5
226
+ with :
227
+ context : .
228
+ file : docker/api/Dockerfile.new
229
+ build-args : |
230
+ PYTHON_VERSION=${{ env.PYTHON_VERSION }}
231
+ tags : ffmpeg-api:security-scan
232
+ load : true
233
+
234
+ - name : Run Trivy vulnerability scanner
235
+ uses : aquasecurity/trivy-action@master
236
+ with :
237
+ image-ref : ' ffmpeg-api:security-scan'
238
+ format : ' sarif'
239
+ output : ' trivy-results.sarif'
240
+
241
+ - name : Upload Trivy scan results
242
+ uses : github/codeql-action/upload-sarif@v3
243
+ if : always()
244
+ with :
245
+ sarif_file : ' trivy-results.sarif'
246
+
247
+ dependency-check :
248
+ name : Dependency Vulnerability Check
249
+ runs-on : ubuntu-latest
250
+
251
+ steps :
252
+ - name : Checkout code
253
+ uses : actions/checkout@v4
254
+
255
+ - name : Set up Python
256
+ uses : actions/setup-python@v4
257
+ with :
258
+ python-version : ${{ env.PYTHON_VERSION }}
259
+
260
+ - name : Install safety
261
+ run : pip install safety
262
+
263
+ - name : Check dependencies with safety
264
+ run : |
265
+ # Check main requirements
266
+ safety check -r requirements.txt
267
+
268
+ # Check stable requirements if exists
269
+ if [ -f "docker/requirements-stable.txt" ]; then
270
+ safety check -r docker/requirements-stable.txt
271
+ fi
272
+
273
+ generate-report :
274
+ name : Generate Build Report
275
+ runs-on : ubuntu-latest
276
+ needs : [validate-python-version, build-matrix, test-ffmpeg, integration-test, security-scan, dependency-check]
277
+ if : always()
278
+
279
+ steps :
280
+ - name : Checkout code
281
+ uses : actions/checkout@v4
282
+
283
+ - name : Generate build report
284
+ run : |
285
+ cat > build-report.md << EOF
286
+ # Stable Build Report
287
+
288
+ **Date**: $(date)
289
+ **Python Version**: ${{ env.PYTHON_VERSION }}
290
+ **Commit**: ${{ github.sha }}
291
+ **Branch**: ${{ github.ref_name }}
292
+
293
+ ## Build Results
294
+
295
+ | Component | Status |
296
+ |-----------|---------|
297
+ | Python Version Validation | ${{ needs.validate-python-version.result }} |
298
+ | API Build | ${{ needs.build-matrix.result }} |
299
+ | Worker CPU Build | ${{ needs.build-matrix.result }} |
300
+ | Worker GPU Build | ${{ needs.build-matrix.result }} |
301
+ | FFmpeg Test | ${{ needs.test-ffmpeg.result }} |
302
+ | Integration Test | ${{ needs.integration-test.result }} |
303
+ | Security Scan | ${{ needs.security-scan.result }} |
304
+ | Dependency Check | ${{ needs.dependency-check.result }} |
305
+
306
+ ## Key Improvements
307
+
308
+ - ✅ Fixed psycopg2-binary compilation issue
309
+ - ✅ Standardized Python version across all containers
310
+ - ✅ Added comprehensive build dependencies
311
+ - ✅ Implemented proper runtime-only final stages
312
+ - ✅ Added dependency vulnerability scanning
313
+ - ✅ Created integration testing pipeline
314
+
315
+ ## Recommendations
316
+
317
+ 1. Use Python ${{ env.PYTHON_VERSION }} for all deployments
318
+ 2. Monitor dependency vulnerabilities regularly
319
+ 3. Keep FFmpeg updated for security patches
320
+ 4. Implement automated deployment with these validated images
321
+
322
+ EOF
323
+
324
+ echo "Build report generated"
325
+
326
+ - name : Upload build report
327
+ uses : actions/upload-artifact@v3
328
+ with :
329
+ name : build-report
330
+ path : build-report.md
331
+
332
+ notify-status :
333
+ name : Notify Build Status
334
+ runs-on : ubuntu-latest
335
+ needs : [validate-python-version, build-matrix, test-ffmpeg, integration-test, security-scan, dependency-check]
336
+ if : always()
337
+
338
+ steps :
339
+ - name : Build status notification
340
+ run : |
341
+ if [ "${{ needs.build-matrix.result }}" = "success" ] && \
342
+ [ "${{ needs.integration-test.result }}" = "success" ]; then
343
+ echo "🎉 Stable build successful! Ready for deployment."
344
+ echo "BUILD_STATUS=success" >> $GITHUB_ENV
345
+ else
346
+ echo "❌ Build failed. Check the logs for details."
347
+ echo "BUILD_STATUS=failure" >> $GITHUB_ENV
348
+ fi
0 commit comments