name: Test on: workflow_call: jobs: build-and-test: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v4 # The test image below swaps in Caddyfile.test, so the production # Caddyfile is otherwise never exercised by CI — an invalid config then # only surfaces when the deploy health-gate fails, after the broken # container already replaced the healthy one (issue #20/#26). Validate # both files up front so a parse error fails the PR check in seconds. - name: Validate Caddyfiles run: | docker run --rm -v "$PWD":/workspace -w /workspace caddy:2-alpine \ caddy validate --config Caddyfile --adapter caddyfile docker run --rm -v "$PWD":/workspace -w /workspace caddy:2-alpine \ caddy validate --config Caddyfile.test --adapter caddyfile - name: Build Docker image run: docker build -t learning-platform . - name: Build test image run: | cat > Dockerfile.test <<'EOF' FROM learning-platform COPY Caddyfile.test /etc/caddy/Caddyfile EOF docker build -t learning-platform-test -f Dockerfile.test . - name: Start container run: | docker run -d --network gitea --name test-container learning-platform-test sleep 5 - name: Test homepage run: | status=$(curl -s -o /dev/null -w "%{http_code}" http://test-container) if [ "$status" != "200" ]; then echo "Homepage failed with status $status" exit 1 fi echo "✓ Homepage OK" - name: Test security headers run: | headers=$(curl -sI http://test-container) echo "$headers" | grep -q "X-Frame-Options" || (echo "Missing X-Frame-Options" && exit 1) echo "$headers" | grep -q "X-Content-Type-Options" || (echo "Missing X-Content-Type-Options" && exit 1) echo "✓ Security headers OK" - name: Cleanup if: always() run: docker stop test-container && docker rm test-container