При ревью запроса на слияние периодически приходится сталкиваться с подозрительными изменениями go.mod и go.sum. Например, когда изменяется только один файл из двух, или когда в Go коде мы не видим то, что могло бы привести к изменениям go.mod и go.sum.

В таких случаях возникают закономерные вопросы: нужны ли эти изменения? почему они появились?

Что могло пойти не так?

  1. Изменения случайно попали в коммит.
  2. Коллега забыл добавить один из файлов в коммит.
  3. Коллега забыл запустить go mod tidy после удаления зависимости.
  4. Кто-то в прошлом сделал коммит с проблемой из первых 3-х пунктов.
  5. Или, может быть, всё хорошо, и коллега обновил версию Go в go.mod или обновил версию зависимости.

Чтобы не проверять вручную первые 4 пункта, можно автоматизировать проверку актуальности состояния файлов go.mod и go.sum.

На примере Gitlab CI такое задание может выглядеть так:

image: golang:1.21.5

stages:
    - check

check-go-dependencies:
    stage: check
    script:
        - go mod tidy
        - git diff --exit-code
  • go mod tidy — это команда, которая приведет в соответствие исходный кода модуля и файлов go.mod и go.sum.
  • git diff --exit-code — эта команда покажет различия между закоммиченными файлами и файлами, получившимися после предыдущей команды. Если различия есть, то благодаря флагу --exit-code ненулевое значение кода выхода приведёт к завершению задания с ошибкой.

Это задание простое в реализации, но если оно падает с ошибкой, то не понятно, что с этим делать. Хорошо бы добавить полезную информацию для коллег или себя из будущего о том, как эту проблему можно решить. Поэтому внесем некоторые доработки в проверку:

image: golang:1.21.5

stages:
    - check

check-go-dependencies:
    stage: check
    script:
        - go mod tidy
        - |
            git diff --exit-code && exit 0 || true
            echo -e "\033[0;31m"
            echo '######################################################################'
            echo
            echo "ERROR: go.mod or go.sum is different from the committed version"
            echo "Try using 'go mod tidy' to fix the go.mod and go.sum files"
            echo "Also, don't forget to commit and push changes"
            echo
            echo '######################################################################'
            exit 1            

Как это работает?

  1. В начале — всё тот жеgo mod tidy, а дальше интересней.
  2. Так как пайплайн завершается при первой же ошибке, сложно разложить проверку на отдельные вызовы команд. Решаем это через многострочный скрипт, используя- |.
  3. Далее, в случае еслиgit diff --exit-codeничего не находит, то выходим с нулевым кодом exit 0. А вот если код выхода не нулевой, то перехватываем и пропускаем его за счет командыtrue.
  4. Следом устанавливаем красный цвет для сообщения об ошибке, выводим нужное сообщение и выходим с ненулевым кодом, чтобы задание завершилось с ошибкой.

Такое задание закрывает основные потребности проверки актуальности go.mod и go.sum. Вывод подробного сообщения об ошибке помогает улучшить пользовательский опыт и снизить количество вопросов, возникающих при падении задания. Дополнительно текст сообщения напоминает нам и коллегам о варианте исправления проблемы командой go mod tidy.