В этом посте я расскажу, как настроить protolint для проверки .proto файлов на соответствие официальному style guide в GitHub Actions и поделюсь практическим опытом его использования.
Введение
Этот пост продолжает первую часть. Сохранение единообразия оформления кода в .proto файлах — задача не менее важная, чем обеспечение обратной совместимости. Я рассмотрю возможности protolint — инструмента для проверки соответствия кода ваших .proto файлов официальному style guide от Google и другим рекомендациям. Обсудим, как единый стиль облегчает его сопровождение, а также минимизирует вероятность ошибок. На примерах я рассмотрю, как настроить и интегрировать Protolint в GitHub Actions.
Protolint — полезный инструмент, он помогает проверять .proto файлы и даже вносить автоматические исправления, если было обнаружено несоответствие с установленным стилем. Также в нем есть возможность настраивать свои правила. Protolint поддерживает интеграции с:
protoс плагином;
редакторами кода (плагинами);
GitHub Actions (готовыми actions);
инструментами CI.
Для локальной разработки я активно пользуюсь protlint плагином для IntelliJ IDEA, что помогает мне проверять code style для .proto файлов непосредственно во время редактирования кода. В контексте интеграции с GitHub Actions воспользуемся его бинарной версией.
Настройка protolint
Приступим к настройке. Для начала настроим собственный стиль .proto файлов. Создадим .protolint.yml файл в корне проекта со следующими настройками:
lint:
rules:
all_default: true
remove:
- FILE_HAS_COMMENT
rules_option:
max_line_length:
max_chars: 120
field_names_exclude_prepositions:
excludes:
- date_from
- date_to
Разберём его содержимое.
all_default: настройка установлена в true — это означает, что будут включены все стандартные и дополнительные правила.
remove: в этом разделе перечисляются правила, которые необходимо отключить. В данном случае с указанием FILE_HAS_COMMENT отключается правило, требующее, чтобы каждый .proto файл содержал комментарий на уровне файла.
rules_option: этот раздел позволяет настроить определенные параметры для конкретных правил.
max_line_length: устанавливает максимальную допустимую длину строки в 120 символов (по умолчанию 80).
field_names_exclude_prepositions: исключает из правила требование, чтобы имена полей не содержали предлогов. В данном случае date_from и date_to исключены из этого правила.
Вы можете использовать эти и другие настройки в своих проектах. Все настройки описаны в разделе Rules репозитория protolint.
Следующим этапом создадим файл protolint_check.yml в папке .github/workflows со следующим содержимым:
name: Protolint Check
on: [pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Download protolint
run: |
wget https://github.com/yoheimuta/protolint/releases/download/v0.46.3/protolint_0.46.3_linux_amd64.tar.gz
tar -zxvf protolint_0.46.3_linux_amd64.tar.gz
- name: Run protolint
run: ./protolint ./bankdemo
Разберём его содержимое.
Триггер on: pull_request будет запускаться при создании, обновлении или закрытии pull request.
Checkout code: клонирование кода репозитория.
Download protolint: загрузка и разархивирование protolint в директорию проекта.
Run protolint: запуск проверки в директории bankdemo.
Тест protolint
Для теста я создал pull request с изменениями, нарушающими установленный стиль. Например, в названии новой переменной postalСode вместо snake_case я использовал CamelCase и добавил новую константу в enum без префикса наименования enum EXTRACTING_STRATEGY.
На скриншоте видно, что protolint обнаружил все несоответствия для установленного стиля.
Protolint на практике
Хочу также поделиться опытом использования protolint в реальном проекте. С необходимостью проверок protolint при работе с .proto файлами я столкнулся в проекте, где была общая библиотека. В этой библиотеке было реализовано перечисление enum, которое использовалось для сортировки данных. Реализация выглядела следующим образом:
// Направление сортировки
enum SortOrder {
asc = 0;
desc = 1;
}
Казалось бы, всё просто и понятно, но на практике это перечисление стало источником путаницы и ошибок. Дело в том, что в gRPC по умолчанию используется концепция null safety. Это означает, что, если значение не установлено, оно автоматически принимает значение по умолчанию. В случае с enum в Protocol Buffers значение по умолчанию — это первое значение, указанное в перечислении.
В примере SortOrder, если значение явно не устанавливается в запросе, будет возвращаться значение SortOrder.asc. Это привело к тому, что неявно все запросы получали сортировку по возрастанию, что искажало логику приложения.
Пример кода получения значения SortOrder:
// Если sortOrder не установлен, вернется SortOrder.asc
SortOrder sortOrder = request.getSortOrder();
Чтобы корректно обрабатывать такие случаи, в Java-коде пришлось прибегнуть к проверке наличия значения:
SortOrder sortOrder = null;
if (request.hasSortOrder()) {
sortOrder = request.getSortOrder();
}
Эта проверка вносит дополнительную сложность в код, и возникает вероятность ошибки, если забыть выполнить проверку.
При проверке .proto файла SortOrder - protolint выводит следующие ошибки:
C учетом найденных ошибок реализация SortOrder была улучшена:
// Направление сортировки
enum SortOrder {
// Не определено
SORT_ORDER_UNSPECIFIED = 0;
// По возрастанию
SORT_ORDER_ASC = 1;
// По убыванию
SORT_ORDER_DESC = 2;
}
После исправления ошибок проверка protolint проходит успешно. Теперь при вызове request.getSortOrder() будет возвращаться SORT_ORDER_UNSPECIFIED для неустановленного значения, что устраняет неоднозначность. Включение protolint с самого начала разработки библиотеки позволило бы избежать ошибок сортировки.
Заключение
В примерах мы рассмотрели, как использование protolint обеспечивает единообразие стиля ваших .proto файлов. С помощью protolint вы упрощаете внесение изменений в код и предотвращаете потенциальные ошибки.