name: Unit Tests on: # 指向 v3 的 PR 与推送都跑全量单测,作为合并门禁 pull_request: branches: - v3 push: branches: - v3 # 允许手动触发 workflow_dispatch: permissions: contents: read concurrency: group: unit-tests-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true jobs: architecture: runs-on: ubuntu-latest name: Architecture Contract Gate timeout-minutes: 10 steps: - name: Checkout code uses: actions/checkout@v7 - name: Set up uv uses: astral-sh/setup-uv@v10.0.1 with: python-version: '3.14' enable-cache: true cache-dependency-glob: | pyproject.toml uv.lock - name: Install dependencies run: uv sync --locked - name: Check event semantic policy run: | uv run --locked --no-sync pytest \ tests/test_architecture_dependencies.py \ tests/test_architecture_adapter_imports.py \ tests/test_architecture_egress.py \ tests/test_architecture_event_facts.py \ tests/test_architecture_event_policy.py -q uv run --locked --no-sync python \ scripts/architecture/event_policy.py - name: Check host architecture snapshot run: | uv run --locked --no-sync pytest \ tests/test_architecture_contract_baseline.py \ tests/test_architecture_baseline_cli.py -q uv run --locked --no-sync python \ scripts/architecture/baseline.py --check-host - name: Check governed Python types run: uv run --locked --no-sync mypy --config-file mypy.ini - name: Check complexity ratchet run: | uv run --locked --no-sync python scripts/architecture/complexity.py uv run --locked --no-sync python scripts/architecture/complexity.py --v2 - name: Check native concurrency ownership run: uv run --locked --no-sync python scripts/architecture/concurrency.py - name: Check async blocking ratchet run: uv run --locked --no-sync python scripts/architecture/async_blocking.py - name: Check background task ownership run: uv run --locked --no-sync python scripts/architecture/task_ownership.py - name: Check process runtime service locators run: uv run --locked --no-sync python scripts/architecture/service_locator.py - name: Check Ruff diagnostic ratchet run: uv run --locked --no-sync python scripts/architecture/ruff_ratchet.py - name: Check mypy error ratchet run: uv run --locked --no-sync python scripts/architecture/mypy_ratchet.py - name: Check startup performance contract run: >- uv run --locked --no-sync python scripts/startup/performance.py --check --repeat 3 pytest: runs-on: ubuntu-latest name: Unit Tests (${{ matrix.shard }}) timeout-minutes: 20 strategy: fail-fast: false matrix: include: - shard: '1/4' - shard: '2/4' - shard: '3/4' - shard: '4/4' steps: - name: Checkout code uses: actions/checkout@v7 - name: Set up uv uses: astral-sh/setup-uv@v10.0.1 with: python-version: '3.14' enable-cache: true cache-dependency-glob: | pyproject.toml uv.lock - name: Install dependencies run: uv sync --locked - name: Run tests timeout-minutes: 10 run: uv run --locked --no-sync python tests/run.py --shard "${{ matrix.shard }}" coverage-shard: runs-on: ubuntu-latest name: Coverage Shard (${{ matrix.shard }}) timeout-minutes: 15 strategy: fail-fast: false matrix: include: - shard: '1/8' index: '1' - shard: '2/8' index: '2' - shard: '3/8' index: '3' - shard: '4/8' index: '4' - shard: '5/8' index: '5' - shard: '6/8' index: '6' - shard: '7/8' index: '7' - shard: '8/8' index: '8' steps: - name: Checkout code uses: actions/checkout@v7 - name: Set up uv uses: astral-sh/setup-uv@v10.0.1 with: python-version: '3.14' enable-cache: true cache-dependency-glob: | pyproject.toml uv.lock - name: Install dependencies run: uv sync --locked - name: Generate coverage data timeout-minutes: 10 run: uv run --locked --no-sync python -m coverage run --parallel-mode tests/run.py --shard "${{ matrix.shard }}" - name: Upload coverage data uses: actions/upload-artifact@v7 with: name: coverage-data-${{ matrix.index }} path: .coverage.* include-hidden-files: true if-no-files-found: error retention-days: 7 coverage-report: runs-on: ubuntu-latest name: Coverage Report needs: coverage-shard timeout-minutes: 10 steps: - name: Checkout code uses: actions/checkout@v7 - name: Set up uv uses: astral-sh/setup-uv@v10.0.1 with: python-version: '3.14' enable-cache: true cache-dependency-glob: | pyproject.toml uv.lock - name: Install dependencies run: uv sync --locked - name: Download coverage data uses: actions/download-artifact@v8 with: pattern: coverage-data-* path: coverage-data merge-multiple: true - name: Combine coverage data and check ratchet run: | uv run --locked --no-sync python -m coverage combine coverage-data uv run --locked --no-sync python -m coverage report uv run --locked --no-sync python -m coverage json uv run --locked --no-sync python -m coverage xml uv run --locked --no-sync python scripts/architecture/coverage_ratchet.py - name: Upload coverage report uses: actions/upload-artifact@v7 with: name: coverage-report path: | coverage.xml coverage.json retention-days: 7