はじめに
GoReleaserを使い始めて、執筆時点で1ヶ月余りが過ぎた。
この間に、GoReleaserとGitHub Actionsを使って3つほどGolangのCLIのリリースを自動化した。
到底、使い倒したといえるほどのものではないが、得られた知見などをまとめておく。
随時、加筆更新予定。
※元ネタは個人のメモサイトに書き溜めていたもの。
GoReleaserとは
Goプロジェクトのリリース自動化ツール。
主な機能:
- バイナリのクロスコンパイル
- GitHub / GitLabへの公開
- 公開済みのtagを参照してreleaseを作り、バイナリをアップロードする
- Release Note生成 ... commit logからChange Logを生成
CIツールから使われることを念頭に作られているようだが、ローカルにインストールして実行することもできる。
参考:
- goreleaser を使って Github Releases へ簡単デプロイ #golang - Qiita
- GitHub Actions での goreleaser と Docker Image の Push | | 1Q77
Installation
macOS:
brew install goreleaser/tap/goreleaser
Snap (Ubuntu, etc.):
sudo snap install --classic goreleaser
Docker:
docker pull goreleaser/goreleaser
Usage
ここではローカルで実行できる手順を示すが、CIツールを使うにしても、大まかなプロセスの内容は変わらない。
①.goreleaser.ymlの生成
.goreleaser.ymlは、goreleaserを使うために必須の設定ファイルで、ふつうはプロジェクトのルートディレクトリに置く。
goreleaserコマンドのオプションでパスを指定可能なので、好みで変えることはできそう。
次のコマンドで雛形を生成できる:
goreleaser init
②設定の編集
生成したYAMLを編集して、挙動をカスタマイズすることができる。
自分がよく使う設定については後述する。
③APIトークンの設定
GitHubやGitLabにリリースする際、goreleaserが利用するAPIトークンを設定する必要がある。
GitHubの場合、次のようにする:
export GITHUB_TOKEN="<YOUR API TOKEN>"
GitHub Actionsで設定する場合については後述する。
④goreleaserコマンド実行
ローカルから実行する場合、GitHubにタグをpushした後、次のコマンドでリリースを行う:
goreleaser --rm-dist
Dockerでgoreleaserを実行
④で示したように、ローカルにインストールしたgoreleaserのバイナリを使ってビルドを行うと、生成物にカレントパス(など)の情報が含まれてしまう。
即ち、生成されたバイナリを実行して、panicした際などにビルド環境のパスが露出したりする。
これを避けるには、CIから実行するか、goreleaserのDockerイメージを使って実行するとよい。
dockerコマンドで実行する場合は、次のようにする:
src_path="/go/src/github.com/<account>/<repo>" # Module/パッケージに合わせて適切に設定する
docker run --rm --privileged \
-v $PWD:$src_path \
-v /var/run/docker.sock:/var/run/docker.sock \
-w $src_path \
-e GITHUB_TOKEN \
goreleaser/goreleaser release --rm-dist
(ローカル実行時の)ハマりポイント
主にローカルで実行する際に、初心者が一度はハマるだろうと思われるポイント:
- ワーキングツリーの最新のコミットが最新のタグと一致してないとNG
- これはCIでも同じと思われる
- ワーキングツリーがdirtyだと失敗する。管理外のファイル、ディレクトリがあってもNG
- 前回のビルド生成物が残っているなどで
dist/
が空じゃないとき、--rm-dist
オプションを付けてないと失敗する
Configuration
.goreleaser.yml
でカスタマイズしたくなりそうなところや、設定のTipsを記す。
(公式サイトに詳しいYAMLのサンプルがあるのは良いのだけど、大き過ぎて見切れてるとつらいのなんとかならないかな。。)
テンプレート変数
GoReleaserでは、YAML内の様々なフィールドでGoのテンプレート機能を使えるようだ。
使える変数は https://goreleaser.com/customization/templates に記されている。
Builds
builds:
# 複数のビルド対象を記述可能
-
# mainパッケージまたはmain.goへのパス
# デフォルトは "."
main: ./cmd/main.go
# デフォルトは [linux, darwin]
# Windowsもサポートしたいなら足す
goos:
- linux
- darwin
goarch:
# デフォルトでは386(32-bit)も含まれる
- amd64
Archive
アーカイブファイル形式や、含めるファイルとか、ファイル名の設定。
archives:
-
# デフォルトはtar.gzだけど、単バイナリでいいときとか変えたくなりそう
#format: binary
# アップロードされるファイルで、GOOSやGOARCHの文字列を置換したいときに設定する。
# 特にこだわりがなければ設定不要
replacements:
amd64: x86_64
files:
# アーカイブに何も追加したくない場合は、マッチしないglob文字列を書かないといけない
- nothing*
Release
GitHubやGitLabに作成するリリースに関する設定。
changelog:
# changelog要らない場合はtrueに設定。デフォルトは未設定
skip: true
# changelogにcommit logを昇順・降順どちらで載せるか(だと思う)
sort: asc
filters:
# 無視するcommit log
exclude:
- '^docs:'
- '^test:'
リリースノートをもっと自由にカスタマイズしたい場合、goreleaserコマンドの引数に指定する。
# 静的ファイル
goreleaser --release-notes=FILE
# コマンドで動的に生成
goreleaser --release-notes <(some_change_log_generator)
Features
Homebrew Formula生成
GoReleaserでHomebrewのFormulaを生成することができる。
参考:
- GoReleaser+GithubActionsを使って、releaseファイルのアップロードとhomebrew対応を自動で行う - 年中アイス
- 2020-07-18 | progrhyme's Tech Notes#GoReleaserでHomebrewのFormulaを作るようにした
- goreleaserで簡単にオレオレコマンドをbrew installできちゃう - Qiita
- goreleaserでHomebrewのFormulaを自動生成する - Qiita
CI設定
各種CIツールへの設定方法についても公式ガイドがあって捗る。
GitHub Actions
公式のアクションを利用できるので、簡単。
2020-06-14現在、progrhyme/shelpでの設定は下の通り。
name: goreleaser
on:
push:
tags:
- '*'
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
# コミットログからリリースノートを作るならこのオプションが必要
fetch-depth: 0
- uses: actions/setup-go@v2
with:
go-version: 1.14
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v2
with:
version: latest
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
任意のコマンドでリリースノートを生成
こちらの設定方法については、下の記事に書いた: