π§ 1. What is Ruff and Why Use It
Ruff is a fast, all-in-one Python linter, formatter, and import sorter written in Rust.
It replaces multiple tools like Flake8, isort, Black, and pyupgrade, drastically speeding up development and CI pipelines.
βοΈ Key Benefits
Feature | Ruff Advantage |
---|---|
π Speed | 10β100Γ faster than Flake8 or Pylint |
π§° All-in-one | Linting + Formatting + Import Sorting |
βοΈ Unified config | Simple setup via pyproject.toml
|
π‘ Auto-fix | Many issues can be fixed automatically |
π§ CI-friendly | Supports GitHub annotations |
π§± 2. Create a Lightweight Example Application
Letβs create a simple Python app: a small To-Do manager.
ποΈ Project structure
todo_app/
βββ app/
β βββ __init__.py
β βββ main.py
β βββ utils.py
βββ tests/
β βββ test_main.py
βββ pyproject.toml
βββ requirements.txt
βββ .github/
βββ workflows/
βββ lint.yml
π§° 3. Build the Example App
app/main.py
from app.utils import add_task, list_tasks
def main():
print("Welcome to the To-Do App")
add_task("Learn Ruff")
add_task("Integrate Ruff in CI")
print("Your Tasks:")
for task in list_tasks():
print(f"- {task}")
if __name__ == "__main__":
main()
app/utils.py
tasks = []
def add_task(task: str):
"""Add a task to the list."""
if not task:
raise ValueError("Task cannot be empty")
tasks.append(task)
def list_tasks():
"""Return all tasks."""
return tasks
tests/test_main.py
from app.utils import add_task, list_tasks
def test_add_task():
add_task("Task 1")
assert "Task 1" in list_tasks()
π¦ 4. Install Ruff
pip install ruff
Verify:
ruff --version
βοΈ 5. Configure Ruff with pyproject.toml
Hereβs a well-commented configuration file with real-world defaults and examples.
pyproject.toml
[tool.ruff]
# Maximum line length (similar to Blackβs default)
line-length = 88
# Specify Python version for compatibility
target-version = "py311"
# Select rulesets to enforce
# Common rule groups:
# E/F = Pycodestyle (errors & warnings)
# W = general warnings
# I = import sorting
# UP = pyupgrade rules (modernize code)
# N = naming conventions
select = ["E", "F", "W", "I", "UP"]
# Ignore specific rule codes if desired
ignore = [
"E501", # ignore line length errors (if you rely on Black)
]
# Exclude certain paths (like virtualenvs or migrations)
exclude = ["venv", "build", "__pycache__", "migrations"]
# Show fixes when applying --fix
show-fixes = true
# Respect .gitignore patterns
respect-gitignore = true
# Auto-detect per-file ignores if necessary
per-file-ignores = { "tests/test_*.py" = ["S101"] }
# Enable incremental mode (optional, speeds up re-runs)
cache-dir = ".ruff_cache"
[tool.ruff.lint.isort]
# Sort imports intelligently
known-first-party = ["app"]
combine-as-imports = true
π§© 6. Useful Ruff Commands
Hereβs a table of common Ruff commands with explanations and when to use them:
Command | Description | Use Case |
---|---|---|
ruff check . |
Run all lint checks | β Recommended default |
ruff check . --fix |
Auto-fix lint errors | Use locally/pre-commit |
ruff format . |
Format all Python files | Code beautification |
ruff format --check . |
Check if code is properly formatted | Use in CI |
ruff rule <CODE> |
Get details for a specific rule (e.g., ruff rule E501 ) |
Learn rules |
ruff --explain <CODE> |
Explain why a rule triggered | Debugging |
ruff --help |
Show CLI options | General help |
Recommended CI Command:
ruff check .
It ensures linting consistency, and when combined withruff format --check .
, it gives both lint + format verification without auto-fixing in CI.
π§° 7. (Optional) Pre-commit Hook Setup
Create .pre-commit-config.yaml
:
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.15
hooks:
- id: ruff
args: [--fix]
- id: ruff-format
Install:
pip install pre-commit
pre-commit install
Now, Ruff runs automatically before every git commit
.
π§© 8. GitHub Actions CI Integration
Letβs integrate Ruff into a lightweight GitHub Actions pipeline.
.github/workflows/lint.yml
name: Ruff Linting CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"
- name: Install Ruff
run: pip install ruff
# πΉ Recommended: lint the code (no fixes)
- name: Run Ruff Linter
run: ruff check . --output-format=github
# πΉ Optional: Check formatting
- name: Check Ruff Formatting
run: ruff format --check .
π‘ Why --output-format=github
?
This format makes lint results appear inline as annotations on your PR.
β‘ 9. Run Everything Locally
Try these locally:
ruff check . # Lint check
ruff check . --fix # Auto-fix issues
ruff format . # Format code
pytest # Run tests
π 10. Benchmark (Optional)
Hereβs an example of how fast Ruff runs compared to traditional linters.
Benchmark
π§© 11. Summary β End-to-End Flow
Stage | Command | Purpose |
---|---|---|
Local development | ruff check . --fix |
Lint + auto-fix |
ruff format . |
Format code | |
pytest |
Run tests | |
Pre-commit | pre-commit run --all-files |
Run Ruff before commits |
CI pipeline |
ruff check . & ruff format --check .
|
Verify code cleanliness |
Customization | Edit [tool.ruff] in pyproject.toml
|
Tailor lint rules |
β 12. Takeaways
- Ruff = One tool replacing many (Flake8, isort, pyupgrade, partial Black)
- Setup takes <5 minutes and improves local + CI performance drastically
-
Recommended pipeline commands:
ruff check .
ruff format --check .
Configuration is easy via
pyproject.toml
Use
pre-commit
for best developer experience
Top comments (0)