GitHub Actions Python CI:pytest、Black、Flake8 与 Poetry 自动化

GitHub Actions Python CI 实战:基于 Poetry 的依赖管理、pytest 测试自动化(覆盖率/coverage)、Black 代码格式化、Flake8 静态检查、mypy 类型检查、多版本 Python 矩阵测试(3.9/3.10/3.11/3.12)、缓存策略加速、安全扫描(bandit/safety)、发布到 PyPI 自动化

Python 项目的 CI 不仅是「跑测试」,而是「把代码质量关」。从依赖锁定到类型检查,从格式化到安全扫描——一个完善的 Python CI 流水线应该在代码合并前拦截 90% 以上的低级问题。本文用 GitHub Actions 搭建覆盖多版本 Python 的完整 CI,包括 Poetry 依赖管理、pytest 测试、coverage 门禁、Black/Flake8/mypy 质量检查和 PyPI 自动发布。


一、基础 CI 流水线:测试与检查

1.1 完整工作流

# .github/workflows/ci.yml
name: Python CI

on:
  push:
    branches: [main, master]
  pull_request:
    branches: [main, master]

jobs:
  test:
    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: Install Poetry
        uses: snok/install-poetry@v1
        with:
          version: latest
          virtualenvs-create: true
          virtualenvs-in-project: true

      - name: Cache dependencies
        uses: actions/cache@v3
        with:
          path: .venv
          key: venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }}

      - name: Install dependencies
        run: poetry install --no-interaction --no-root

      - name: Run tests
        run: poetry run pytest tests/ -v --cov=src --cov-report=xml --cov-report=term

      - name: Upload coverage
        uses: codecov/codecov-action@v3
        with:
          files: ./coverage.xml
          fail_ci_if_error: true

1.2 关键要点

矩阵测试:确保代码在 Python 3.9-3.12 均通过
Poetry 缓存:.venv 目录缓存,复用依赖安装
覆盖率:--cov 生成 xml + terminal 报告
Codecov:上传覆盖率并设门禁(如 < 80% 失败)

二、代码质量检查:Black + Flake8 + mypy

2.1 工作流扩展

      - name: Check formatting with Black
        run: poetry run black --check src/ tests/

      - name: Lint with Flake8
        run: poetry run flake8 src/ tests/ --max-line-length=88 --extend-ignore=E203

      - name: Type check with mypy
        run: poetry run mypy src/

2.2 配置同步

# pyproject.toml
[tool.black]
line-length = 88
target-version = ['py39', 'py310', 'py311', 'py312']

[tool.flake8]
max-line-length = 88
extend-ignore = ["E203", "W503"]

[tool.mypy]
python_version = "3.11"
strict = true
warn_return_any = true
warn_unused_configs = true

2.3 提交前检查

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/psf/black
    rev: 23.12.1
    hooks:
      - id: black
  - repo: https://github.com/pycqa/flake8
    rev: 6.1.0
    hooks:
      - id: flake8
  - repo: https://github.com/pre-commit/mirrors-mypy
    rev: v1.7.1
    hooks:
      - id: mypy

三、安全扫描:Bandit + Safety

3.1 安全扫描工作流

      - name: Security scan with Bandit
        run: poetry run bandit -r src/ -f json -o bandit-report.json || true

      - name: Check dependencies for known vulnerabilities
        run: poetry run safety check

3.2 安全策略

Bandit:扫描代码中的安全问题(硬编码密码、SQL 注入模式等)
Safety:扫描依赖中的已知 CVE
# 生产建议:加入 CI 门禁,安全漏洞阻塞合并

四、发布到 PyPI

4.1 自动发布工作流

# .github/workflows/release.yml
name: Release to PyPI

on:
  release:
    types: [published]

jobs:
  publish:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.11"

      - name: Install Poetry
        uses: snok/install-poetry@v1

      - name: Configure PyPI token
        run: poetry config pypi-token.pypi ${{ secrets.PYPI_TOKEN }}

      - name: Build and publish
        run: |
          poetry build
          poetry publish

4.2 版本管理

Poetry version bump:
  poetry version patch  # 1.0.0 → 1.0.1
  poetry version minor  # 1.0.0 → 1.1.0
  poetry version major  # 1.0.0 → 2.0.0

# GitHub Release 触发发布:
# 1) 本地 poetry version patch && git commit && git tag v1.0.1
# 2) git push && git push --tags
# 3) GitHub 上创建 Release → 触发 Actions 发布到 PyPI

五、性能与可靠性优化

5.1 缓存策略

依赖缓存:
  - .venv 目录( Poetry 虚拟环境)
  - pip 缓存(actions/setup-python 自带)
  - pre-commit 缓存

缓存键设计:
  key: venv-${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('poetry.lock') }}
  restore-keys: |
    venv-${{ runner.os }}-${{ matrix.python-version }}-

5.2 失败处理

      - name: Run tests
        run: poetry run pytest tests/ -v
        continue-on-error: ${{ matrix.python-version == '3.13-dev' }}

      - name: Notify on failure
        if: failure()
        uses: slackapi/slack-github-action@v1
        with:
          payload: |
            {"text": "CI failed on ${{ github.ref }}"}

六、多包 Monorepo 策略

6.1 项目结构

project/
  packages/
    core/
      pyproject.toml
      src/
    api/
      pyproject.toml
      src/
    cli/
      pyproject.toml
      src/
  .github/workflows/ci.yml

6.2 矩阵构建

    strategy:
      matrix:
        package: [core, api, cli]
        python-version: ["3.10", "3.11"]

    steps:
      - uses: actions/checkout@v4

      - name: Test ${{ matrix.package }}
        working-directory: packages/${{ matrix.package }}
        run: |
          poetry install
          poetry run pytest

七、CI 模板速查

# 最小可用 Python CI
name: CI
on: [push, pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"
      - name: Install dependencies
        run: |
          pip install -r requirements.txt
      - name: Run tests
        run: pytest

总结

Python 项目的 GitHub Actions CI 核心 pipeline 是:检出代码 → 安装 Poetry → 缓存依赖 → 运行 pytest + coverage → Black 格式化检查 → Flake8 lint → mypy 类型检查 → Bandit/Safety 安全扫描 → 上传报告。矩阵测试覆盖 Python 3.9-3.12,确保兼容性。发布到 PyPI 通过 GitHub Release 触发自动化。Poetry 的锁文件 poetry.lock 比 requirements.txt 更可靠,缓存 .venv 让 CI 运行时间从 3 分钟降到 30 秒。代码质量工具在 CI 中设门禁,比 code review 更前置拦截问题。

延伸阅读:

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「github-actions」更多文章

  1. GitHub Actions Go/Rust CI:交叉编译、静态检查与发布
  2. GitHub Actions Java/JVM CI:Maven、Gradle、JaCoCo 与 Jib 容器化
  3. GitHub Actions PR 自动化:标签、审查、合并与发布