name: CI on: push: branches: [main] pull_request: branches: [main] # 取消同一分支/同一次 push 的旧运行,避免资源浪费 concurrency: group: ci-${{ github.ref }} cancel-in-progress: true permissions: contents: read jobs: test: name: pytest (Python ${{ matrix.python-version }}) runs-on: ubuntu-latest strategy: fail-fast: false matrix: python-version: ["3.10", "3.11", "3.12"] steps: - name: Checkout repository 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 dependencies uses: actions/cache@v4 with: path: ~/.cache/pip key: pip-${{ runner.os }}-py${{ matrix.python-version }}-${{ hashFiles('requirements-dev.txt') }} restore-keys: | pip-${{ runner.os }}-py${{ matrix.python-version }}- pip-${{ runner.os }}- - name: Install dependencies run: | python -m pip install --upgrade pip # clean env 必须同时安装测试依赖 + admin 运行依赖,避免本地环境污染掩盖导入问题 if [ -f requirements-dev.txt ]; then pip install -r requirements-dev.txt else echo "::warning::requirements-dev.txt not found, installing test deps directly" pip install pytest pytest-cov fi if [ -f requirements-admin.txt ]; then pip install -r requirements-admin.txt fi - name: Verify Python and pytest versions run: | python --version pytest --version - name: Run unified quality gate # P1-7: CI 与本地统一走 scripts/dev-verify.sh,避免 coverage / lint / mypy 口径漂移 run: | PYTHON_BIN=python bash scripts/dev-verify.sh - name: Upload coverage artifact if: always() && matrix.python-version == '3.11' && hashFiles('coverage.xml') != '' uses: actions/upload-artifact@v4 with: name: coverage-report path: coverage.xml retention-days: 7 # T10.2: 上传 coverage.xml 到 codecov 渲染覆盖率徽章 # 关键决策: # - 仅在 3.11 单点上传:避免多份报告名冲突(codecov 按文件名合并) # - fail_ci_if_error: false: codecov 不可达时不影响 CI 通过(与个人项目 + 多镜像 # 仓库场景匹配;tksea/gitea 不被 codecov 官方支持,无 token 时仍能上传但不写 status) # - 不设 token: public repo 可匿名上传;徽章正常渲染 - name: Upload coverage to Codecov if: always() && matrix.python-version == '3.11' && hashFiles('coverage.xml') != '' uses: codecov/codecov-action@v4 with: file: coverage.xml flags: python-3.11 fail_ci_if_error: false verbose: false - name: Test summary if: always() run: | echo "### CI Summary" >> $GITHUB_STEP_SUMMARY echo "- Python: ${{ matrix.python-version }}" >> $GITHUB_STEP_SUMMARY echo "- Status: ${{ job.status }}" >> $GITHUB_STEP_SUMMARY if [ -f coverage.xml ]; then echo "- Coverage report: uploaded as artifact" >> $GITHUB_STEP_SUMMARY fi