From 0be6dbc8241c2382fe5b78eff1bc0eddf1036cb2 Mon Sep 17 00:00:00 2001 From: Derek Roberts Date: Fri, 9 Oct 2026 23:56:55 -0700 Subject: [PATCH 1/2] ci: smoke-test docker-compose.yml on pull requests Bring the compose stack up and check the API health endpoint, the frontend and its /api proxy, and mongo-express. Fix the stack so it starts: the frontend was missing LOG_LEVEL and BACKEND_URL, and the API image's curl healthcheck can't run in its distroless image. --- .github/workflows/pr-open.yml | 41 ++++++++++++++++++++++++++++++++++- docker-compose.yml | 25 ++++++++++++++++++--- 2 files changed, 62 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pr-open.yml b/.github/workflows/pr-open.yml index d596532..f54546c 100644 --- a/.github/workflows/pr-open.yml +++ b/.github/workflows/pr-open.yml @@ -76,11 +76,50 @@ jobs: with: target: ${{ github.event.number }} + compose: + name: Docker Compose + runs-on: ubuntu-26.04 + timeout-minutes: 15 + permissions: + contents: read + steps: + - uses: actions/checkout@v7 + - uses: actions/setup-node@v7 + with: + node-version: "24.x" + + # docker-compose.yml serves frontend/dist from the host + - name: Build frontend + working-directory: frontend + run: npm ci --ignore-scripts && npm run build + + - name: Start stack + run: docker compose up --build --detach --wait --wait-timeout 300 + + - name: Smoke test + run: | + set -euo pipefail + curl -fsS --retry 5 --retry-all-errors --retry-delay 3 http://localhost:3005/api/pub-code/health + curl -fsS --retry 5 --retry-all-errors --retry-delay 3 http://localhost:3002/ | grep -q '
' + curl -fsS --retry 5 --retry-all-errors --retry-delay 3 http://localhost:3002/api/pub-code/health + # mongo-express may answer 401 (basic auth); anything below 500 means it's up + code=$(curl -sS --retry 5 --retry-all-errors --retry-delay 3 -o /dev/null -w '%{http_code}' http://localhost:8001/) + echo "mongo-express: HTTP ${code}" + [ "${code}" -lt 500 ] + + - name: Logs + if: failure() + run: docker compose logs + + - name: Stop stack + if: always() + run: docker compose down -v + # This job is the merge gate for this workflow. Every job in this # workflow must be listed in 'needs', or its failure won't block the PR. results: name: PR Results - needs: [builds, deploys, tests] + needs: [builds, compose, deploys, tests] if: always() runs-on: ubuntu-26.04 timeout-minutes: 1 diff --git a/docker-compose.yml b/docker-compose.yml index 8dcf8e9..c29b13e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -11,6 +11,11 @@ services: image: ghcr.io/bcgov/nr-containers/mongo:7.0.43 ports: ["27017:27017"] restart: unless-stopped + healthcheck: + test: ["CMD", "mongosh", "--quiet", "--eval", "db.adminCommand({ ping: 1 })"] + interval: 5s + timeout: 5s + retries: 20 mongo-express: # The admin UI container for mongoDB image: mongo-express @@ -27,7 +32,7 @@ services: ME_CONFIG_MONGODB_URL: mongodb://admin:DPEPGHbjUluRjetU@database:27017/ depends_on: database: - condition: service_started + condition: service_healthy api: image: pub-code-api:latest @@ -41,20 +46,34 @@ services: ports: - "3005:3000" restart: unless-stopped + # The image is distroless (no curl), so check with Node instead + healthcheck: + test: ["CMD", "/nodejs/bin/node", "-e", "fetch('http://localhost:3000/').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))"] + interval: 5s + timeout: 5s + retries: 20 depends_on: database: - condition: service_started + condition: service_healthy #Run npm run build-watch in local before this. frontend: image: caddy:2.11.7-alpine working_dir: /app + environment: + BACKEND_URL: http://api:3000 + LOG_LEVEL: info volumes: - ./frontend/Caddyfile:/etc/caddy/Caddyfile - ./frontend/dist:/app/dist + healthcheck: + test: ["CMD", "wget", "-qO-", "http://localhost:3001/health"] + interval: 5s + timeout: 5s + retries: 20 depends_on: api: - condition: service_started + condition: service_healthy ports: - "3002:3000" restart: unless-stopped From ffee18801bec6f6723fbd7d22bcd8a52fb146fc8 Mon Sep 17 00:00:00 2001 From: Derek Roberts Date: Sat, 10 Oct 2026 00:01:45 -0700 Subject: [PATCH 2/2] fix(compose): give the API placeholder CHES settings so it starts The API exits at startup when CHES settings are missing, so the compose stack never came up. Default them to placeholders that can be overridden from the shell. --- docker-compose.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docker-compose.yml b/docker-compose.yml index c29b13e..6ee92a4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -43,6 +43,12 @@ services: DB_USER: admin DB_PWD: DPEPGHbjUluRjetU DB_NAME: pubcode + # The API won't start without CHES settings. These placeholders let it + # start; set real values in your shell to send email locally. + CHES_TOKEN_URL: ${CHES_TOKEN_URL:-http://localhost/ches/token} + CHES_CLIENT_ID: ${CHES_CLIENT_ID:-placeholder} + CHES_CLIENT_SECRET: ${CHES_CLIENT_SECRET:-placeholder} + CHES_API_URL: ${CHES_API_URL:-http://localhost/ches} ports: - "3005:3000" restart: unless-stopped