diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3500152..d2cf56d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -134,6 +134,34 @@ jobs: TRIVY_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-db TRIVY_JAVA_DB_REPOSITORY: public.ecr.aws/aquasecurity/trivy-java-db + compose-smoke: + name: Compose smoke + runs-on: ubuntu-latest + needs: build-test + + permissions: + contents: read + + # Step order is load-bearing: smoke -> logs (on failure) -> teardown (always). + # `docker compose down` removes containers, so logs must be dumped before it. + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Bring up stack + run: docker compose up -d --build --wait --wait-timeout 90 + + - name: Smoke (readiness < 30s, public surface served) + run: bash scripts/demo.sh + + - name: Dump container logs on failure + if: failure() + run: docker compose logs --no-color + + - name: Tear down stack + if: always() + run: docker compose down -v + lint-security: name: Security Scan runs-on: ubuntu-latest diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..e3d9a14 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,26 @@ +services: + postgres: + image: postgres:17-alpine + environment: + POSTGRES_DB: ledger + POSTGRES_USER: ledger + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-ledger} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ledger -d ledger"] + interval: 2s + timeout: 3s + retries: 10 + start_period: 5s + + ledger: + build: . + depends_on: + postgres: + condition: service_healthy + ports: + - "8080:8080" + environment: + SPRING_DATASOURCE_URL: jdbc:postgresql://postgres:5432/ledger + SPRING_DATASOURCE_USERNAME: ledger + SPRING_DATASOURCE_PASSWORD: ${POSTGRES_PASSWORD:-ledger} + KEYCLOAK_ISSUER_URI: http://localhost/realms/fincore diff --git a/scripts/demo.sh b/scripts/demo.sh new file mode 100755 index 0000000..036d7b1 --- /dev/null +++ b/scripts/demo.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +set -euo pipefail + +BASE_URL="${1:-http://localhost:8080}" +READINESS="$BASE_URL/actuator/health/readiness" +LIVENESS="$BASE_URL/actuator/health/liveness" +API_DOCS="$BASE_URL/v3/api-docs" + +attempts=15 +interval=2 + +ready=false +for i in $(seq 1 "$attempts"); do + if curl -fsS -o /dev/null "$READINESS"; then + ready=true + break + fi + [ "$i" -lt "$attempts" ] && sleep "$interval" +done + +if [ "$ready" != true ]; then + echo "FAIL: ledger readiness not UP within $((attempts * interval))s at $READINESS" + exit 1 +fi + +if ! curl -fsS -o /dev/null "$LIVENESS"; then + echo "FAIL: ledger liveness not UP at $LIVENESS" + exit 1 +fi + +code=$(curl -sS -o /dev/null -w '%{http_code}' "$API_DOCS") +if [ "$code" != "200" ]; then + echo "FAIL: api-docs returned $code at $API_DOCS" + exit 1 +fi + +echo "ledger smoke OK: readiness UP, liveness UP, api-docs 200"