Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
147 changes: 147 additions & 0 deletions .github/workflows/gateway-integration-test-sqlserver.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
name: Gateway Integration Test (SQL Server)

on:
workflow_dispatch:
pull_request:
branches:
- main
paths:
- 'gateway/**'
- 'common/**'
- 'tests/mock-servers/mock-platform-api/**'
- '.github/workflows/gateway-integration-test-sqlserver.yml'

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true

jobs:
integration-test:
runs-on: ubuntu-24.04
env:
# Used for both Compose interpolation and the runner-side sqlcmd checks below.
MSSQL_SA_PASSWORD: Gateway_Strong!Pass123
steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false

- name: Set up Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
with:
go-version: '1.26.2'
cache-dependency-path: '**/go.sum'

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0

- name: Build coverage-instrumented images
run: |
cd gateway
make build-coverage VERSION=test

- name: Build mock server images
run: |
for mock in mock-jwks mock-azure-content-safety mock-aws-bedrock-guardrail mock-embedding-provider mock-analytics-collector; do
echo "Building $mock..."
docker build -t ghcr.io/wso2/api-platform/$mock:latest tests/mock-servers/$mock
done

- name: Build sample-service
run: |
cd samples/sample-service
make build

- name: Verify gateway-controller uses SQL Server
run: |
set -euo pipefail
cd gateway/it

PROJECT="gateway-it-sqlserver-verify"
cleanup() {
docker compose -p "$PROJECT" -f docker-compose.test.sqlserver.yaml down -v --remove-orphans || true
}
trap cleanup EXIT

docker compose -p "$PROJECT" -f docker-compose.test.sqlserver.yaml up -d sqlserver mssql-init gateway-controller

timeout 120 bash -c 'until curl -fsS http://localhost:9092/api/admin/v0.9/health >/dev/null 2>&1; do sleep 2; done' || {
echo "=== Health check timed out — gateway-controller logs ==="
docker logs it-gateway-controller 2>&1 || true
exit 1
}

# Dump controller logs on any subsequent failure so the cause is never hidden
# by the cleanup trap (otherwise an assertion failure tears everything down silently).
dump_logs() {
echo "=== gateway-controller logs ==="
docker logs it-gateway-controller 2>&1 || true
}
trap 'dump_logs; cleanup' EXIT

docker logs it-gateway-controller > /tmp/gateway-controller.log 2>&1 || true
grep -Eq "Initializing SQLServer schema|SQLServer schema initialized" /tmp/gateway-controller.log

table_count="$(docker compose -p "$PROJECT" -f docker-compose.test.sqlserver.yaml exec -T sqlserver \
/opt/mssql-tools18/bin/sqlcmd -C -S localhost -U sa -P "$MSSQL_SA_PASSWORD" -d gateway_test -h -1 -W \
-Q "SET NOCOUNT ON; SELECT COUNT(*) FROM information_schema.tables WHERE table_name = 'artifacts'" | tr -d '[:space:]')"
echo "artifacts table_count=$table_count"
[ "$table_count" = "1" ]

# The controller's DSN sets 'app name=gateway-controller', so its sessions are
# tagged accordingly in sys.dm_exec_sessions (SQL Server's analog of pg_stat_activity).
conn_count="$(docker compose -p "$PROJECT" -f docker-compose.test.sqlserver.yaml exec -T sqlserver \
/opt/mssql-tools18/bin/sqlcmd -C -S localhost -U sa -P "$MSSQL_SA_PASSWORD" -d gateway_test -h -1 -W \
-Q "SET NOCOUNT ON; SELECT COUNT(*) FROM sys.dm_exec_sessions WHERE program_name = 'gateway-controller'" | tr -d '[:space:]')"
echo "gateway-controller conn_count=$conn_count"
[ "${conn_count:-0}" -ge 1 ]

- name: Run integration tests
run: |
cd gateway
COMPOSE_FILE=docker-compose.test.sqlserver.yaml make test-integration

- name: Upload coverage report
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: always()
with:
name: coverage-report-sqlserver
path: gateway/it/coverage/output
retention-days: 7

- name: Upload test reports
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
if: always()
with:
name: test-reports-sqlserver
path: gateway/it/reports/
retention-days: 7

- name: Debug on failure - Dump logs
if: failure()
run: |
echo "=== Docker Containers ==="
docker ps -a

for ctr in it-gateway-controller it-gateway-runtime it-sqlserver it-mock-platform-api; do
echo ""
echo "=== Docker logs: $ctr ==="
docker logs "$ctr" 2>&1 || echo "(container $ctr not found)"
done

echo ""
echo "=== gateway/it/logs Directory Contents ==="
if [ -d gateway/it/logs ]; then
if [ "$(ls -A gateway/it/logs)" ]; then
for f in gateway/it/logs/*; do
echo ""
echo "--- Contents of $f ---"
cat "$f"
done
else
echo "No log files found in gateway/it/logs."
fi
else
echo "Directory gateway/it/logs does not exist."
fi
5 changes: 3 additions & 2 deletions .github/workflows/operator-integration-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -323,9 +323,10 @@ jobs:

# Storage configuration
storage:
# Storage type: "sqlite", "postgres" (future), or "memory"
# Storage type: "sqlite", "postgres", "sqlserver", or "memory"
# - sqlite: Use SQLite embedded database for persistence
# - postgres: Use PostgreSQL database for persistence (future support)
# - postgres: Use PostgreSQL database for persistence
# - sqlserver: Use SQL Server database for persistence
# - memory: No persistent storage, all configs lost on restart (useful for testing)
type: sqlite

Expand Down
61 changes: 61 additions & 0 deletions .github/workflows/platform-api-gateway-e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: Platform API + Gateway E2E

# Combined live-traffic end-to-end test: the real platform-api control plane
# deploys an API to the real gateway data plane, and a request through the
# gateway ingress must reach the sample backend — exercised on every database.
#
# This builds the gateway (Envoy) images, so it is intentionally not on the
# per-PR critical path: it runs on demand and when the e2e itself changes.
on:
workflow_dispatch:
pull_request:
branches:
- main
paths:
- 'tests/integration-e2e/**'
- '.github/workflows/platform-api-gateway-e2e.yml'

permissions:
contents: read

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true

jobs:
Comment thread
coderabbitai[bot] marked this conversation as resolved.
e2e:
runs-on: ubuntu-24.04
strategy:
fail-fast: false
matrix:
db: [sqlite, postgres, sqlserver]
steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false

- name: Set up Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
with:
go-version: '1.26.2'
cache-dependency-path: '**/go.sum'

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0

- name: Build platform-api image
run: docker build -t platform-api:it-e2e --build-context common=../common .
working-directory: platform-api

- name: Build gateway images (controller + runtime)
run: make build VERSION=it-e2e
working-directory: gateway

- name: Build sample-service image
run: make build
working-directory: samples/sample-service

- name: Run combined e2e (${{ matrix.db }})
run: E2E_DB=${{ matrix.db }} go test -run TestFeatures -count=1 -v -timeout 25m ./...
working-directory: tests/integration-e2e
100 changes: 98 additions & 2 deletions .github/workflows/platform-api-pr-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,20 @@ concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true

permissions:
contents: read

jobs:
pr-check:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false

- name: Set up Go
uses: actions/setup-go@v5
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
with:
go-version: '1.26.2'
cache-dependency-path: '**/go.sum'
Expand All @@ -33,3 +38,94 @@ jobs:
- name: Run tests
run: make test
working-directory: platform-api

- name: Cross-database integration tests (SQLite)
run: IT_DB=sqlite go test -tags integration -count=1 ./internal/integration/...
working-directory: platform-api/src

pr-check-postgres:
runs-on: ubuntu-24.04
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: platform_api_it
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U postgres -d platform_api_it"
--health-interval 2s --health-timeout 3s --health-retries 30
env:
IT_DB: postgres
IT_DB_HOST: localhost
IT_DB_PORT: 5432
IT_DB_USER: postgres
IT_DB_PASSWORD: postgres
IT_DB_NAME: platform_api_it
steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false

- name: Set up Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
with:
go-version: '1.26.2'
cache-dependency-path: '**/go.sum'
Comment thread
coderabbitai[bot] marked this conversation as resolved.

- name: Cross-database integration tests (PostgreSQL)
run: go test -tags integration -count=1 -v ./internal/integration/...
working-directory: platform-api/src

pr-check-sqlserver:
runs-on: ubuntu-24.04
env:
IT_DB: sqlserver
IT_DB_HOST: 127.0.0.1
IT_DB_PORT: 1433
IT_DB_USER: sa
IT_DB_NAME: platform_api_it
steps:
- name: Checkout code
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1
with:
persist-credentials: false

- name: Set up Go
uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0
with:
go-version: '1.26.2'
cache-dependency-path: '**/go.sum'

- name: Start SQL Server
run: |
set -euo pipefail

# Generate the SA password at runtime instead of using a committed
# literal or a stored secret. A runtime value avoids secret-scanner
# false positives and secret-handling pitfalls (e.g. a stray trailing
# newline) that silently fail SQL Server's password policy at init.
SA_PASSWORD="Aa1$(openssl rand -hex 16)"
echo "::add-mask::$SA_PASSWORD"
echo "IT_DB_PASSWORD=$SA_PASSWORD" >> "$GITHUB_ENV"

docker run -d --name sqlserver \
-e ACCEPT_EULA=Y \
-e MSSQL_PID=Developer \
-e MSSQL_SA_PASSWORD="$SA_PASSWORD" \
-p 1433:1433 \
mcr.microsoft.com/mssql/server:2022-latest

- name: Build with SQL Server configuration
run: go build ./cmd/main.go
working-directory: platform-api/src

# The harness waits for the server and creates the test database itself,
# then exercises the real schema, pagination and delete cascades against
# SQL Server (the previous `make test` step here only ran SQLite).
- name: Cross-database integration tests (SQL Server)
run: go test -tags integration -count=1 -v ./internal/integration/...
working-directory: platform-api/src
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Loading
Loading