Следование style guide для .proto файлов с помощью protolint в GitHub Actions
В этом посте я расскажу, как настроить protolint для проверки .proto файлов на соответствие официальному style guide в GitHub Actions и поделюсь практическим опытом его использования.
Введение
Этот пост продолжает первую часть. Сохранение единообразия оформления кода в .proto файлах — задача не менее важная, чем обеспечение обратной совместимости. Я рассмотрю возможности protolint — инструмента для проверки соответствия кода ваших .proto файлов официальному style guide от Google и другим рекомендациям. Обсудим, как единый стиль облегчает его сопровождение, а также минимизирует вероятность ошибок. На примерах я рассмотрю, как настроить и интегрировать Protolint в GitHub Actions.
Protolint — полезный инструмент, он помогает проверять .proto файлы и даже вносить автоматические исправления, если было обнаружено несоответствие с установленным стилем. Также в нем есть возможность настраивать свои правила. Protolint поддерживает интеграции с:
Для локальной разработки я активно пользуюсь 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 вы упрощаете внесение изменений в код и предотвращаете потенциальные ошибки.