Линтер на все случаи жизни — GitHub Super Linter

Команда DevOps инженеров из GitHub поделились своим универсальным решением для проверки качества кода. С ним можно настроить линтер для 17 языков всего в 11 строк:

name: Lint Code Base on: push: branches-ignore: - 'master' jobs: linter: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: docker://github/super-linter:v2.1.0

Код выше является YAML конфигурацией для GitHub Actions (бесплатный CI/CD от GitHub) и далее мы разберемся с его содержимым и принципом работы.

Мотивация

Данный проект изначально является внутренней разработкой GitHub:

GitHub Super Linter был создан командой DevOps GitHub Services для обеспечения согласованности нашей документации и кода для повышения продуктивности взаимодействия и совместной работы в компании.
Лукас Гравли, 2020

Проблема

  1. Для каждого языка существует отдельный линтер, а иногда несколько
  2. В каждой экосистеме настройка линтера отличается

Настройка линтера это важная часть любого проекта, с более чем 1 участником. Он помогает приводить код к единому стандарту, во избежание недопониманий и разногласий между разработчиками.

Я могу судить из мира JS, где настройка линтера и CI/CD занимает 10-20 минут. Устанавливаем eslint (обычно в связке с prettier), и настраиваем список правил. Ничего сложного, но то версия eslint обновилась, то какой-то плагин нужно доустановить, то транспайлер ругается, в общем оставшиеся 9 минут 30 секунд занимаешься отладкой.

Не так уж и страшно и даже полезно потратить 10 минут на ручную настройку, но только вот в случае с монорепо, это превращается в ад. Я не являюсь сторонником использования монореп, но они есть и с ними нужно жить и работать ¯(ツ)/¯

Решение

Обнародованный в open source super-linter интегрированный в CI/CD может автоматически определять и проверять код на следующих языках:

  • Ansible (ansible-lint)
  • CSS (stylelint)
  • CoffeeScriptc(offeelint)
  • Dockerfile (dockerfilelint)
  • Golang (golangci-lint)
  • JavaScript (eslint standard js)
  • JSON (jsonlint)
  • Markdown (markdownlint
  • Perl (perl)
  • Python3 (pylint)
  • Ruby (RuboCop)
  • Shell (Shellcheck)
  • Terraform (tflint)
  • TypeScript (eslint standard js)
  • XML (LibXML)
  • YAML (YamlLint)
  • ENV (dotenv-linter)

Следовательно, если в проекте наблюдается смешивание стеков, то вполне рекомендуется посмотреть в сторону super-linter. Достаточно спорный момент насчет его использования в проектах с одним языком/фреймворком. Проекты с претензией на универсальность всегда несут за собой ограничения и потерю гибкости. Это немного из философии, ведь поиск глубины требуемой абстракции может привести к ассемблеру, или же остановится на JS. Я бы выбирал исходя из задачи:

  • нет времени объяснять, нужен линтер за 30 секунд — подключили super-linter
  • можно продумать список правил и подстроить под текущее окружение — я бы пробовал точечное решение

Реализация

GitHub Super Linter — это репозиторий исходного кода, упакованный в контейнер Docker и вызываемый из GitHub Actions.

Принцип работы

При триггере CI/CD выполняется workflow, описанный конфигом из начала статьи:

# Название name: Lint Code Base # Определение триггера для запуска CI/CD on: # Триггер на push любого коммита в ветку push: # Игнорирование ветки `master` branches-ignore: - 'master' # Задачи к выполнению jobs: # Задача linter: # Сборка окружения ubuntu-latest runs-on: ubuntu-latest # Шаги задачи steps: # Переключение на текущую ветку (обязательное действие, если нужен доступ к файлам репозитория) - uses: actions/checkout@v2 # Вызов Super Linter - uses: docker://github/super-linter:v2.1.0

Только последняя строка вызывает super-linter, и дальше мяч переходит на его сторону. Внутри происходит примерно следующее:

  1. Поднимается Docker-контейнер и устанавливает в себя требуемые окружения с соответствующими линтерами
  2. Следом собираются все переданные данные о правилах и настройках
  3. Запускается Bash скрипт,
    • собирает переданный конфиг
    • анализирует файлы на принадлежность к языку/фреймворку (по расширению файла)
    • запускает соответствующий линтер на каждом файле
    • генерирует отчет

До банальности просто и работает:

NOTE: Я например для реализации такого же функционала настраивал CI на работу с конкретными папками, содержащими тот или иной тип файлов. У меня не было таких случаев, чтобы в папке с JS, обнаруживались файлы .cs. Работало так же, и пожалуй более оптимизировано, чем перебор всех файлов, но кто я такой против GitHub DevOps team

Вывод

Стратегия Microsoft(GitHub) — публиковать свои наработки в open source очень похвальная затея, хотя у некоторых возникают сомнения на этот счет. Результатом таких действий является и GitHub Super Linter. На мой взгляд это не что-то революционное, а просто еще один проект на GitHub, но с отметкой made with in GitHub.

P.S. Использование standardjs в качестве линтера для JS/TS в 2020 году, это как-то обескураживает. Думаю это объяснимо как GitHub === enterprise === legacy, и код опубликован как есть, вот и получили технологию 5-летней давности. Уже создан issue, предлагаю поддержать или даже поконтрибьютить.

Источник