В этом посте я расскажу, как настроить 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.

Workflow Protolint Check завершился с ошибкой
Workflow Protolint Check завершился с ошибкой
Ошибки в логах
Ошибки в логах

На скриншоте видно, что 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 выводит следующие ошибки:

Ошибки в .proto файле SortOrder
Ошибки в .proto файле SortOrder

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 вы упрощаете внесение изменений в код и предотвращаете потенциальные ошибки.

Комментарии (0)