Run CI Locally
This guide shows how to run CI checks locally before pushing, using both
direct commands and gh act for full workflow simulation.
Prerequisites
Poetry installed with dependencies:
poetry installFor
gh act: GitHub CLI with act extension (gh extension install nektos/gh-act)For
gh act: Docker running
Quick Checks (Direct Commands)
Run individual CI checks directly:
Lint check:
poetry run ruff check .
# Auto-fix issues
poetry run ruff check . --fix
Type check:
poetry run mypy src
Run tests:
# All non-AI tests
poetry run pytest -m "not ai" --tb=short
# Fast math/engine tests only
mise run test-fast
Check documentation:
# Build docs
cd docs && poetry run sphinx-build -b html . _build/html
# Strict mode (warnings as errors)
mise run docs-strict
Check formatting:
# Check only (no changes)
poetry run ruff format --check .
# Auto-format
poetry run ruff format .
Using Mise Tasks
Mise provides convenient task shortcuts:
# List all available tasks
mise tasks
# Quick CI (lint + format + typecheck + fast tests)
mise run ci
# Full test suite
mise run test
# Type checking only
mise run typecheck
# Documentation build
mise run docs
# Live documentation server (auto-reload)
mise run docs-live
Full CI Simulation with gh act
gh act runs GitHub Actions workflows locally in Docker, simulating
exactly what CI will do.
Dry run (see what would execute):
gh act --dryrun
Run specific job:
# Run the main CI job
gh act -j ci
# Run documentation build
gh act -j docs
# Run style check
gh act -j style
Simulate specific events:
# Simulate push event
gh act push
# Simulate pull request event
gh act pull_request
Custom event payloads:
Create .github/test-events/pr-to-dev.json:
{
"pull_request": {
"base": { "ref": "dev" },
"head": { "ref": "feature/test" }
}
}
Then run:
gh act pull_request -e .github/test-events/pr-to-dev.json
gh act Limitations
Some GitHub-specific features don’t work locally:
Secrets: Not available (by design—this is a security feature)
GitHub API calls: May fail without proper authentication
Caching: Works differently than GitHub’s infrastructure
Artifacts: Upload/download behaves differently
For most development purposes, dry-run validation is sufficient:
# Validates YAML syntax and shows execution plan
gh act --dryrun
Pre-Commit Hooks
Pre-commit hooks run automatically on git commit. To run manually:
# Run all hooks on staged files
poetry run pre-commit run
# Run all hooks on all files
poetry run pre-commit run --all-files
# Run specific hook
poetry run pre-commit run ruff
Hooks configured (from .pre-commit-config.yaml):
ruff (lint) - Catches bugs, style issues
ruff (format) - Enforces formatting
mypy (typecheck) - Type errors
pytest (fast tests) - Quick sanity check
yamllint - YAML syntax validation
commitizen - Commit message format
CI Job Reference
The CI workflow (.github/workflows/ci.yml) runs three jobs:
Job |
Blocks Merge |
Purpose |
|---|---|---|
|
Yes |
Lint (Ruff), types (MyPy), tests (Pytest) |
|
Yes |
Doctest examples, Sphinx build |
|
No (advisory) |
Formatting check (informational only) |
Troubleshooting
- “command not found: gh”
Install GitHub CLI: https://cli.github.com/
- “gh act: command not found”
Install the act extension:
gh extension install nektos/gh-act
- “Cannot connect to Docker daemon”
Ensure Docker is running. On Linux:
sudo systemctl start docker
- MyPy errors on third-party libraries
Install type stubs:
poetry add --group dev types-requests # example
- Pre-commit hooks slow
Skip hooks for WIP commits:
git commit --no-verify -m "wip: work in progress"
Warning
Remember to run hooks before final commit!
See Also
Submit a Pull Request - Full contribution workflow
CI/CD Workflow Reference - CI technical reference
Configuration System - Configuration options