Skip to content

Commit 4341b9d

Browse files
authored
feat: implement high-priority improvements (#98)
1. Centralize Docker image versions in .env - Add Docker image version variables to .env.example - Update docker-compose.yml to use environment variables with defaults - Update Dockerfiles (pgbouncer, forgejo, vector) to use build args - Enables easy version management and consistent upgrades 2. Add actual vulnerability scanning to security workflow - Install and run Trivy on all Docker images - Parse environment variable defaults from docker-compose.yml - Report CRITICAL vulnerabilities with counts - Provide actionable scan summaries 3. Add unit test execution to test workflow - New 'unit-tests' job running Python, Go, and Rust tests - Tests run with continue-on-error (some require services) - Clear messaging about which tests require infrastructure - Updated test-summary to include unit test results
1 parent 32550fe commit 4341b9d

7 files changed

Lines changed: 213 additions & 33 deletions

File tree

.env.example

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,34 @@
44
# Copy this file to .env and fill in the values
55
# DO NOT commit .env to version control
66

7+
# ===========================================================================
8+
# Docker Image Versions (Centralized Version Management)
9+
# ===========================================================================
10+
# All Docker image versions in one place for easy updates and consistency.
11+
# Update these versions when upgrading services.
12+
#
13+
# Core Infrastructure:
14+
VAULT_VERSION=1.18
15+
POSTGRES_VERSION=18
16+
MYSQL_VERSION=8.0.40
17+
MONGODB_VERSION=7.0
18+
REDIS_VERSION=7.4-alpine3.21
19+
RABBITMQ_VERSION=3.13-management-alpine
20+
21+
# Connection Pooling:
22+
PGBOUNCER_VERSION=latest
23+
24+
# Git Server:
25+
FORGEJO_VERSION=1.21.11-0
26+
27+
# Observability Stack:
28+
PROMETHEUS_VERSION=v2.48.0
29+
GRAFANA_VERSION=10.2.2
30+
LOKI_VERSION=2.9.3
31+
VECTOR_VERSION=0.50.0-debian
32+
CADVISOR_VERSION=v0.47.2
33+
REDIS_EXPORTER_VERSION=v1.55.0
34+
735
# ===========================================================================
836
# HashiCorp Vault Configuration (Secrets Management & PKI)
937
# ===========================================================================

.github/workflows/security.yml

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,20 +92,62 @@ jobs:
9292
done
9393
continue-on-error: true
9494

95-
- name: Check Docker image vulnerabilities
95+
- name: Scan Docker images for vulnerabilities
9696
run: |
97+
echo "Installing Trivy for Docker image scanning..."
98+
curl -sfL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /usr/local/bin v0.58.0
99+
100+
echo ""
97101
echo "Extracting Docker images from docker-compose.yml..."
98102
99-
# Get unique images from docker-compose.yml
100-
images=$(grep -E "^\s+image:" docker-compose.yml | awk '{print $2}' | sort -u)
103+
# Get unique images from docker-compose.yml (resolve env vars to defaults)
104+
images=$(grep -E "^\s+image:" docker-compose.yml | \
105+
sed 's/.*image:\s*//' | \
106+
sed 's/\${[^:]*:-\([^}]*\)}/\1/g' | \
107+
sort -u)
101108
102109
echo "Found images:"
103110
echo "$images"
104111
echo ""
105-
echo "Note: For full vulnerability scanning, consider using:"
106-
echo " - Trivy: trivy image <image>"
107-
echo " - Snyk: snyk container test <image>"
108-
echo " - Docker Scout: docker scout cves <image>"
112+
113+
vuln_count=0
114+
critical_count=0
115+
116+
for image in $images; do
117+
echo ""
118+
echo "=========================================="
119+
echo "Scanning: $image"
120+
echo "=========================================="
121+
122+
# Scan for CRITICAL and HIGH vulnerabilities
123+
if ! trivy image --severity CRITICAL,HIGH --no-progress --exit-code 0 "$image" 2>/dev/null; then
124+
echo "⚠ Warning: Could not scan $image (may need to be pulled first)"
125+
continue
126+
fi
127+
128+
# Count critical vulnerabilities
129+
critical=$(trivy image --severity CRITICAL --no-progress --format json "$image" 2>/dev/null | \
130+
jq '[.Results[]?.Vulnerabilities // [] | length] | add // 0' 2>/dev/null || echo "0")
131+
132+
if [ "$critical" -gt 0 ]; then
133+
echo "⚠ Found $critical CRITICAL vulnerabilities in $image"
134+
critical_count=$((critical_count + critical))
135+
fi
136+
137+
vuln_count=$((vuln_count + 1))
138+
done
139+
140+
echo ""
141+
echo "=========================================="
142+
echo "Scan Summary"
143+
echo "=========================================="
144+
echo "Images scanned: $vuln_count"
145+
echo "Total CRITICAL vulnerabilities: $critical_count"
146+
147+
if [ "$critical_count" -gt 0 ]; then
148+
echo ""
149+
echo "⚠ Warning: Critical vulnerabilities found. Review and update affected images."
150+
fi
109151
110152
trivy-scan:
111153
name: Trivy Security Scan

.github/workflows/test.yml

Lines changed: 107 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,65 @@ jobs:
243243
echo "ℹ No Python files to validate"
244244
fi
245245
246+
unit-tests:
247+
name: Unit Tests
248+
runs-on: ubuntu-latest
249+
250+
steps:
251+
- name: Checkout code
252+
uses: actions/checkout@v6
253+
254+
- name: Set up Python
255+
uses: actions/setup-python@v6
256+
with:
257+
python-version: '3.11'
258+
259+
- name: Set up Go
260+
uses: actions/setup-go@v6
261+
with:
262+
go-version-file: 'reference-apps/golang/go.mod'
263+
264+
- name: Set up Rust
265+
uses: dtolnay/rust-toolchain@stable
266+
267+
- name: Install Python test dependencies
268+
run: |
269+
pip install pytest pytest-asyncio pytest-cov pytest-mock httpx
270+
271+
- name: Run FastAPI unit tests
272+
run: |
273+
cd reference-apps/fastapi
274+
pip install -r requirements.txt
275+
# Run tests that don't require external services
276+
pytest tests/ -v --ignore=tests/test_integration.py -k "not integration" \
277+
--tb=short || echo "⚠ Some tests require running services (expected in CI)"
278+
continue-on-error: true
279+
280+
- name: Run Go unit tests
281+
run: |
282+
cd reference-apps/golang
283+
go test -v -short ./... 2>&1 || echo "⚠ Some tests require running services (expected in CI)"
284+
continue-on-error: true
285+
286+
- name: Run Rust unit tests
287+
run: |
288+
cd reference-apps/rust
289+
cargo test --lib -- --test-threads=1 2>&1 || echo "⚠ Some tests require running services (expected in CI)"
290+
continue-on-error: true
291+
292+
- name: Test summary
293+
run: |
294+
echo "=========================================="
295+
echo "Unit Test Summary"
296+
echo "=========================================="
297+
echo ""
298+
echo "Note: Full test coverage requires running infrastructure services."
299+
echo "Unit tests that don't require external dependencies were executed."
300+
echo ""
301+
echo "For full integration tests, run locally with:"
302+
echo " ./devstack start --profile standard"
303+
echo " ./tests/run-all-tests.sh"
304+
246305
integration-test:
247306
name: Integration Test (Basic)
248307
runs-on: ubuntu-latest
@@ -333,21 +392,60 @@ jobs:
333392
- validate-configs
334393
- test-documentation
335394
- test-python
395+
- unit-tests
336396
- integration-test
337397
if: always()
338398

339399
steps:
340400
- name: Check test results
341401
run: |
342-
if [ "${{ needs.validate-compose.result }}" != "success" ] || \
343-
[ "${{ needs.validate-env.result }}" != "success" ] || \
344-
[ "${{ needs.validate-scripts.result }}" != "success" ] || \
345-
[ "${{ needs.validate-configs.result }}" != "success" ] || \
346-
[ "${{ needs.test-documentation.result }}" != "success" ] || \
347-
[ "${{ needs.test-python.result }}" != "success" ] || \
348-
[ "${{ needs.integration-test.result }}" != "success" ]; then
349-
echo "❌ Some tests failed"
402+
failed=0
403+
404+
if [ "${{ needs.validate-compose.result }}" != "success" ]; then
405+
echo "❌ Docker Compose validation failed"
406+
failed=1
407+
fi
408+
409+
if [ "${{ needs.validate-env.result }}" != "success" ]; then
410+
echo "❌ Environment validation failed"
411+
failed=1
412+
fi
413+
414+
if [ "${{ needs.validate-scripts.result }}" != "success" ]; then
415+
echo "❌ Script validation failed"
416+
failed=1
417+
fi
418+
419+
if [ "${{ needs.validate-configs.result }}" != "success" ]; then
420+
echo "❌ Config validation failed"
421+
failed=1
422+
fi
423+
424+
if [ "${{ needs.test-documentation.result }}" != "success" ]; then
425+
echo "❌ Documentation tests failed"
426+
failed=1
427+
fi
428+
429+
if [ "${{ needs.test-python.result }}" != "success" ]; then
430+
echo "❌ Python syntax check failed"
431+
failed=1
432+
fi
433+
434+
if [ "${{ needs.integration-test.result }}" != "success" ]; then
435+
echo "❌ Integration tests failed"
436+
failed=1
437+
fi
438+
439+
# Unit tests are informational (some require services)
440+
if [ "${{ needs.unit-tests.result }}" == "failure" ]; then
441+
echo "⚠ Unit tests had failures (some may require running services)"
442+
fi
443+
444+
if [ $failed -eq 1 ]; then
350445
exit 1
351446
fi
352447
353-
echo "✅ All tests passed!"
448+
echo "✅ All validation tests passed!"
449+
echo ""
450+
echo "Note: Unit tests for reference apps may have partial failures"
451+
echo "when external services are not available. This is expected in CI."

configs/forgejo/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
FROM codeberg.org/forgejo/forgejo:1.21.11-0
1+
ARG FORGEJO_VERSION=1.21.11-0
2+
FROM codeberg.org/forgejo/forgejo:${FORGEJO_VERSION}
23

34
# Install dependencies for Vault integration (needs root)
45
USER root

configs/pgbouncer/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
FROM edoburu/pgbouncer:latest
1+
ARG PGBOUNCER_VERSION=latest
2+
FROM edoburu/pgbouncer:${PGBOUNCER_VERSION}
23

34
# Install dependencies for Vault integration
45
USER root

configs/vector/Dockerfile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
FROM timberio/vector:0.50.0-debian
1+
ARG VECTOR_VERSION=0.50.0-debian
2+
FROM timberio/vector:${VECTOR_VERSION}
23

34
# Install dependencies required by init script
45
RUN apt-get update && \

docker-compose.yml

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ x-init-library: &init-library
3131
# =============================================================================
3232
x-redis-common: &redis-common
3333
<<: *default-platform
34-
image: redis:7.4-alpine3.21
34+
image: redis:${REDIS_VERSION:-7.4-alpine3.21}
3535
restart: unless-stopped
3636
entrypoint: ["/init/init-approle.sh"]
3737
environment: &redis-env
@@ -75,7 +75,7 @@ x-redis-common: &redis-common
7575
# =============================================================================
7676
x-redis-exporter-common: &redis-exporter-common
7777
<<: *default-platform
78-
image: oliver006/redis_exporter:v1.55.0
78+
image: oliver006/redis_exporter:${REDIS_EXPORTER_VERSION:-v1.55.0}
7979
restart: unless-stopped
8080
entrypoint: ["/init/init.sh"]
8181
environment: &redis-exporter-env
@@ -178,7 +178,7 @@ services:
178178

179179
postgres:
180180
<<: *default-platform
181-
image: postgres:18
181+
image: postgres:${POSTGRES_VERSION:-18}
182182
container_name: dev-postgres
183183
restart: unless-stopped
184184

@@ -270,7 +270,10 @@ services:
270270

271271
pgbouncer:
272272
<<: *default-platform
273-
build: ./configs/pgbouncer
273+
build:
274+
context: ./configs/pgbouncer
275+
args:
276+
PGBOUNCER_VERSION: ${PGBOUNCER_VERSION:-latest}
274277
container_name: dev-pgbouncer
275278
restart: unless-stopped
276279

@@ -336,7 +339,7 @@ services:
336339

337340
mysql:
338341
<<: *default-platform
339-
image: mysql:8.0.40
342+
image: mysql:${MYSQL_VERSION:-8.0.40}
340343
container_name: dev-mysql
341344
restart: unless-stopped
342345

@@ -527,7 +530,7 @@ services:
527530

528531
rabbitmq:
529532
<<: *default-platform
530-
image: rabbitmq:3.13-management-alpine
533+
image: rabbitmq:${RABBITMQ_VERSION:-3.13-management-alpine}
531534
container_name: dev-rabbitmq
532535
restart: unless-stopped
533536

@@ -591,7 +594,7 @@ services:
591594

592595
mongodb:
593596
<<: *default-platform
594-
image: mongo:7.0
597+
image: mongo:${MONGODB_VERSION:-7.0}
595598
container_name: dev-mongodb
596599
restart: unless-stopped
597600

@@ -658,7 +661,10 @@ services:
658661

659662
forgejo:
660663
<<: *default-platform
661-
build: ./configs/forgejo
664+
build:
665+
context: ./configs/forgejo
666+
args:
667+
FORGEJO_VERSION: ${FORGEJO_VERSION:-1.21.11-0}
662668
container_name: dev-forgejo
663669
restart: unless-stopped
664670

@@ -731,7 +737,7 @@ services:
731737

732738
vault:
733739
<<: *default-platform
734-
image: hashicorp/vault:1.18
740+
image: hashicorp/vault:${VAULT_VERSION:-1.18}
735741
container_name: dev-vault
736742
restart: unless-stopped
737743

@@ -1147,7 +1153,7 @@ services:
11471153

11481154
prometheus:
11491155
<<: *default-platform
1150-
image: prom/prometheus:v2.48.0
1156+
image: prom/prometheus:${PROMETHEUS_VERSION:-v2.48.0}
11511157
container_name: dev-prometheus
11521158
restart: unless-stopped
11531159

@@ -1207,7 +1213,7 @@ services:
12071213

12081214
grafana:
12091215
<<: *default-platform
1210-
image: grafana/grafana:10.2.2
1216+
image: grafana/grafana:${GRAFANA_VERSION:-10.2.2}
12111217
container_name: dev-grafana
12121218
restart: unless-stopped
12131219

@@ -1267,7 +1273,7 @@ services:
12671273

12681274
loki:
12691275
<<: *default-platform
1270-
image: grafana/loki:2.9.3
1276+
image: grafana/loki:${LOKI_VERSION:-2.9.3}
12711277
container_name: dev-loki
12721278
restart: unless-stopped
12731279

@@ -1402,7 +1408,7 @@ services:
14021408

14031409
cadvisor:
14041410
<<: *default-platform
1405-
image: gcr.io/cadvisor/cadvisor:v0.47.2
1411+
image: gcr.io/cadvisor/cadvisor:${CADVISOR_VERSION:-v0.47.2}
14061412
container_name: dev-cadvisor
14071413
restart: unless-stopped
14081414

@@ -1458,7 +1464,10 @@ services:
14581464

14591465
vector:
14601466
<<: *default-platform
1461-
build: ./configs/vector
1467+
build:
1468+
context: ./configs/vector
1469+
args:
1470+
VECTOR_VERSION: ${VECTOR_VERSION:-0.50.0-debian}
14621471
container_name: dev-vector
14631472
restart: unless-stopped
14641473

0 commit comments

Comments
 (0)