1- name : CI/CD Pipeline
1+ name : CI Pipeline
22
33on :
44 push :
99
1010env :
1111 PYTHON_VERSION : " 3.11"
12- DOCKER_BUILDKIT : 1
1312
1413jobs :
1514 lint-and-typecheck :
@@ -76,258 +75,34 @@ jobs:
7675 name : codecov-umbrella
7776 continue-on-error : true
7877
79- build-container :
80- name : Build Docker Container
78+ validate-docker :
79+ name : Validate Dockerfile
8180 runs-on : ubuntu-latest
82- needs : lint-and-typecheck
83- steps :
84- - name : Checkout code
85- uses : actions/checkout@v4
86-
87- - name : Set up Python
88- uses : actions/setup-python@v5
89- with :
90- python-version : ${{ env.PYTHON_VERSION }}
91-
92- - name : Set up Docker Buildx
93- uses : docker/setup-buildx-action@v3
94-
95- - name : Log in to GitHub Container Registry
96- uses : docker/login-action@v3
97- with :
98- registry : ghcr.io
99- username : ${{ github.actor }}
100- password : ${{ secrets.GITHUB_TOKEN }}
101-
102- - name : Build with build.py (test mode)
103- run : |
104- # Install Python dependencies for build script
105- pip install rich
106-
107- # Run build.py in skip-push mode for testing
108- python build.py --skip-push --version-tag test-${{ github.sha }}
109-
110- # Export the test image for artifact upload
111- docker save ghcr.io/${{ github.repository }}:test-${{ github.sha }} > /tmp/sensor-simulator.tar
112-
113- - name : Upload Docker image artifact
114- uses : actions/upload-artifact@v4
115- with :
116- name : docker-image
117- path : /tmp/sensor-simulator.tar
118- retention-days : 1
119-
120- test-container :
121- name : Test Docker Container
122- runs-on : ubuntu-latest
123- needs : build-container
12481 steps :
12582 - name : Checkout code
12683 uses : actions/checkout@v4
12784
128- - name : Download Docker image artifact
129- uses : actions/download-artifact@v4
130- with :
131- name : docker-image
132- path : /tmp
133-
134- - name : Load Docker image
135- run : |
136- docker load --input /tmp/sensor-simulator.tar
137- # Retag for simpler testing
138- docker tag ghcr.io/${{ github.repository }}:test-${{ github.sha }} sensor-simulator:test
139-
140- - name : Test container startup
141- run : |
142- # Create necessary directories
143- mkdir -p data logs config
144-
145- # Create test config
146- cat > config/test-config.yaml << EOF
147- sensor:
148- type: "environmental"
149- location: "CI Test"
150- manufacturer: "SensorTech"
151- model: "EnvMonitor-3000"
152- firmware_version: "1.4"
153-
154- simulation:
155- readings_per_second: 10
156- run_time_seconds: 5
157-
158- anomalies:
159- enabled: true
160- probability: 0.1
161-
162- database:
163- path: "/app/data/test.db"
164-
165- logging:
166- level: "INFO"
167- console_output: true
168- EOF
169-
170- - name : Run container with default settings
85+ - name : Validate Dockerfile exists
17186 run : |
172- docker run -d --name sensor-default \
173- -v $(pwd)/data:/app/data \
174- -v $(pwd)/logs:/app/logs \
175- sensor-simulator:test
176-
177- # Wait for container to generate some data
178- sleep 10
179-
180- # Check if container is still running
181- docker ps | grep sensor-default
182-
183- # Check logs for errors
184- docker logs sensor-default 2>&1 | grep -i error && exit 1 || true
185-
186- # Stop container
187- docker stop sensor-default
188-
189- - name : Run container with custom config
190- run : |
191- docker run -d --name sensor-custom \
192- -v $(pwd)/data:/app/data \
193- -v $(pwd)/config:/app/config \
194- -e CONFIG_FILE=/app/config/test-config.yaml \
195- sensor-simulator:test
196-
197- # Wait for simulation to complete
198- sleep 7
199-
200- # Check if data was generated
201- if [ ! -f "data/test.db" ]; then
202- echo "Database file not created!"
203- exit 1
204- fi
205-
206- # Verify data was written
207- apt-get update && apt-get install -y sqlite3
208- count=$(sqlite3 data/test.db "SELECT COUNT(*) FROM sensor_data;" 2>/dev/null || echo "0")
209- echo "Generated $count readings"
210-
211- if [ "$count" -eq "0" ]; then
212- echo "No data generated!"
213- docker logs sensor-custom
87+ if [ ! -f "Dockerfile" ]; then
88+ echo "Dockerfile not found!"
21489 exit 1
21590 fi
216-
217- # Stop container
218- docker stop sensor-custom || true
21991
220- - name : Test container with monitoring
221- run : |
222- docker run -d --name sensor-monitor \
223- -v $(pwd)/data:/app/data \
224- -e MONITORING_ENABLED=true \
225- -e MONITORING_PORT=8080 \
226- -p 8080:8080 \
227- sensor-simulator:test
228-
229- # Wait for monitoring to start
230- sleep 5
231-
232- # Test health endpoint
233- curl -f http://localhost:8080/healthz || exit 1
234-
235- # Test metrics endpoint
236- curl -f http://localhost:8080/metricz || exit 1
237-
238- # Stop container
239- docker stop sensor-monitor
240-
241- - name : Test container resilience
242- run : |
243- # Test with missing directories
244- docker run -d --name sensor-resilient \
245- sensor-simulator:test
246-
247- sleep 5
248-
249- # Container should still be running
250- docker ps | grep sensor-resilient
251-
252- # Check for graceful handling
253- docker logs sensor-resilient 2>&1 | grep -E "(ERROR|CRITICAL)" | grep -v "recoverable" && exit 1 || true
254-
255- docker stop sensor-resilient
256-
257- security-scan :
258- name : Security Scan
259- runs-on : ubuntu-latest
260- needs : build-container
261- steps :
262- - name : Checkout code
263- uses : actions/checkout@v4
264-
265- - name : Download Docker image artifact
266- uses : actions/download-artifact@v4
267- with :
268- name : docker-image
269- path : /tmp
270-
271- - name : Load Docker image
272- run : |
273- docker load --input /tmp/sensor-simulator.tar
274- # Retag for simpler testing
275- docker tag ghcr.io/${{ github.repository }}:test-${{ github.sha }} sensor-simulator:test
276-
277- - name : Run Trivy vulnerability scanner
278- uses : aquasecurity/trivy-action@master
279- with :
280- image-ref : sensor-simulator:test
281- format : ' sarif'
282- output : ' trivy-results.sarif'
283- severity : ' CRITICAL,HIGH'
284-
285- - name : Upload Trivy results to GitHub Security
286- uses : github/codeql-action/upload-sarif@v3
92+ - name : Lint Dockerfile
93+ uses : hadolint/hadolint-action@v3.1.0
28794 with :
288- sarif_file : ' trivy-results.sarif '
95+ dockerfile : Dockerfile
28996 continue-on-error : true
29097
291- publish :
292- name : Publish Docker Image
293- runs-on : ubuntu-latest
294- needs : [test, test-container, security-scan]
295- if : github.event_name == 'push' && github.ref == 'refs/heads/main'
296- steps :
297- - name : Checkout code
298- uses : actions/checkout@v4
299-
300- - name : Set up Python
301- uses : actions/setup-python@v5
302- with :
303- python-version : ${{ env.PYTHON_VERSION }}
304-
305- - name : Set up Docker Buildx
306- uses : docker/setup-buildx-action@v3
98+ - name : Test Dockerfile build (single platform)
99+ run : |
100+ # Test that the Dockerfile can build successfully
101+ # We only test a single platform build here for speed
102+ docker build -t test-build:ci .
307103
308- - name : Log in to GitHub Container Registry
309- uses : docker/login-action@v3
310- with :
311- registry : ghcr.io
312- username : ${{ github.actor }}
313- password : ${{ secrets.GITHUB_TOKEN }}
104+ # Verify the image was created
105+ docker images | grep test-build
314106
315- - name : Build and push with build.py
316- run : |
317- # Install Python dependencies for build script
318- pip install rich
319-
320- # Get the current version from the latest tag or use default
321- LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
322- VERSION_NUMBER=${LATEST_TAG#v}
323-
324- # Build and push with auto version bump
325- python build.py --version-bump minor
326-
327- # Also tag as latest for main branch
328- docker tag ghcr.io/${{ github.repository }}:$(cat .latest-semver) ghcr.io/${{ github.repository }}:latest
329- docker push ghcr.io/${{ github.repository }}:latest
330-
331- # Tag with branch name
332- docker tag ghcr.io/${{ github.repository }}:$(cat .latest-semver) ghcr.io/${{ github.repository }}:main
333- docker push ghcr.io/${{ github.repository }}:main
107+ # Clean up
108+ docker rmi test-build:ci || true
0 commit comments