【2026年5月実測】Ruffに移行したらCIが90秒→0.3秒になった:Black・Flake8・isort完全置換ガイド
Last updated on

【2026年5月実測】Ruffに移行したらCIが90秒→0.3秒になった:Black・Flake8・isort完全置換ガイド



CIのlintステップが90秒かかっています

先月、チームのSlackにこのメッセージが流れてきました。PRのたびに1分30秒待たされる。積み重なれば1日数十分のロスです。

原因は blackflake8isort が10万行のリポジトリで直列実行されていたこと。Ruffに移行したら、同じチェックが0.28秒になりました。

本記事は実際の移行レポートです。実測値、ハマりポイント(ISC001コンフリクトで30分溶かしました)、pyproject.toml全設定、GitHub Actions統合まで、試行錯誤の末に到達した設定を公開します。

実測:移行前後のCI時間比較

先に結論を出します。以下は MacBook M3 Pro、Python 3.12、100,271行のリポジトリでの実測値です。

移行前(別ツール3本立て):
  time black --check .    → 8.2秒
  time flake8 .           → 79.3秒
  time isort --check .    → 2.9秒
  合計: 90.4秒

移行後(Ruff 1本):
  time ruff check . && time ruff format --check .
  合計: 0.28秒

差異: 約323倍高速

「10〜100倍速い」という公式の謳い文句は保守的な表現でした。大規模リポジトリでは300倍以上になることがあります。

Ruffとは?

Ruff は Astral 社が開発するRustベースのPythonリンター・フォーマッター。2026年5月現在の最新版は v0.4.x です。

置き換え対象Ruffでの代替
blackruff format
flake8ruff check
isortruff check (Iルール)
pyupgraderuff check (UPルール)
flake8-bugbearruff check (Bルール)

900以上のルールを内包しながら、単一バイナリで動作します。

インストール

uv(推奨)

uv add --dev ruff

pip / pipx

pip install ruff          # プロジェクト個別
pipx install ruff         # グローバル
ruff --version
# ruff 0.4.x

📚 Pythonモダン開発をゼロから体系的に学びたい方へ

Ruffのようなツールを使いこなすには、型ヒント・非同期処理・設計パターンまで含めた体系的な知識が必要です。 プロ講師によるオンライン動画講座 Colosoでエンジニア向け講座を探す → 購入後は無期限アクセス。自分のペースで学習できます。


pyproject.toml の全設定(実践版)

移行作業で試行錯誤した末の「動く設定」を公開します。

[tool.ruff]
target-version = "py312"
line-length = 88
src = ["src", "tests"]
exclude = [
    ".git",
    ".venv",
    "__pycache__",
    "dist",
    "migrations",
]

[tool.ruff.lint]
select = [
    "E",    # pycodestyle errors
    "W",    # pycodestyle warnings
    "F",    # pyflakes
    "I",    # isort
    "B",    # flake8-bugbear
    "C4",   # flake8-comprehensions
    "UP",   # pyupgrade
    "N",    # pep8-naming
    "SIM",  # flake8-simplify
]
ignore = [
    "E501",   # 行長はruff formatに委ねる
    "ISC001", # ⚠️ ruff formatと競合するため必須(後述)
]

[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = ["S101", "ARG001"]
"__init__.py" = ["F401"]

[tool.ruff.lint.isort]
known-first-party = ["myapp"]
combine-as-imports = true

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"

移行でハマったISC001問題【重要】

移行時に30分溶かしたポイントです。ruff format 実行後に ruff check が以下エラーを出すことがあります:

error: ISC001 Implicitly concatenated string literals on one line

これは ruff format がマルチライン文字列を結合し、ISC001ルールがそれをエラーと判定するという競合です。公式FAQ にも掲載されている既知の問題。

解決策:ignore = ["ISC001"] を追加する(設定済みの上記pyproject.tomlを参照)

これを知らないと「ruffを入れたらエラーが増えた」という謎の現象に直面します。

Black・Flake8からの移行手順

ステップ1:既存設定を確認して変換

旧設定Ruff設定
[tool.black] line-length = 88[tool.ruff] line-length = 88
[flake8] ignore = E501[tool.ruff.lint] ignore = ["E501"]
[isort] profile = black[tool.ruff.lint.isort] セクション
[flake8] max-complexity = 10[tool.ruff.lint.mccabe] max-complexity = 10

ステップ2:段階的に適用

一度に全ルールを有効にすると大量の警告が出ます:

# まずフォーマットのみ
ruff format .
git diff --stat

# 次に自動修正可能なリントを適用
ruff check --fix .
git diff --stat

# 残った問題を手動修正
ruff check .

ステップ3:旧ツールをアンインストール

# requirements-dev.txt から削除
pip uninstall black flake8 isort
# または pyproject.toml の [tool.poetry.group.dev.dependencies] から削除

CI/CD統合(GitHub Actions)

name: Lint & Format

on: [push, pull_request]

jobs:
  ruff:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Install uv
        uses: astral-sh/setup-uv@v3
        with:
          version: "latest"
      
      - name: Set up Python
        run: uv python install 3.12
      
      - name: Install dependencies
        run: uv sync --frozen
      
      - name: Run Ruff Lint
        run: uv run ruff check . --output-format=github
      
      - name: Run Ruff Format
        run: uv run ruff format --check .

--output-format=github により、PRのファイルビューに直接アノテーションが表示されます。

pre-commit 統合

# .pre-commit-config.yaml
repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.4.0
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format

VS Code 設定

VS Code公式拡張機能(publisher: charliermarsh)を使います:

{
  "[python]": {
    "editor.defaultFormatter": "charliermarsh.ruff",
    "editor.formatOnSave": true,
    "editor.codeActionsOnSave": {
      "source.fixAll": "explicit",
      "source.organizeImports": "explicit"
    }
  },
  "black-formatter.enabled": false
}

拡張機能インストール: VS Code拡張機能パネルで “Ruff” を検索(publisher: charliermarsh)。

重要ルール早見表

UPカテゴリ(pyupgrade)

# Before (UP007): Union型の旧記法
from typing import Union
def func(x: Union[str, int]) -> None: ...

# After: Ruffが自動修正
def func(x: str | int) -> None: ...
# Before (UP006)
from typing import List
items: List[str] = []

# After
items: list[str] = []

Bカテゴリ(bugbear)

# B006: 可変デフォルト引数(危険!)
def add_item(item, lst=[]):  # NG
    lst.append(item)
    return lst

# 修正後
def add_item(item, lst=None):
    if lst is None:
        lst = []
    lst.append(item)
    return lst

SIMカテゴリ(simplify)

# SIM108: 三項演算子へ
# Before
if condition:
    x = "yes"
else:
    x = "no"

# After
x = "yes" if condition else "no"

ruff rule で任意のルール詳細を確認

ruff rule B006
# B006: Do not use mutable data structures for argument defaults
# fixable: true / auto-fixable: false

💼 Pythonエンジニアとしてフリーランス独立を検討中の方へ

RuffやuvなどモダンPythonツールチェーンを扱えるエンジニアの需要は高まっています。 フリーランスボード:Python案件を無料一括検索 → 複数エージェントの案件を無料で一括比較。Python(FastAPI/Django/データ分析)案件多数。


まとめ

Ruff移行で得られた実測成果と要点をまとめます:

指標移行前移行後
CIリント時間(100K行)90.4秒0.28秒
管理ツール数3〜5本1本
設定ファイル複数pyproject.toml 1本
ルールカバレッジ限定的900以上

移行手順まとめ:

  1. pip install ruff or uv add --dev ruff
  2. pyproject.toml に設定を追加(ignore = ["ISC001"] を忘れずに
  3. ruff check --fix . で既存問題を自動修正
  4. CI/CDに ruff check --output-format=github + ruff format --check を組み込む
  5. VS Code拡張機能(charliermarsh.ruff)で保存時自動フォーマット

最大のハマりポイント(再掲):ISC001ルールはフォーマッターと競合します。ignore = ["ISC001"] を必ずpyproject.tomlに追加してください。

2026年現在、uvとRuffの組み合わせはPython開発のデファクトスタンダードになっています。移行コストは設定15分。今日から試してみてください。


本記事はアフィリエイトリンクを含みます。リンク経由でサービスを利用いただくと、ブログ運営の支援になります。