Integration testing #3
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Tests | |
| on: | |
| push: | |
| branches: [ main, develop ] | |
| pull_request: | |
| branches: [ main, develop ] | |
| jobs: | |
| # Unit tests - fast, no external dependencies | |
| unit-tests: | |
| name: Unit Tests (Python ${{ matrix.python-version }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| python-version: ["3.9", "3.10", "3.11", "3.12"] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python ${{ matrix.python-version }} | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: ${{ matrix.python-version }} | |
| - name: Cache pip packages | |
| uses: actions/cache@v3 | |
| with: | |
| path: ~/.cache/pip | |
| key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml') }} | |
| restore-keys: | | |
| ${{ runner.os }}-pip- | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e . | |
| pip install pytest pytest-cov pytest-mock | |
| - name: Run unit tests | |
| run: | | |
| pytest tests/ -v -m "not integration and not e2e" \ | |
| --cov=src/openshift_ai_auth \ | |
| --cov-report=xml \ | |
| --cov-report=term-missing | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@v3 | |
| with: | |
| files: ./coverage.xml | |
| flags: unittests | |
| name: codecov-${{ matrix.python-version }} | |
| # Integration tests - use mock OAuth server | |
| integration-tests: | |
| name: Integration Tests | |
| runs-on: ubuntu-latest | |
| needs: unit-tests | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.11 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e . | |
| pip install pytest pytest-cov pytest-mock requests | |
| - name: Run integration tests with mock server | |
| run: | | |
| pytest tests/integration/ -v -m integration \ | |
| --cov=src/openshift_ai_auth \ | |
| --cov-report=xml \ | |
| --cov-report=term-missing | |
| - name: Upload integration coverage | |
| uses: codecov/codecov-action@v3 | |
| with: | |
| files: ./coverage.xml | |
| flags: integration | |
| name: codecov-integration | |
| # E2E tests with real Keycloak (optional, slower) | |
| e2e-tests: | |
| name: End-to-End Tests | |
| runs-on: ubuntu-latest | |
| needs: integration-tests | |
| if: github.event_name == 'push' || github.event.pull_request.draft == false | |
| services: | |
| keycloak: | |
| image: quay.io/keycloak/keycloak:23.0 | |
| env: | |
| KEYCLOAK_ADMIN: admin | |
| KEYCLOAK_ADMIN_PASSWORD: admin | |
| KC_HTTP_ENABLED: "true" | |
| KC_HOSTNAME_STRICT: "false" | |
| KC_HOSTNAME_STRICT_HTTPS: "false" | |
| ports: | |
| - 8080:8080 | |
| options: >- | |
| --health-cmd "curl -f http://localhost:8080/health/ready || exit 1" | |
| --health-interval 10s | |
| --health-timeout 5s | |
| --health-retries 30 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.11 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install dependencies | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install -e . | |
| pip install pytest pytest-mock requests | |
| - name: Wait for Keycloak | |
| run: | | |
| echo "Waiting for Keycloak to be ready..." | |
| timeout 120 bash -c 'until curl -f http://localhost:8080/health/ready; do sleep 2; done' | |
| - name: Configure Keycloak test realm | |
| run: | | |
| # Get admin token | |
| TOKEN=$(curl -X POST 'http://localhost:8080/realms/master/protocol/openid-connect/token' \ | |
| -H 'Content-Type: application/x-www-form-urlencoded' \ | |
| -d 'username=admin' \ | |
| -d 'password=admin' \ | |
| -d 'grant_type=password' \ | |
| -d 'client_id=admin-cli' \ | |
| | jq -r '.access_token') | |
| # Create test realm | |
| curl -X POST 'http://localhost:8080/admin/realms' \ | |
| -H "Authorization: Bearer $TOKEN" \ | |
| -H 'Content-Type: application/json' \ | |
| -d '{ | |
| "realm": "test", | |
| "enabled": true | |
| }' | |
| # Create test client | |
| curl -X POST 'http://localhost:8080/admin/realms/test/clients' \ | |
| -H "Authorization: Bearer $TOKEN" \ | |
| -H 'Content-Type: application/json' \ | |
| -d '{ | |
| "clientId": "test-client", | |
| "enabled": true, | |
| "publicClient": false, | |
| "secret": "test-secret", | |
| "redirectUris": ["http://localhost:8080/*"], | |
| "standardFlowEnabled": true, | |
| "directAccessGrantsEnabled": true, | |
| "serviceAccountsEnabled": true | |
| }' | |
| - name: Run E2E tests | |
| env: | |
| OIDC_ISSUER: http://localhost:8080/realms/test | |
| OIDC_CLIENT_ID: test-client | |
| OIDC_CLIENT_SECRET: test-secret | |
| run: | | |
| pytest tests/ -v -m e2e --tb=short | |
| # Lint and format checks | |
| lint: | |
| name: Lint & Format | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Python 3.11 | |
| uses: actions/setup-python@v5 | |
| with: | |
| python-version: "3.11" | |
| - name: Install linting tools | |
| run: | | |
| python -m pip install --upgrade pip | |
| pip install ruff mypy | |
| - name: Run ruff | |
| run: | | |
| ruff check src/ tests/ | |
| - name: Run mypy | |
| run: | | |
| mypy src/openshift_ai_auth --ignore-missing-imports | |
| continue-on-error: true # Don't fail build on type errors yet | |
| # Security scanning | |
| security: | |
| name: Security Scan | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Run Trivy vulnerability scanner | |
| uses: aquasecurity/trivy-action@master | |
| with: | |
| scan-type: 'fs' | |
| scan-ref: '.' | |
| format: 'sarif' | |
| output: 'trivy-results.sarif' | |
| - name: Upload Trivy results to GitHub Security | |
| uses: github/codeql-action/upload-sarif@v2 | |
| with: | |
| sarif_file: 'trivy-results.sarif' |