Skip to main content

Overview

The CI workflow automatically runs on every push to main and on all pull requests targeting main. It performs comprehensive Python code quality checks including linting, type checking, testing, and security scanning.

Trigger Conditions

The workflow runs on:
1

Push to main

Automatically triggers when code is pushed directly to the main branch
2

Pull requests

Triggers on all pull requests targeting the main branch
on:
  push: { branches: [ main ] }
  pull_request: { branches: [ main ] }

Workflow Configuration

Runner Environment

The workflow runs on ubuntu-latest, which provides:
  • Latest Ubuntu LTS version
  • Pre-installed development tools
  • Docker support
  • GitHub Actions runner environment
jobs:
  ci:
    runs-on: ubuntu-latest

Workflow Steps

1

Checkout code

Uses actions/checkout@v4 to clone the repository into the runner
- uses: actions/checkout@v4
This step fetches the complete repository history and checks out the commit that triggered the workflow.
2

Setup Python

Configures Python 3.12 using actions/setup-python@v5
- uses: actions/setup-python@v5
  with:
    python-version: "3.12"
Python 3.12 is specified to ensure consistent behavior across all CI runs. This version includes the latest performance improvements and security updates.
3

Install dependencies

Upgrades pip and wheel, then installs the project with development dependencies
python -m pip install -U pip wheel
if [ -f pyproject.toml ]; then pip install -e ".[dev]" || true; fi
The workflow:
  1. Upgrades pip and wheel to latest versions
  2. Checks for pyproject.toml presence
  3. Installs the project in editable mode with dev extras
  4. Uses || true to continue even if installation fails
4

Run linting and testing

Executes a comprehensive suite of Python code quality tools
if [ -f pyproject.toml ]; then
  pip install ruff black mypy pytest pytest-cov bandit safety || true
  ruff check . || true
  black --check . || true
  mypy src/ || true
  pytest || true
  bandit -r src/ || true
  safety check -r <(pip freeze) --full-report || true
else
  echo "No pyproject found. Skipping python checks."
fi

Code Quality Tools

The CI workflow runs multiple tools to ensure code quality:
Command: ruff check .Ruff is an extremely fast Python linter written in Rust. It checks for:
  • Code style issues
  • Common programming errors
  • Complexity issues
  • Import sorting
ruff check .
Ruff replaces multiple tools (flake8, isort, pydocstyle) with a single fast linter.
Command: black --check .Black verifies that code follows consistent formatting standards. The --check flag ensures it only reports issues without modifying files.
black --check .
If Black finds formatting issues, the CI will fail. Run black . locally to auto-format your code.
Command: mypy src/MyPy performs static type analysis on the src/ directory to catch type-related bugs before runtime.
mypy src/
Ensures type hints are correct and catches potential type errors.
Command: pytestRuns the project’s test suite using pytest with coverage reporting enabled (via pytest-cov).
pytest
Executes all tests found in the project and reports results.
Command: bandit -r src/Bandit scans Python code for common security issues:
  • Hard-coded passwords
  • SQL injection vulnerabilities
  • Use of insecure functions
  • Shell injection risks
bandit -r src/
While Bandit findings don’t fail the build (due to || true), address any security issues it identifies.
Command: safety check -r <(pip freeze) --full-reportSafety checks installed dependencies against a database of known security vulnerabilities.
safety check -r <(pip freeze) --full-report
The --full-report flag provides detailed information about any vulnerable packages found.

Failure Handling

All tool commands use || true to prevent individual tool failures from stopping the entire workflow. This means the workflow will always complete, but you should review the logs for any issues.
The workflow is designed to be informative rather than strictly blocking:
  • Each tool runs independently
  • Tool failures don’t stop subsequent checks
  • All results are visible in the workflow logs
  • Review logs to identify and fix issues

Customization

Changing Python Version

To use a different Python version, modify the setup step:
- uses: actions/setup-python@v5
  with:
    python-version: "3.11"  # or "3.10", "3.13", etc.

Adding Additional Checks

Add new tools to the linting step:
- name: Lint/Test (Python)
  run: |
    pip install ruff black mypy pytest pytest-cov bandit safety your-tool
    # ... existing checks ...
    your-tool --check .

Making Checks Blocking

To make the workflow fail on tool errors, remove || true from commands:
# Non-blocking (current)
ruff check . || true

# Blocking (fails on errors)
ruff check .
Removing || true will cause the workflow to fail immediately when a tool encounters an error. Ensure your code passes all checks before making this change.

Running on Additional Branches

Expand trigger conditions to include more branches:
on:
  push: 
    branches: [ main, develop, release/* ]
  pull_request: 
    branches: [ main, develop ]

Local Development

Run the same checks locally before pushing:
# Install dev dependencies
pip install -e ".[dev]"

# Install tools
pip install ruff black mypy pytest pytest-cov bandit safety

# Run checks
ruff check .
black --check .
mypy src/
pytest
bandit -r src/
safety check
Running these checks locally helps catch issues before pushing, reducing CI iteration time.

Troubleshooting

If your project doesn’t have a pyproject.toml file, the workflow skips all Python checks and logs:
No pyproject found. Skipping python checks.
To enable checks, add a pyproject.toml file to your project root.
The workflow uses || true for installations, so failures don’t stop the workflow. Check logs for:
  • Missing system dependencies
  • Incompatible package versions
  • Network issues during download
Fix dependency issues in your pyproject.toml or requirements files.
If a tool isn’t found, ensure it’s included in the installation step:
pip install ruff black mypy pytest pytest-cov bandit safety
All tools must be installed before they’re executed.

Best Practices

  1. Fix issues locally first - Run all checks before pushing to avoid CI failures
  2. Review all tool output - Even if checks pass, review warnings and suggestions
  3. Keep dependencies updated - Regularly update tools to get latest checks and fixes
  4. Use pre-commit hooks - Automate local checks with pre-commit framework
  5. Monitor security findings - Address Bandit and Safety findings promptly

Build docs developers (and LLMs) love