From 8fe7d81e57fdfa37f5e19d5e280336444f701f60 Mon Sep 17 00:00:00 2001 From: Chris Coutinho Date: Fri, 27 Feb 2026 20:35:47 +0100 Subject: [PATCH] ci: use matrix strategy for deployment mode integration tests Replace the single integration-test job with a matrix that tests each deployment mode independently using Docker Compose profiles: - single-user: smoke + integration tests (port 8000) - oauth: OAuth flow tests with Playwright (port 8001) - login-flow: Login Flow v2 tests with Playwright (port 8004) Unit tests run separately without Docker. OIDC app build and Playwright install are conditional based on the mode. Service logs are captured on failure for debugging. Co-Authored-By: Claude Opus 4.6 --- .github/workflows/test.yml | 113 ++++++++++++++++++++++++++++--------- 1 file changed, 85 insertions(+), 28 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 960b180..ac3e535 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,4 +1,4 @@ -name: Docker Compose Action +name: Tests on: pull_request: @@ -13,76 +13,133 @@ jobs: - name: Install the latest version of uv uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0 - name: Check format - run: | - uv run --frozen ruff format --diff + run: uv run --frozen ruff format --diff - name: Linting - run: | - uv run --frozen ruff check - - name: Linting - run: | - uv run --frozen ty check -- nextcloud_mcp_server + run: uv run --frozen ruff check + - name: Type check + run: uv run --frozen ty check -- nextcloud_mcp_server + unit-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: Install the latest version of uv + uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0 + - name: Run unit tests + run: uv run pytest -v -m unit -o "addopts=-p no:asyncio" integration-test: runs-on: ubuntu-latest + needs: [linting, unit-test] + strategy: + fail-fast: false + matrix: + include: + - mode: single-user + profile: single-user + markers: "smoke or (integration and not oauth and not keycloak and not login_flow)" + wait-port: 8000 + needs-oidc: false + needs-playwright: false + + - mode: oauth + profile: oauth + markers: "oauth and not keycloak" + wait-port: 8001 + needs-oidc: true + needs-playwright: true + + - mode: login-flow + profile: login-flow + markers: "login_flow" + wait-port: 8004 + needs-oidc: true + needs-playwright: true + + name: integration (${{ matrix.mode }}) steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - submodules: 'true' + submodules: ${{ matrix.needs-oidc && 'true' || 'false' }} - - ###### Required to build OIDC App ###### - - - name: Set up php 8.4 + # Build OIDC app (required for OAuth and Login Flow modes) + - name: Set up PHP 8.4 + if: matrix.needs-oidc uses: shivammathur/setup-php@44454db4f0199b8b9685a5d763dc37cbf79108e1 # 2.36.0 with: php-version: 8.4 coverage: none - name: Install OIDC app composer dependencies + if: matrix.needs-oidc run: | cd third_party/oidc composer install --no-dev - ###### Required to build OIDC App ###### - - + # Start services with the appropriate profile - name: Run docker compose uses: hoverkraft-tech/compose-action@4894d2492015c1774ee5a13a95b1072093087ec3 # v2.5.0 with: compose-file: "./docker-compose.yml" - #compose-flags: "--profile qdrant" + compose-flags: "--profile ${{ matrix.profile }}" up-flags: "--build" - name: Install the latest version of uv uses: astral-sh/setup-uv@eac588ad8def6316056a12d4907a9d4d84ff7a3b # v7.3.0 - - name: Install Playwright dependencies - run: | - uv run playwright install chromium --with-deps + - name: Install Playwright + if: matrix.needs-playwright + run: uv run playwright install chromium --with-deps - - name: Wait for service to be ready + # Wait for Nextcloud to be healthy + - name: Wait for Nextcloud run: | - echo "Waiting for service at http://localhost:8080/ocs/v2.php/apps/serverinfo/api/v1/info to return 401..." + echo "Waiting for Nextcloud at http://localhost:8080..." max_attempts=60 attempt=0 until curl -o /dev/null -s -w "%{http_code}\n" http://localhost:8080/ocs/v2.php/apps/serverinfo/api/v1/info | grep -q "401"; do attempt=$((attempt + 1)) if [ $attempt -ge $max_attempts ]; then - echo "Service did not become ready in time." + echo "Nextcloud did not become ready in time." + docker compose logs app exit 1 fi - echo "Attempt $attempt/$max_attempts: Service not ready, sleeping for 5 seconds..." + echo "Attempt $attempt/$max_attempts: Not ready, sleeping 5s..." sleep 5 done - echo "Service is ready (returned 401)." + echo "Nextcloud is ready." - # Add subsequent steps here, e.g., running tests - - name: Run tests + # Wait for the MCP service to be healthy + - name: Wait for MCP service (${{ matrix.mode }}) + run: | + echo "Waiting for MCP service on port ${{ matrix.wait-port }}..." + max_attempts=30 + attempt=0 + until curl -o /dev/null -s -w "%{http_code}\n" http://localhost:${{ matrix.wait-port }}/health 2>/dev/null | grep -qE "200|404|405"; do + attempt=$((attempt + 1)) + if [ $attempt -ge $max_attempts ]; then + echo "MCP service did not become ready in time." + docker compose --profile ${{ matrix.profile }} logs + exit 1 + fi + echo "Attempt $attempt/$max_attempts: Not ready, sleeping 5s..." + sleep 5 + done + echo "MCP service is ready on port ${{ matrix.wait-port }}." + + - name: Run tests (${{ matrix.mode }}) env: NEXTCLOUD_HOST: "http://localhost:8080" NEXTCLOUD_USERNAME: "admin" NEXTCLOUD_PASSWORD: "admin" run: | - uv run pytest -v --log-cli-level=WARN -m unit -m smoke + uv run pytest -v \ + --log-cli-level=WARN \ + -m '${{ matrix.markers }}' \ + -o "addopts=-p no:asyncio" \ + --timeout=300 + + - name: Show service logs on failure + if: failure() + run: docker compose --profile ${{ matrix.profile }} logs --tail=100