Этот пост является частью серии постов, в которых мы создадим полную систему Python CI/CD, способную запускать тесты для нескольких проектов. В каждом посте мы будем освещать определенную концепцию.

Качество кода — одна из наиболее важных вещей, которую команда разработчиков программного обеспечения должна обеспечить хорошей ремонтопригодностью решений, над которыми работает команда. В технологической отрасли наблюдается высокий уровень текучести кадров по сравнению с другими отраслями, и обеспечение стандарта качества кода на постоянной основе может помочь в управлении временем до продуктивной работы новых разработчиков и общим техническим долгом.

Сканирование качества кода полностью предотвратит проблемы? Нет, но словами Tesco; "Каждый по нитке".

Введение в пилинт

Вместо того, чтобы пытаться объяснить себе, что такое pylint, вот прямо из первых уст:

Pylint — это инструмент статического анализа кода Python, который ищет ошибки программирования, помогает обеспечить соблюдение стандарта кодирования, выявляет запахи кода и предлагает простые предложения по рефакторингу.

Pylint — это предпочтительный инструмент для сканирования проектов на основе Python, помогающий выявить вышеупомянутые запахи кода и потенциальные улучшения. Одна из его потенциально неизвестных функций заключается в том, что вы можете создавать свои собственные плагины для pylint, которые могут помочь вашей команде обеспечить соблюдение определенных стилистических требований для конкретной команды. Например, возможно, вашей команде требуется определенная проверка pylint, чтобы убедиться, что ваш исходный код содержит заявление об авторских правах или лицензии. Если будет какой-то спрос, я мог бы сделать пост на эту тему.

Скрипт или не скрипт

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

https://github.com/marketplace/actions/github-action-for-pylint

Если вы пойдете по этому пути, вам может понадобиться файл .pylintrc, а может и не понадобиться. Файл .pylintrc — это файл конфигурации для pylint, который позволяет вам статически устанавливать параметры для pylint, чтобы избежать их передачи при каждом вызове cli.

Обеспечение минимального балла для ваших команд pylint

Существует очень большое количество предупреждений и ошибок в правилах оценки pylints, которые в зависимости от стиля кода вашей команды могут быть разрешенной практикой. Одним из примеров этого является ошибка слишком длинной строки.

В идеале лучшее, что можно сделать, — это определить как команду, какие ошибки будут пропущены, а затем поместить все эти ошибки в файл .pylintrc, но в зависимости от сроков и зрелости команды вы, возможно, захотите вместо этого быстро выполнить задание. но позвольте этому пройти для счета выше порога качества. Для этого урока предположим, что порог равен 8,00.

Чтобы сделать вышеперечисленное, нам нужно вместо этого запустить pylint в скрипте, а затем выполнить немного магии bash с awk и grep, чтобы проанализировать значение оценки из стандартного вывода. После анализа значения оценки все, что нужно, — это сравнить его с пороговым значением. Если он превышает его? Буэно, выходи успешно.

Быстрый старт с Pylint

Как правило, вы будете устанавливать Pylint через Pip либо через файл requirements.txt, либо как часть вашего файла setup.py. Чтобы установить его по запросу, используйте следующую команду:

pip install pylint

Далее нам понадобится некоторый код для запуска. Мне нравится использовать реальные практические примеры, поэтому вместо какого-то a+b примера сценария мы собираемся использовать этот пример быстрого запуска для FastAPI. Для небольшого контекста FastAPI — это пакет для создания современных строго типизированных API-сервисов. Вот ссылка, если вы хотите узнать больше: https://fastapi.tiangolo.com/

А теперь для примера API мы запустим pylint:

from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
    return {"message": "Hello World"}

Источник: https://fastapi.tiangolo.com/tutorial/first-steps/

Перед запуском pylint, чтобы убедиться, что мы не получаем никаких ошибок об отсутствующих модулях, также установите FastAPI с помощью следующей команды:

pip install fastapi

А затем запустите Pylint для приведенного выше кода, сохраненного в файле с именем production_api:

pylint production_api.py
************* Module production_api
production_api.py:8:0: C0304: Final newline missing (missing-final-newline)
production_api.py:1:0: C0114: Missing module docstring (missing-module-docstring)
production_api.py:7:0: C0116: Missing function or method docstring (missing-function-docstring)
------------------------------------------------------------------
Your code has been rated at 2.50/10 (previous run: 2.50/10, +0.00)

И точно так же у нас есть несколько быстрых отзывов о том, как улучшить удобство обслуживания этого конкретного файла Python.

Pylint можно использовать для работы со многими файлами, используя обозначения с подстановочными знаками, такие как pylint **/*.py (сканировать все файлы python во всех каталогах верхнего уровня из этого каталога)

После внесения некоторых быстрых исправлений скрипт теперь выглядит так, и оценка улучшилась:

-------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: 2.50/10, +7.50)

Заключение и сценарий сборки

С учетом вышеизложенного вы должны иметь возможность запустить сканирование вашего кода с помощью pylint и создать задание как часть вашей общей матрицы сборки. Теперь ваш вопрос будет в том, должен ли он оставаться там? В зависимости от ограничений ресурсов для вашей среды CI/CD вы можете решить, давайте проведем все это сканирование до того, как мы выполним CI/CD, и если это так, я планирую также рассказать об использовании pylint как части git-хука.

В эту статью включен сценарий bash, который вы можете подключить и использовать для своей системы CI/CD. Скрипт выполнит сканирование pylint для каждого проекта в вашем репозитории (например, если у вас есть монорепозиторий с несколькими проектами), и если какой-либо проект выйдет из строя, скрипт зафиксирует этот сбой.

Чтобы продемонстрировать это, я создал новый репозиторий с двумя проектами: учебным проектом Flask и файлом fastapi, определенным выше, но помещенным в отдельный проект. Fastapi пройдет, как мы исправили ранее, но новый проект flask завершится ошибкой.

./.cicd/pylint.sh
Starting a script to run pylint on python files.
[flask_tutorial]
>Running Pylint scan for flask_tutorial python package
>Pylint score for flask_tutorial is 5.00
>Your commit has a pylint score lower than 8.25
FAILURE : [1]
[fastapi]
>Running Pylint scan for fastapi python package
>Pylint score for fastapi is 10.00
>Pylint score 10.00 greater than min required score: 8.25; Success!
Pylint Run Complete.  Final Status 1