$ sudo teach|
    $ sudo teach|
    IT school
  • Telegram
  • Партнёрам
  • Все курсы
$ sudo teach IT
OOO "SALEPROFIT"Контакты и реквизитыIT-Park Logo

Школа

  • Блог
  • Проверить сертификат

Сотрудничество

  • Стать учителем
  • Партнёрская программа
  • О проекте

Право

  • Оферта
  • Политика конфиденциальности

© 2023–2026 $ sudo teach IT™. All Rights Reserved. Public user contributions licensed under CC BY-SA 4.0 license with attribution required
TelegramGitHubYouTube
ГлавнаяБлогRuff в продакшене: автозамены (fix), правила для команды и контроль качества перед релизом

Ruff в продакшене: автозамены (fix), правила для команды и контроль качества перед релизом

$ sudo teach IT
·17 августа 2026 г.·12 мин·39
Ruff в продакшене: автозамены (fix), правила для команды и контроль качества перед релизом

Покажем, как настроить Ruff так, чтобы он не просто линтовал, а безопасно исправлял код, как выбрать набор правил под ваш стиль и как встроить проверки в релизный пайплайн.

Содержание
Почему именно Ruff и где он «ломается», если сделать по-быстромуНастройка Ruff для безопасных автозамен (fix)Базовая идея: сначала выберите, что считать «исправляемым»Вариант 1: фикс только безопасных изменений и проверка идемпотентности в CIВариант 2: фикс по желанию в отдельном шаге (и отдельная политика)Что с --unsafe-fixes?Автозамены ≠ форматированиеВыбор набора правил под стиль команды: практическая методика1) Не выбирайте правила «из головы». Соберите исходную базу качества2) Разделяйте правила по слоям жизненного цикла3) Договоритесь о числовых параметрах: line-length, target-version, исключения4) Настройте правила для разных директорий5) Включите «правила для команды» через политику фиксовИнтеграция в релизный пайплайн: контроль качества перед выпускомМодель контроля: «быстро локально, строго в CI, идеально перед релизом»Пример пайплайна в GitHub ActionsПодводные камни: git diff и CIКонтроль качества: как измерять эффект и не утонуть в шумеИндикатор 1: доля файлов, которые меняются на --fixИндикатор 2: число уникальных правил и динамика по времениИндикатор 3: стабильность результата (идемпотентность)Конкретные настройки: безопасный профиль для командыОшибки, которые чаще всего приводят к проблемам в продакшене1) Включили fix для всего набора правил2) Не согласовали Ruff и форматтер3) Разные версии Ruff в окружениях4) Нет «контракта» для команды по unsafe-fixes5) Нет проверки идемпотентностиКак выстроить процесс обучения команды (и зачем это нужно Ruff)Вывод: Ruff как механизм контроля качества, а не просто набор правил

Ruff давно перестал быть «ещё одним линтером». На практике он становится частью инженерной культуры: разработчики получают быстую обратную связь локально, а CI превращает стиль и качество кода в управляемый процесс. Самый частый следующий шаг — включить автозамены (--fix) и сделать Ruff не только «показывающим ошибки», но и «исправляющим» их перед тем, как изменения попадут в продакшн.

Однако автозамены в команде — это зона, где легко сломать доверие к инструменту. Ошибка в настройках приводит к неожиданным правкам, конфликтам с форматтером, различиям между локальной и CI-версией, а иногда — к изменению поведения кода. В этой статье разберёмся, как настроить Ruff в продакшене так, чтобы:

  • fix работал безопасно и предсказуемо;
  • правила соответствовали вашему стилю, а не «стандартному вкусу» автора конфигурации;
  • проверки были встроены в релизный пайплайн;
  • перед релизом появлялась измеримая гарантия качества.

Почему именно Ruff и где он «ломается», если сделать по-быстрому

Ruff выполняет несколько разных задач одновременно: статический анализ (линтинг), проверка типов/семантики в рамках выбранных правил, сортировки импортов, иногда — автозамены (fixers). Важный момент: не все фиксы одинаковы по риску.

Условно можно разделить правила на классы:

  1. Чисто стилистические фиксы, которые не меняют семантику.
  2. Фиксы, которые меняют структуру кода, но считаются безопасными Ruff'ом (например, замена синтаксиса, реорганизация выражений).
  3. Фиксы с потенциальным риском — там, где автозамена может повлиять на читаемость, сложность или даже поведение (хотя Ruff старается маркировать такие случаи).

Проблемы, которые обычно возникают при «быстром старте»:

  • Включили --fix без ограничений: Ruff начинает править больше, чем ожидали.
  • Не согласовали правила с форматтером (Black/others): Ruff чинит формат, а форматтер снова меняет обратно.
  • Конфигурация в CI и локально различается: один разработчик получает одни результаты, другой — другие.
  • Нет «контракта» для команды: люди обсуждают, кто «имеет право» отключать правила, а кто — нет.
  • Нет контроля перед релизом: ленты кода проходят мимо, пока не обнаружится регрессия.

Поэтому настройка для продакшена — это не «включить Ruff», а выстроить систему: правила → фикс → форматирование → проверка в пайплайне → контроль качества.


Настройка Ruff для безопасных автозамен (fix)

Базовая идея: сначала выберите, что считать «исправляемым»

Ruff поддерживает разные режимы автозамены. На практике удобно мыслить так: включаем фикс только там, где риск приемлемый для вашей команды. Для этого важно:

  • ограничить набор правил, которые включены;
  • управлять тем, какие классы исправлений применяются;
  • отделить «быстрые безопасные фиксы» от «более спорных».

Начнём с минимальной конфигурации в pyproject.toml.

code
[tool.ruff]
target-version = "py311"
line-length = 100
src = ["src", "tests"]

[tool.ruff.lint]
select = [
  "E",  # pycodestyle errors (часть стилистики)
  "F",  # pyflakes
  "I",  # isort
  "UP", # upgrades (в более новых версиях Python)
  "B",  # flake8-bugbear (часть помогает находить ошибки)
]
ignore = [
  "E501", # line too long — если у вас line-length соблюдается иначе
]

Это уже задаёт базовую рамку: мы не просим Ruff «чинить всё подряд», а выбираем конкретные семейства правил.

Дальше — ключевой слой: как включать fix.

Рекомендованный подход

  • В локальной разработке: ruff check --fix (или ruff check --fix --unsafe-fixes только по решению команды).
  • В CI: проверять, что после фикса код не меняется (идемпотентность), или запускать фиксы и снова прогонять проверки.

Ниже — типичная схема для «надёжного продакшена».

Вариант 1: фикс только безопасных изменений и проверка идемпотентности в CI

В CI сначала запускается фикс (без unsafe), затем Ruff проверяет, что состояние репозитория чистое.

code
ruff check --fix .
ruff check .

Но это недостаточно жёстко: изменения могли быть применены, но вы всё равно их закоммитили не полностью. Поэтому лучше сделать «жёсткую» проверку: после автозамены не должно оставаться диффа.

Пример: проверка, что фиксы ничего не меняют

code
ruff check --fix .
git diff --exit-code

И только потом:

code
ruff check .

Так вы превращаете --fix в контролируемый шаг: либо CI применяет фикс и код становится «принятым», либо CI обнаруживает, что разработчик не подтянул автоисправления.

Вариант 2: фикс по желанию в отдельном шаге (и отдельная политика)

Если команда не хочет, чтобы CI всегда менял код, можно разделить процессы:

  • локально разработчик делает ruff check --fix;
  • CI просто проверяет ruff check без --fix;
  • перед релизом запускается «валидация с фиксом» в режиме проверки идемпотентности.

Идея в том, что основной pipeline остаётся быстрым и предсказуемым, а строгая проверка — только перед выпуском.

Пример для релизной задачи:

code
ruff check --fix .
git diff --exit-code
ruff check .

Что с --unsafe-fixes?

У Ruff есть режимы, связанные с «unsafe fixes». Практически это означает: не все фиксы, которые Ruff умеет применять, одинаково безопасны для автоматической правки без ревью.

Правило команды можно сформулировать так:

  • По умолчанию: ruff check --fix без --unsafe-fixes.
  • Unsafe-fixes: только в отдельном, согласованном шаге (например, nightly или перед массовой реорганизацией кода), и обязательно с ревью/чекером диффа.

В pyproject.toml можно управлять частично и через выбор правил. Но окончательное решение «unsafe или нет» лучше закреплять не в голове, а в документации команды и в скриптах CI.

Автозамены ≠ форматирование

Частая ошибка — считать, что Ruff «всё приведёт к виду». Форматтер (Black, ruff format и т.п.) отвечает за формат. Ruff — за линтинг и часть структурных правок (и иногда — за импорты/связанные вещи).

Чтобы избежать гонки инструментов:

  • либо используйте единый форматтер и разрешите Ruff правки только там, где формат не затрагивается;
  • либо включайте в pipeline форматирование после фиксов, но тогда фикс должен быть устойчив к форматированию.

Обычно рабочий порядок для Python-проектов выглядит так:

  1. ruff check --fix (без unsafe)
  2. ruff format или black
  3. ruff check (финальная проверка)

Если вы используете Black, пример:

code
ruff check --fix .
black .
ruff check .

А лучше — зафиксировать один порядок и не менять его без причины: иначе в диффах будет «шум», и команда начнёт отключать проверки.


Выбор набора правил под стиль команды: практическая методика

1) Не выбирайте правила «из головы». Соберите исходную базу качества

Перед тем как включать автозамены, полезно сделать «аудит» текущего состояния:

code
ruff check .

Затем соберите список правил/категорий, которые чаще всего:

  • уже дают полезные подсказки;
  • создают много шума и не дают ценности;
  • потенциально затрагивают места, где автозамена спорна.

Для команды это превращается в управляемую таблицу: что включаем сразу, что включаем постепенно, что игнорируем до тех пор, пока кодовая база не «очистится».

В Ruff удобно настраивать select и ignore. Но не делайте «ignore всего подряд» — он со временем начинает маскировать реальные проблемы.

2) Разделяйте правила по слоям жизненного цикла

В реальных проектах полезно вести политику примерно так:

  • Layer A (обязательные, высокое отношение пользы к шуму): F, базовые E, I.
  • Layer B (качество и потенциальные ошибки): B, часть правил о логике/ошибках.
  • Layer C (стиль/улучшения по вкусу): UP, расширенные flake8-*, сложные правила.

Тогда автозамены активируются прежде всего для Layer A и частично для Layer B. Layer C — либо без fix, либо с осторожным включением, когда команда договорилась о стиле.

3) Договоритесь о числовых параметрах: line-length, target-version, исключения

Неприятный нюанс: даже одинаковые правила могут давать разные результаты, если:

  • target-version не совпадает с реальным интерпретатором,
  • line-length отличен от того, что ожидает форматтер,
  • вы используете разные версии Ruff у разработчиков и в CI.

В продакшене минимум:

  • зафиксировать версию Ruff (в requirements-dev или lockfile);
  • закрепить target-version и line-length в pyproject.toml;
  • убедиться, что форматтер и Ruff используют совместимые параметры.

4) Настройте правила для разных директорий

Часто в проектах есть src/ и tests/ — требования к ним отличаются. Например, тестам проще простить некоторые вещи, но нельзя допускать очевидные ошибки.

Ruff позволяет задавать конфигурацию по файлам. Типовой пример: игнорировать некоторые предупреждения в тестах.

code
[tool.ruff.lint.per-file-ignores]
"tests/**/*.py" = ["S101"] # пример: asserts в тестах (условно)

Здесь главное — не превращать per-file-ignores в «корзину». Это должно быть точечное решение, закреплённое аргументом: «мы осознанно разрешаем X в тестах, потому что…».

5) Включите «правила для команды» через политику фиксов

Технически можно разрешить Ruff править многое, но культурно лучше разделить:

  • что разработчик должен чинить до отправки (pre-commit);
  • что будет автоматически чиниться в CI;
  • что требует отдельного ревью.

Практическая политика:

  • обязательные исправления → pre-commit / local --fix;
  • остальные исправления → CI проверяет, что код после фикса идемпотентен;
  • unsafe-fixes → только по решению команды, в отдельном релизном процессе.

Интеграция в релизный пайплайн: контроль качества перед выпуском

Модель контроля: «быстро локально, строго в CI, идеально перед релизом»

Релизный пайплайн обычно состоит из стадий: сборка, тесты, линтинг, security scanning. Ошибки качества на ранних стадиях полезны, но наиболее важен этап перед релизом — там вы исключаете ситуации, когда «вроде всё прошло», но код несогласован с контрактом репозитория.

Рекомендуемый сценарий с Ruff:

  1. On PR (быстро):
    • ruff check (без --fix);
    • опционально ruff format --check (или black --check).
  2. Перед релизом (строго):
    • ruff check --fix (без unsafe);
    • проверка идемпотентности git diff --exit-code;
    • ruff check финально;
    • форматирование (если вы не форматируете в CI автоматически).

Это даёт эффект: если на сервере автозамены меняют код — значит в репозитории ещё не закреплены правила и команда должна согласовать дифф.

Пример пайплайна в GitHub Actions

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

      - uses: actions/setup-python@v5
        with:
          python-version: "3.11"

      - name: Install deps
        run: |
          pip install ruff
          pip install black

      - name: Ruff check (PR)
        if: github.event_name != 'release'
        run: |
          ruff check .

      - name: Format check (PR)
        if: github.event_name != 'release'
        run: |
          black --check .

      - name: Ruff fix + idempotency (release)
        if: github.event_name == 'release'
        run: |
          ruff check --fix .
          git diff --exit-code
          ruff check .
          black .
          git diff --exit-code

Если у вас GitHub не релиз, а тег, можно заменить условие. Смысл не в платформе, а в механике: на релизе вы обязаны получить чистое состояние после фиксов/форматирования.

Подводные камни: git diff и CI

  1. Чистый diff зависит от того, коммитите ли вы фиксы. В нашем сценарии мы предполагаем: CI не коммитит, а проверяет, что изменений быть не должно.
  2. Локальные правки и CRLF/LF могут создать «фальшивые» диффы. Это решается через настройки .gitattributes и единое окружение форматирования.
  3. Разные версии Ruff/Black ведут к разным фиксам. В продакшене лучше фиксировать версии.

Контроль качества: как измерять эффект и не утонуть в шуме

Индикатор 1: доля файлов, которые меняются на --fix

Если при включении --fix внезапно меняется половина репозитория — это не «автоматика», а потенциальный сбой в стратегии. Такой запуск лучше делать поэтапно:

  • сначала включить check без fix;
  • закрепить набор правил и исключения;
  • затем включить --fix и ожидать, что дифф будет локальным и предсказуемым.

Индикатор 2: число уникальных правил и динамика по времени

В проекте полезно вести список правил, которые добавились/убрали. Это можно делать через логирование конфигурации или через отчёты из Ruff.

Идея: команда должна видеть, что правила — управляемый продукт, а не «магия настройки навсегда».

Индикатор 3: стабильность результата (идемпотентность)

Один из самых практичных признаков зрелости настройки:

  • после ruff check --fix и последующего ruff check не должно быть новых правок, которые CI пытается снова применить.

Если идемпотентность «прыгает», обычно виноваты:

  • конфликт с форматтером;
  • нестабильные правила по версиям Python;
  • не совпадают исключения per-file;
  • разные версии Ruff.

Конкретные настройки: безопасный профиль для команды

Ниже — пример конфигурации, которую часто берут как основу для продакшена (адаптируйте под ваш код и форматтер).

code
[tool.ruff]
target-version = "py311"
line-length = 100
src = ["src", "tests"]
respect-gitignore = true

[tool.ruff.lint]
# Базовая стратегия: сначала полезное, потом расширения
select = [
  "E",
  "F",
  "I",
  "B",
  "UP",
]
ignore = [
  "E203", # пример: часто конфликтует с Black (условно)
  "W503", # пример: иногда конфликтует со стилями интерпретаций
  "E501", # если ограничение управляет форматтер
]

[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"] # импортов ради экспорта пакета

[tool.ruff.format]
# Если вы используете ruff format вместо black — согласуйте это
quote-style = "double"
indent-style = "space"

Дальше — набор команд для разработчика и CI:

  • локально:
    • ruff check --fix .
    • форматтер (black . / ruff format .)
  • в CI:
    • ruff check .
    • на релизе: ruff check --fix . && git diff --exit-code

Ошибки, которые чаще всего приводят к проблемам в продакшене

1) Включили fix для всего набора правил

Это ускоряет первую очистку, но потом ломает процесс: команда начинает бороться с диффами, а не с качеством.

Правильнее: стартовать с ограниченного набора правил и расширять.

2) Не согласовали Ruff и форматтер

Если Ruff применяет правки, которые меняют переносы/структуру, а форматтер — по другой логике, вы получите постоянный «маятник».

Стабилизируйте порядок: fix → format → check и держите его неизменным.

3) Разные версии Ruff в окружениях

Проблема часто всплывает на CI: разработчик сказал «у меня всё чисто», а CI прислал новые фиксы. В продакшене фиксируйте версии.

4) Нет «контракта» для команды по unsafe-fixes

Если кто-то включает unsafe-fixes локально и коммитит неожиданно большие изменения, а кто-то отключает — правила конфликта начинают происходить не в коде, а в коммуникации.

Нужна договорённость: unsafe-fixes — только по расписанию/решению/процессу.

5) Нет проверки идемпотентности

Если вы не проверяете «что было бы, если применить fix ещё раз», вы можете пропустить сценарии, когда фиксы зависят от очередности или от частично изменённых файлов.


Как выстроить процесс обучения команды (и зачем это нужно Ruff)

Ruff — инструмент, но качество — это процесс. Чтобы автозамены не превратились в «внезапные диффы», нужно:

  • короткое правило: как запускать fix локально;
  • точный порядок команд (и кто его определил);
  • политику по исключениям (per-file-ignores);
  • политику по unsafe-fixes;
  • практику: что делать, если Ruff предлагает исправление, но это влияет на читаемость/архитектуру.

Полезно выделить один рабочий сценарий для PR:

  1. ruff check . должен быть зелёным.
  2. Перед коммитом разработчик может выполнить ruff check --fix ..
  3. Если CI всё равно правит — значит разработчик не прогнал те же шаги, либо конфигурация несовместима с окружением.

Так вы формируете привычку и минимизируете «неожиданные правки».


Вывод: Ruff как механизм контроля качества, а не просто набор правил

Ruff в продакшене — это не про «настроить линтер», а про построение цепочки доверия: какие правила считаются обязательными, какие исправляются автоматически, как предотвращаются конфликты с форматированием и как CI/релиз подтверждает, что код соответствует контракту.

Ключевые принципы, которые стоит закрепить в документации команды:

  • автозамены включайте постепенно и ограничивайте риск;
  • отделяйте fix от форматирования и фиксируйте порядок fix → format → check;
  • делайте релизный шаг строгим: применить fix и проверить идемпотентность;
  • согласуйте конфигурацию, версии инструментов и исключения;
  • ведите правила как управляемый актив (обсуждение, расширение, исключения по аргументам).

Если вы хотите глубже разобраться в том, как системно подходить к настройке и внедрению Ruff в кодовую базу (включая практики организации правил и работы с fix), можно дополнительно изучить материал в рамках курса: [ /course/ ] — как один из способов упорядочить знания и быстрее довести настройки до «рабочего уровня команды», а не до разового эксперимента.

Войдите, чтобы поставить лайк и оставить комментарий.

Автор

$ sudo teach IT

Продолжите обучение

Все курсы
Python – для начинающих!

Python – для начинающих!

С нуля до профессионального уровня. Подходит для всех. Учитесь каждый день и овладейте самым популярным языком программирования.

Перейти к курсу

Приложения для iPhone и Apple Watch на SwiftUI

Разработка приложений для iPhone и Apple Watch на SwiftUI: навигация, SwiftData, виджеты, часы, выпуск. Нужен Mac с Xcode 27, сами устройства не нужны.

Перейти к курсу
Ботостроение Telegram

Ботостроение Telegram

Лёгкий, быстрый и доступный способ познакомиться с миром ботостроения в Telegram. Видео, конспекты, практика и помощь – всё у нас на курсе.

Перейти к курсу

Приложения для macOS на SwiftUI

Разработка приложений для Mac на SwiftUI: окна и меню, Liquid Glass, SwiftData, сеть, выпуск. Нужен Mac с macOS 27 и Xcode 27.

Перейти к курсу

Другие статьи

Typer для API-подобных CLI: зависимости, подкоманды и формирование “контракта” команды
typer

Typer для API-подобных CLI: зависимости, подкоманды и формирование “контракта” команды

Покажем, как сделать CLI предсказуемым: единый стиль флагов, повторное использование зависимостей и корректные ответы об ошибках. Статья поможет превратить утилиты в инструменты для команды.

26 июля 2026 г.
510
CLI как инструмент команды: UX текста, exit codes и обработка конфигов
инструмент

CLI как инструмент команды: UX текста, exit codes и обработка конфигов

Сделаем CLI “дружелюбным”: читабельные сообщения, help-текст, стабильные exit codes и корректная загрузка конфигов. Разберём сценарии ошибок, которые чаще всего забывают в небольших утилитах.

25 июля 2026 г.
510
Создание Telegram бота в 2026 легко и просто! Полный курсы!
создание

Создание Telegram бота в 2026 легко и просто! Полный курсы!

19 июня 2026 г.
1231
Что такое переменные, типы и условия в коде: объясню без матана на примерах
такое

Что такое переменные, типы и условия в коде: объясню без матана на примерах

Разберём ключевые понятия для старта — переменные, типы данных, сравнения и условные операторы — простыми словами и на бытовых примерах. В конце соберём мини-скрипт, который принимает решение по введённым данным.

30 сентября 2026 г.
10
FastAPI и фоновые задачи: когда лучше использовать BackgroundTasks, а когда очередь
fastapi

FastAPI и фоновые задачи: когда лучше использовать BackgroundTasks, а когда очередь

Поймём различия между синхронной обработкой, BackgroundTasks и внешними очередями. Разберём idempotency, ретраи и мониторинг фоновых процессов.

22 июля 2026 г.
830
Нужно ли мне знать математику, чтобы начать программировать?
знать

Нужно ли мне знать математику, чтобы начать программировать?

Разберём, где математика реально нужна (и где нет) для новичка: основы Python/веб/автоматизация/аналитика. В конце составим понятный маршрут обучения без лишней теории и подскажем, что повторить, если вы чувствуете пробелы.

28 сентября 2026 г.
50

Комментарии

Пока нет комментариев

Содержание

Почему именно Ruff и где он «ломается», если сделать по-быстромуНастройка Ruff для безопасных автозамен (fix)Базовая идея: сначала выберите, что считать «исправляемым»Вариант 1: фикс только безопасных изменений и проверка идемпотентности в CIВариант 2: фикс по желанию в отдельном шаге (и отдельная политика)Что с --unsafe-fixes?Автозамены ≠ форматированиеВыбор набора правил под стиль команды: практическая методика1) Не выбирайте правила «из головы». Соберите исходную базу качества2) Разделяйте правила по слоям жизненного цикла3) Договоритесь о числовых параметрах: line-length, target-version, исключения4) Настройте правила для разных директорий5) Включите «правила для команды» через политику фиксовИнтеграция в релизный пайплайн: контроль качества перед выпускомМодель контроля: «быстро локально, строго в CI, идеально перед релизом»Пример пайплайна в GitHub ActionsПодводные камни: git diff и CIКонтроль качества: как измерять эффект и не утонуть в шумеИндикатор 1: доля файлов, которые меняются на --fixИндикатор 2: число уникальных правил и динамика по времениИндикатор 3: стабильность результата (идемпотентность)Конкретные настройки: безопасный профиль для командыОшибки, которые чаще всего приводят к проблемам в продакшене1) Включили fix для всего набора правил2) Не согласовали Ruff и форматтер3) Разные версии Ruff в окружениях4) Нет «контракта» для команды по unsafe-fixes5) Нет проверки идемпотентностиКак выстроить процесс обучения команды (и зачем это нужно Ruff)Вывод: Ruff как механизм контроля качества, а не просто набор правил