chore(deps): update dependency hypothesis to v6.167.1 #195
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: CI Pipeline | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| workflow_dispatch: | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| env: | |
| PYTHON_VERSION: "3.14" | |
| PYTHONDONTWRITEBYTECODE: 1 | |
| FORCE_COLOR: 1 | |
| jobs: | |
| # ============================================================================ | |
| # STAGE 1: Code Quality Gates (fail-fast) | |
| # ============================================================================ | |
| lint: | |
| name: Lint and Type Check | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v7 | |
| with: | |
| ref: ${{ github.head_ref }} | |
| - name: Set up Python ${{ env.PYTHON_VERSION }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install Poetry | |
| uses: snok/install-poetry@v1 | |
| with: | |
| version: latest | |
| virtualenvs-create: true | |
| virtualenvs-in-project: true | |
| - name: Cache Poetry dependencies | |
| uses: actions/cache@v5 | |
| with: | |
| path: .venv | |
| key: venv-lint-${{ runner.os }}-${{ env.PYTHON_VERSION }}-${{ hashFiles('**/poetry.lock') }} | |
| restore-keys: | | |
| venv-lint-${{ runner.os }}-${{ env.PYTHON_VERSION }}- | |
| - name: Install dependencies | |
| run: poetry install --only dev --no-interaction | |
| - name: Lint with Ruff | |
| run: poetry run ruff check . | |
| - name: Auto-format with Ruff | |
| if: github.event_name == 'pull_request' | |
| run: | | |
| poetry run ruff format . | |
| if ! git diff --quiet; then | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git commit -am "style: auto-format with ruff" | |
| git push | |
| fi | |
| - name: Check code formatting with Ruff | |
| run: poetry run ruff format --check --diff . | |
| - name: Type checking with mypy | |
| run: poetry run mypy app/ | |
| # ============================================================================ | |
| # STAGE 2: Test Matrix (parallel execution) | |
| # ============================================================================ | |
| test-unit: | |
| name: Unit Tests | |
| runs-on: ubuntu-latest | |
| needs: lint | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v7 | |
| - name: Set up Python ${{ env.PYTHON_VERSION }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install Poetry | |
| uses: snok/install-poetry@v1 | |
| with: | |
| version: latest | |
| virtualenvs-create: true | |
| virtualenvs-in-project: true | |
| - name: Cache Poetry dependencies | |
| uses: actions/cache@v5 | |
| with: | |
| path: .venv | |
| key: venv-${{ runner.os }}-${{ env.PYTHON_VERSION }}-${{ hashFiles('**/poetry.lock') }} | |
| restore-keys: | | |
| venv-${{ runner.os }}-${{ env.PYTHON_VERSION }}- | |
| - name: Install dependencies | |
| run: poetry install --with dev --no-interaction | |
| - name: Run unit tests | |
| run: | | |
| poetry run pytest tests/ \ | |
| -m "not integration and not slow and not benchmark and not property" \ | |
| --cov=app \ | |
| --cov-report= \ | |
| --cov-fail-under=0 \ | |
| --junitxml=test-results-unit.xml \ | |
| --benchmark-disable \ | |
| -n auto \ | |
| -v | |
| - name: Rename coverage data | |
| run: mv .coverage .coverage.unit | |
| - name: Upload coverage data | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: coverage-data-unit | |
| path: .coverage.unit | |
| include-hidden-files: true | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: test-results-unit | |
| path: test-results-unit.xml | |
| test-integration: | |
| name: Integration Tests | |
| runs-on: ubuntu-latest | |
| needs: lint | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v7 | |
| - name: Set up Python ${{ env.PYTHON_VERSION }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install Poetry | |
| uses: snok/install-poetry@v1 | |
| with: | |
| version: latest | |
| virtualenvs-create: true | |
| virtualenvs-in-project: true | |
| - name: Cache Poetry dependencies | |
| uses: actions/cache@v5 | |
| with: | |
| path: .venv | |
| key: venv-${{ runner.os }}-${{ env.PYTHON_VERSION }}-${{ hashFiles('**/poetry.lock') }} | |
| restore-keys: | | |
| venv-${{ runner.os }}-${{ env.PYTHON_VERSION }}- | |
| - name: Install dependencies | |
| run: poetry install --with dev --no-interaction | |
| - name: Run integration tests | |
| run: | | |
| poetry run pytest tests/ \ | |
| -m "integration" \ | |
| --cov=app \ | |
| --cov-report= \ | |
| --cov-fail-under=0 \ | |
| --junitxml=test-results-integration.xml \ | |
| -v | |
| - name: Rename coverage data | |
| run: mv .coverage .coverage.integration | |
| - name: Upload coverage data | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: coverage-data-integration | |
| path: .coverage.integration | |
| include-hidden-files: true | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: test-results-integration | |
| path: test-results-integration.xml | |
| test-security: | |
| name: Security Scan | |
| runs-on: ubuntu-latest | |
| needs: lint | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v7 | |
| - name: Set up Python ${{ env.PYTHON_VERSION }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install Poetry | |
| uses: snok/install-poetry@v1 | |
| with: | |
| version: latest | |
| virtualenvs-create: true | |
| virtualenvs-in-project: true | |
| - name: Cache Poetry dependencies | |
| uses: actions/cache@v5 | |
| with: | |
| path: .venv | |
| key: venv-${{ runner.os }}-${{ env.PYTHON_VERSION }}-${{ hashFiles('**/poetry.lock') }} | |
| restore-keys: | | |
| venv-${{ runner.os }}-${{ env.PYTHON_VERSION }}- | |
| - name: Install dependencies | |
| run: poetry install --only dev --no-interaction | |
| - name: Upgrade pip to patched version | |
| run: poetry run pip install --upgrade pip | |
| - name: Audit dependencies for known vulnerabilities | |
| run: poetry run pip-audit | |
| - name: Bandit security lint | |
| run: poetry run ruff check . --select S | |
| test-property: | |
| name: Property-Based Tests | |
| runs-on: ubuntu-latest | |
| needs: lint | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v7 | |
| - name: Set up Python ${{ env.PYTHON_VERSION }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install Poetry | |
| uses: snok/install-poetry@v1 | |
| with: | |
| version: latest | |
| virtualenvs-create: true | |
| virtualenvs-in-project: true | |
| - name: Cache Poetry dependencies | |
| uses: actions/cache@v5 | |
| with: | |
| path: .venv | |
| key: venv-${{ runner.os }}-${{ env.PYTHON_VERSION }}-${{ hashFiles('**/poetry.lock') }} | |
| restore-keys: | | |
| venv-${{ runner.os }}-${{ env.PYTHON_VERSION }}- | |
| - name: Install dependencies | |
| run: poetry install --with dev --no-interaction | |
| - name: Run property-based tests | |
| run: | | |
| poetry run pytest tests/ \ | |
| -m "property" \ | |
| --cov=app \ | |
| --cov-report= \ | |
| --cov-fail-under=0 \ | |
| --junitxml=test-results-property.xml \ | |
| -v | |
| - name: Rename coverage data | |
| run: mv .coverage .coverage.property | |
| - name: Upload coverage data | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: coverage-data-property | |
| path: .coverage.property | |
| include-hidden-files: true | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: test-results-property | |
| path: test-results-property.xml | |
| test-performance: | |
| name: Performance Tests | |
| runs-on: ubuntu-latest | |
| needs: lint | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v7 | |
| - name: Set up Python ${{ env.PYTHON_VERSION }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install Poetry | |
| uses: snok/install-poetry@v1 | |
| with: | |
| version: latest | |
| virtualenvs-create: true | |
| virtualenvs-in-project: true | |
| - name: Cache Poetry dependencies | |
| uses: actions/cache@v5 | |
| with: | |
| path: .venv | |
| key: venv-${{ runner.os }}-${{ env.PYTHON_VERSION }}-${{ hashFiles('**/poetry.lock') }} | |
| restore-keys: | | |
| venv-${{ runner.os }}-${{ env.PYTHON_VERSION }}- | |
| - name: Install dependencies | |
| run: poetry install --with dev --no-interaction | |
| - name: Run performance tests | |
| run: | | |
| poetry run pytest tests/ \ | |
| -m "benchmark or slow" \ | |
| --junitxml=test-results-performance.xml \ | |
| --timeout=120 \ | |
| --no-cov \ | |
| -v | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: test-results-performance | |
| path: test-results-performance.xml | |
| test-e2e: | |
| name: E2E Tests (Playwright) | |
| runs-on: ubuntu-latest | |
| needs: lint | |
| timeout-minutes: 25 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| browser: [chromium, firefox] | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v7 | |
| - name: Set up Python ${{ env.PYTHON_VERSION }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install Poetry | |
| uses: snok/install-poetry@v1 | |
| with: | |
| version: latest | |
| virtualenvs-create: true | |
| virtualenvs-in-project: true | |
| - name: Cache Poetry dependencies | |
| uses: actions/cache@v5 | |
| with: | |
| path: .venv | |
| key: venv-${{ runner.os }}-${{ env.PYTHON_VERSION }}-${{ hashFiles('**/poetry.lock') }} | |
| restore-keys: | | |
| venv-${{ runner.os }}-${{ env.PYTHON_VERSION }}- | |
| - name: Install dependencies | |
| run: poetry install --with dev --no-interaction | |
| - name: Install Playwright browser (${{ matrix.browser }}) | |
| run: poetry run playwright install ${{ matrix.browser }} --with-deps | |
| - name: Start Streamlit server | |
| run: poetry run streamlit run main.py --server.headless=true --server.port=8501 > /tmp/streamlit.log 2>&1 & | |
| - name: Wait for server to be ready | |
| run: | | |
| poetry run python - <<'EOF' | |
| import sys | |
| import time | |
| import urllib.error | |
| import urllib.request | |
| url = "http://localhost:8501" | |
| for attempt in range(30): | |
| try: | |
| urllib.request.urlopen(url, timeout=2) | |
| print(f"Server ready after {attempt + 1}s", flush=True) | |
| sys.exit(0) | |
| except (urllib.error.URLError, OSError): | |
| time.sleep(1) | |
| print("ERROR: Streamlit server did not start within 30 seconds.") | |
| sys.exit(1) | |
| EOF | |
| - name: Run E2E tests (${{ matrix.browser }}) | |
| run: | | |
| mkdir -p test-results-e2e-${{ matrix.browser }}/artifacts | |
| poetry run pytest tests/e2e/ \ | |
| -m "e2e" \ | |
| -p no:xdist \ | |
| --browser ${{ matrix.browser }} \ | |
| --screenshot only-on-failure \ | |
| --tracing retain-on-failure \ | |
| --output test-results-e2e-${{ matrix.browser }}/artifacts \ | |
| --junitxml=test-results-e2e-${{ matrix.browser }}.xml \ | |
| --html=test-results-e2e-${{ matrix.browser }}/report.html \ | |
| --self-contained-html \ | |
| --reruns 2 \ | |
| --reruns-delay 1 \ | |
| --only-rerun "TimeoutError|Page closed|Target closed" \ | |
| --timeout=60 \ | |
| -v | |
| - name: Link HTML report from job summary | |
| if: always() | |
| run: | | |
| echo "## E2E report — ${{ matrix.browser }}" >> "$GITHUB_STEP_SUMMARY" | |
| echo "Download \`test-results-e2e-${{ matrix.browser }}\` artifact and open \`report.html\`." >> "$GITHUB_STEP_SUMMARY" | |
| - name: Upload test results | |
| uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: test-results-e2e-${{ matrix.browser }} | |
| path: | | |
| test-results-e2e-${{ matrix.browser }}/ | |
| test-results-e2e-${{ matrix.browser }}.xml | |
| retention-days: 7 | |
| - name: Upload E2E artifacts on failure | |
| uses: actions/upload-artifact@v7 | |
| if: failure() | |
| with: | |
| name: e2e-artifacts-${{ matrix.browser }} | |
| path: | | |
| test-results-e2e-${{ matrix.browser }}/ | |
| /tmp/streamlit.log | |
| retention-days: 7 | |
| # ============================================================================ | |
| # STAGE 3: Coverage Report and Summary | |
| # ============================================================================ | |
| coverage-report: | |
| name: Coverage Report | |
| runs-on: ubuntu-latest | |
| needs: [test-unit, test-integration, test-security, test-property, test-performance, test-e2e] | |
| if: always() | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v7 | |
| - name: Set up Python ${{ env.PYTHON_VERSION }} | |
| uses: actions/setup-python@v7 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install Poetry | |
| uses: snok/install-poetry@v1 | |
| with: | |
| version: latest | |
| virtualenvs-create: true | |
| virtualenvs-in-project: true | |
| - name: Cache Poetry dependencies | |
| uses: actions/cache@v5 | |
| with: | |
| path: .venv | |
| key: venv-${{ runner.os }}-${{ env.PYTHON_VERSION }}-${{ hashFiles('**/poetry.lock') }} | |
| restore-keys: | | |
| venv-${{ runner.os }}-${{ env.PYTHON_VERSION }}- | |
| - name: Install dependencies | |
| run: poetry install --with dev --no-interaction | |
| - name: Download all coverage data | |
| uses: actions/download-artifact@v8 | |
| continue-on-error: true | |
| with: | |
| pattern: coverage-data-* | |
| merge-multiple: true | |
| path: . | |
| - name: Combine and generate coverage report | |
| run: | | |
| poetry run coverage combine | |
| poetry run coverage json | |
| poetry run coverage html | |
| poetry run coverage xml | |
| echo "## Coverage Report" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| if [ -f coverage.json ]; then | |
| COVERAGE=$(python3 -c "import json; data=json.load(open('coverage.json')); print(data['totals']['percent_covered_display'])") | |
| echo "**Total Coverage: ${COVERAGE}%**" >> $GITHUB_STEP_SUMMARY | |
| fi | |
| - name: Upload final coverage report | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: coverage-report-final | |
| path: | | |
| coverage.xml | |
| coverage.json | |
| htmlcov/ | |
| retention-days: 30 | |
| # ============================================================================ | |
| # STAGE 4: CI Summary | |
| # ============================================================================ | |
| ci-summary: | |
| name: CI Summary | |
| runs-on: ubuntu-latest | |
| needs: [lint, test-unit, test-integration, test-security, test-property, test-performance, test-e2e] | |
| if: always() | |
| steps: | |
| - name: Generate CI Summary | |
| run: | | |
| echo "## CI Pipeline Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| Stage | Status |" >> $GITHUB_STEP_SUMMARY | |
| echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| Lint and Type Check | ${{ needs.lint.result == 'success' && 'PASSED' || 'FAILED' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Unit Tests | ${{ needs.test-unit.result == 'success' && 'PASSED' || 'FAILED' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Integration Tests | ${{ needs.test-integration.result == 'success' && 'PASSED' || 'FAILED' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Security Scan | ${{ needs.test-security.result == 'success' && 'PASSED' || 'FAILED' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Property Tests | ${{ needs.test-property.result == 'success' && 'PASSED' || 'FAILED' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Performance Tests | ${{ needs.test-performance.result == 'success' && 'PASSED' || 'FAILED' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| E2E Tests (Playwright) | ${{ needs.test-e2e.result == 'success' && 'PASSED' || 'FAILED' }} |" >> $GITHUB_STEP_SUMMARY | |
| - name: Fail if any job failed | |
| if: | | |
| needs.lint.result == 'failure' || | |
| needs.test-unit.result == 'failure' || | |
| needs.test-integration.result == 'failure' || | |
| needs.test-security.result == 'failure' || | |
| needs.test-property.result == 'failure' || | |
| needs.test-performance.result == 'failure' || | |
| needs.test-e2e.result == 'failure' | |
| run: exit 1 |