Как использовать GoReleaser для автоматизации выпусков сборки GoLang
11 апреля 2022 г.Чтобы сделать проект более удобным и привлекательным, авторы добавляют образы докеров и делают сборки дистрибутива для множества разных платформ. Требуется для каждой новой версии проекта, даже минорной. Поэтому необходимо писать автоматизацию этого процесса, потому что делать это вручную очень долго и рутинно и легко ошибиться или что-то забыть. Ниже я расскажу о GoReleaser, который практически бесплатно автоматизирует сборку релизов проектов golang.
В статье все примеры будут для GitHub. Но эти же методы могут быть легко адаптированы
закрывать проекты тоже.
Я подготовил простой проект, чтобы продемонстрировать возможности GoReleaser. Этот проект состоит из двух частей клиентской и серверной. Сервер может подсчитывать количество слов
в тексте, и клиент может обратиться к серверу с запросом на количество слов.
Мне нужно сделать использование приложения максимально удобным для пользователя, и мне потребуется:
- бинарный сервер (mac/linux/windows)
- бинарный клиент (mac/linux/windows)
:::Информация
GoReleaser — утилита, написанная на Go, которая может выполнять все эти действия на основе простого yaml-скрипта (на самом деле утилита еще может делать много полезного).
После установки на вашу ОС вам нужно запустить команду для начала работы:
```javascript
инициализация goreleaser
• Создание файла .goreleaser.yaml
• конфиг создан; пожалуйста, отредактируйте в соответствии с вашими потребностями file=.goreleaser.yaml
Эта команда создает файл .goreleaser.yaml
в корне проекта. Пока он пуст и ничего не делает, и я должен его заполнить. Так,
```javascript
Это пример файла .goreleaser.yml с некоторыми разумными значениями по умолчанию.
Обязательно ознакомьтесь с документацией на https://goreleaser.com
до:
крючки:
Вы можете удалить это, если не используете модули go.
- приведи мод в порядок
вы можете удалить это, если вам не нужно идти генерировать
- иди генерируй ./...
строит:
- среда:
- CGO_ENABLED=0
сладкие:
- линукс
- окна
- Дарвин
архивы:
- замены:
Дарвин: Дарвин
линукс: линукс
окна: окна
386: и386
амд64: x86_64
контрольная сумма:
name_template: 'контрольные суммы.txt'
снимок:
name_template: "{{ incpatch .Version }}-следующий"
журнал изменений:
сортировка: по возрастанию
фильтры:
исключать:
- '^документы:'
- '^ тест:'
Начну с описания раздела builds. Он определяет сборки go, которые должны быть запущены. Это создаст нужные нам двоичные файлы. Опишем это:
```javascript
строит:
- идентификатор: срв
двоичный файл: срв
среда:
- CGO_ENABLED=0
сладкие:
- линукс
- окна
- Дарвин
основной: ./cmd/сервер/main.go
- идентификатор: кли
бинарный: кли
среда:
- CGO_ENABLED=0
сладкие:
- линукс
- окна
- Дарвин
основной: ./cmd/client/main.go
В этой конфигурации я установил две сборки, потому что необходимо собрать сервер и клиент. Обе сборки выглядят примерно одинаково. Я указываю, какой main.go
следует использовать и как следует вызывать полученный двоичный файл.
Также я указал GOOS и перечислил платформы, для которых мне нужно собрать бинарники, то есть в результате должно получиться не один файл клиента и сервера, а три: Linux, Mac и Windows. Если бы построение производилось вручную, это выглядело бы так:
```javascript
CGO_ENABLED=0 GOOS=darwin go build -o srv
Это пример только для Mac и только для сервера. То есть один корпус из 6. Помимо ОС можно указать еще и архитектуры:
```javascript
гоарх:
- amd64
- рука
- рука64
И потом, каждая ОС все равно будет собирать дополнительный бинарник для каждой архитектуры. Чтобы не собирать какие-то конкретные пары ОС/архитектура, которые вам не нужны, нужно указать их в списке:
```javascript
игнорировать:
- гус: Дарвин
гоарх: 386
- гус: линукс
гоарх: рука
гоарм: 7
В своем примере я этого делать не буду, чтобы не усложнять понимание результата большим количеством результирующих файлов. Позже читатель сможет добавить это в свои реальные проекты. Также часто могут быть затронуты дополнительные переменные среды. Например, в своих последних проектах я использовал GOPROXY, GOPRIVATE. Все их можно указать в разделе env
, который для каждой сборки отдельный.
Позвольте мне показать вам, как работает строительство:
```javascript
выпуск goreleaser --skip-publish --snapshot
• освобождение...
• загрузка конфигурационного файла file=.goreleaser.yaml
• загрузка переменных окружения
• получение и проверка состояния git
• игнорирование ошибок, поскольку это моментальный снимок error=git не содержит никаких тегов. Либо добавьте тег, либо используйте --snapshot
• создание... commit=87eea7148d7e07b947cdef49e0b1b6a8c406a60e последний тег=v0.0.0
• ошибка пропущенного канала = отключено в режиме моментального снимка
• тег синтаксического анализа
• бег перед крюками
• бегущий хук = иди мод аккуратно
• работающий хук=иди сгенерируй ./...
• установка значений по умолчанию
• моментальные снимки
• создание моментального снимка... версия=0.0.1-следующая
• проверка каталога дистрибутива
• загрузка информации о моде
• создавать предварительные условия
• написание эффективного конфигурационного файла
• запись config=dist/config.yaml
• создание двоичных файлов
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/srv_darwin_arm64/srv
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/srv_linux_amd64/srv
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/srv_windows_386/srv.exe
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/srv_linux_arm64/srv
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/srv_windows_arm64/srv.exe
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/srv_windows_amd64/srv.exe
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/srv_linux_386/srv
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/srv_darwin_amd64/srv
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/cli_windows_386/cli.exe
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/cli_windows_amd64/cli.exe
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/cli_linux_386/cli
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/cli_linux_amd64/cli
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/cli_linux_arm64/cli
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/cli_darwin_amd64/cli
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/cli_darwin_arm64/cli
• сборка бинарника=/Users/antgubarev/project/gorelex/dist/cli_windows_arm64/cli.exe
• архивы
• создание архива=dist/gorelex_0.0.1-next_Linux_x86_64.tar.gz
• создание архива=dist/gorelex_0.0.1-next_Linux_arm64.tar.gz
• создание архива=dist/gorelex_0.0.1-next_Darwin_x86_64.tar.gz
• создание архива=dist/gorelex_0.0.1-next_Darwin_arm64.tar.gz
• создание архива=dist/gorelex_0.0.1-next_Windows_arm64.tar.gz
• создание архива=dist/gorelex_0.0.1-next_Windows_i386.tar.gz
• создание архива=dist/gorelex_0.0.1-next_Linux_i386.tar.gz
• создание архива=dist/gorelex_0.0.1-next_Windows_x86_64.tar.gz
• вычисление контрольных сумм
• хранение списка артефактов
• запись файла=dist/artifacts.json
• релиз успешен через 3,39 с
Из журнала видно, какие файлы были собраны и что все они находятся в каталоге /dist
. Я передал два аргумента в начале команды:
--skip-publish
По умолчанию GoReleaser немедленно публикует файлы. Это пока не требуется, так как мы все еще занимаемся отладкой, но нам это понадобится позже.
--snapshot
Выпуск должен быть создан с версией. GoReleaser берет версию из последнего тега git. И так как еще нет, мне нужен этот флаг.
Оба эти флага будут часто требоваться при подготовке и отладке будущих выпусков. Иногда я использую черновой репозиторий на GitHub, где будут публиковаться релизы. Так что у меня есть возможность редактировать и улучшать свою систему выпуска, не затрагивая пользователей. Очень рекомендую поступить так же.
:::Информация
Как вы могли заметить, в дополнение к файлам сборки также были заархивированы. Это следующая возможность поговорить. Архив должен содержать все, что нужно вашему пользователю для использования продукта. В текущем примере это файл сервера и клиента.
По умолчанию имя архива создается с использованием следующего шаблона {{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}
(вы также можете заменить этот шаблон для ваших нужд). В разделе замены указаны соответствующие замены для переменных в шаблоне. По умолчанию этот параметр пуст, но, к счастью, в созданном .goreleaser.yaml
уже указаны комбинации, которых достаточно.
Текущие созданные архивы содержат файлы srv и client. Иногда может быть необходимо иметь их в разных архивах. Это можно легко сделать:
```javascript
архивы:
идентификатор: срв
строит:
- срв
замены:
Дарвин: Дарвин
линукс: линукс
окна: окна
386: и386
амд64: x86_64
name_template: "{{ .ProjectName }}srv{{ .Version }}{{ .Os }}{{ .Arch }}"
файлы:
- ЛИЦЕНЗИЯ
- README.md
- документ/сервер/*
идентификатор: кли
строит:
- кли
замены:
Дарвин: Дарвин
линукс: линукс
окна: окна
386: и386
амд64: x86_64
name_template: "{{ .ProjectName }}cli{{ .Version }}{{ .Os }}{{ .Arch }}"
файлы:
- ЛИЦЕНЗИЯ
- README.md
- документ/кли/*
В этом примере я перечислил архивы, которые необходимо создать. В разделе «сборки» я перечислил сборки, которые необходимо заархивировать. То есть вы можете распространять любые файлы для удобства пользователей. Это может быть полезно в таких проектах, где много компонентов.
Например, помимо клиента и сервера могут быть другие агенты и утилиты для резервного копирования и мониторинга. Тогда будет повод отделить утилиту CLI от остальных серверов.
Исполняемые файлы — не единственное, что может попасть в архив. Как вы могли видеть в примере, я добавил файл с лицензией и читает. И для каждого архива можно задать свои наборы. Это удобно для примера, который я привел выше. Для утилиты CLI комплект документации будет отличаться от серверных утилит.
И я не могу не упомянуть еще одну возможность. Его крючки.
```javascript
до:
крючки:
- сделать чистым
- приведи мод в порядок
Этот функционал позволяет выполнять дополнительные действия перед сборкой. Например, удалите лишние пакеты или создайте файл конфигурации по умолчанию и т. д. Я бы рекомендовал сделать это в качестве шага конвейера, когда дело доходит до встраивания GoReleaser в вашу систему непрерывной доставки. Но когда эта опция недоступна, крючки будут очень кстати. Я обычно добавляю:
```javascript
rm -rf расстояние/
Это удобно при отладке, потому что для сборки целевой каталог должен быть пустым.
Итак, проект готов к первому релизу. Напомню, что в рамках этой статьи я выпущу ее на GitHub. Зафиксируйте наш .goreleaser.yaml
. Не забудьте добавить /dist
к . gitignore
! Эти файлы артефактов точно не принадлежат репозиторию. Теперь нужно создать тег и сразу его нажать.
```javascript
Git-тег v0.1.0
git push --tags мастер происхождения
GoReleaser требует токен GitHub, чтобы иметь возможность использовать GitHub API для создания и редактирования выпусков. Вы можете создать его в своих настройках. Вам просто нужно поставить на управление публичными репозиториями флаг «Доступ к публичным репозиториям».
```javascript
экспортировать GITHUB_TOKEN=xxx
Наконец-то начните строительство без дополнительных флагов
В логи добавлена информация о создании релиза в репозиторий GitHub.
```javascript
• публикация
• SCM-релизы
• создание или обновление репозитория релиза=antgubarev/pet tag=v0.1.0
• обновленный релиз url=https://github.com/antgubarev/pet/releases/tag/v0.1.0
• загрузка в релиз file=dist/checksums.txt name=checksums.txt
• загрузка в релиз file=dist/pet_cli_0.1.0_Linux_x86_64.tar.gz name=pet_cli_0.1.0_Linux_x86_64.tar.gz
• загрузка в релиз file=dist/pet_srv_0.1.0_Windows_i386.tar.gz name=pet_srv_0.1.0_Windows_i386.tar.gz
• загрузка в релиз file=dist/pet_srv_0.1.0_Linux_x86_64.tar.gz name=pet_srv_0.1.0_Linux_x86_64.tar.gz
• загрузка в релиз file=dist/pet_srv_0.1.0_Linux_i386.tar.gz name=pet_srv_0.1.0_Linux_i386.tar.gz
• загрузка в релиз file=dist/pet_srv_0.1.0_Darwin_x86_64.tar.gz name=pet_srv_0.1.0_Darwin_x86_64.tar.gz
• загрузка в релиз file=dist/pet_cli_0.1.0_Linux_i386.tar.gz name=pet_cli_0.1.0_Linux_i386.tar.gz
• загрузка в релиз file=dist/pet_srv_0.1.0_Windows_arm64.tar.gz name=pet_srv_0.1.0_Windows_arm64.tar.gz
• загрузка в релиз file=dist/pet_cli_0.1.0_Darwin_arm64.tar.gz name=pet_cli_0.1.0_Darwin_arm64.tar.gz
• загрузка в релиз file=dist/pet_cli_0.1.0_Windows_i386.tar.gz name=pet_cli_0.1.0_Windows_i386.tar.gz
• загрузка в релиз file=dist/pet_srv_0.1.0_Linux_arm64.tar.gz name=pet_srv_0.1.0_Linux_arm64.tar.gz
• загрузка в релиз file=dist/pet_cli_0.1.0_Windows_arm64.tar.gz name=pet_cli_0.1.0_Windows_arm64.tar.gz
• загрузка в релиз file=dist/pet_srv_0.1.0_Darwin_arm64.tar.gz name=pet_srv_0.1.0_Darwin_arm64.tar.gz
• загрузка в релиз file=dist/pet_cli_0.1.0_Windows_x86_64.tar.gz name=pet_cli_0.1.0_Windows_x86_64.tar.gz
• загрузка в релиз file=dist/pet_cli_0.1.0_Darwin_x86_64.tar.gz name=pet_cli_0.1.0_Darwin_x86_64.tar.gz
• загрузка в релиз file=dist/pet_cli_0.1.0_Linux_arm64.tar.gz name=pet_cli_0.1.0_Linux_arm64.tar.gz
• загрузка в релиз file=dist/pet_srv_0.1.0_Windows_x86_64.tar.gz name=pet_srv_0.1.0_Windows_x86_64.tar.gz
• объявление
• релиз успешен через 7,08 с
Перейдите на страницу выпуска и посмотрите
Ура, все получилось. Помимо всех архивов еще создается и журнал изменений, в котором содержатся коммиты, которые были сделаны из предыдущего тега. Это поможет пользователям понять, что изменилось, а разработчику — от рутинного описания этого вручную.
Вот такую простую вещь я и сделал за короткое время, чтобы организовать релизы проекта. Конечно, с помощью GitHub Workflow автоматизировать это было даже удобнее. Но это выходит за рамки этой темы. В будущих статьях я опишу, как можно сделать проект с открытым исходным кодом еще более привлекательным с помощью GitHub Workflow и возможностей golangci-lint
.
Оригинал