Goツールのビルドをおこない、GitHub Releasesにアップロードする
今回で最終回。Goのツールをビルドして成果物を生成し、それをGitHub Releasesにアップロードする。
ビルドする
CGOを使っていない限り、最近のGoは簡単にマルチプラットフォーム対応の実行バイナリをそれぞれビルドすることができる。
僕の場合、OSはlinuxとdarwin(Mac)用は必ず作っている。windows用も余力があれば作るようにはしている。アーキテクチャーはamd64(64bit)決め打ちにしてしまうことも多い。
また、成果物を配布する場合は、実行バイナリの他にLICENSEやREADMEなどを含め、zipやtar玉等に固めるのが定番。
これらのビルドとアーカイブに固める作業のために特別なツールは必要なく、シェルスクリプトでもいけるレベルだが、僕は goxc
を使っている。
https://github.com/laher/goxc/
goxc
は結構ゴツくてGitHub Releasesとかbintrayに上げる機能とかも持ってたりするんだけど、それの、成果物を生成する部分だけを利用しているという具合。
成果物のネーミングルールや、成果物に含めるファイルのルールを設定できるところが便利ではある。ただ、更新が滞っていることもあるし、そういう成果物生成だけに絞ったもう少しシンプルなツールが欲しいと思っている。
goxcの設定
goxc
は .goxc.json
をリポジトリにおいておけば、 % goxc
と打つだけで設定通りにビルドしてくれる。ただ、それを丁寧に書くのを以前はやってたんだけど、それらは大体コマンドライン引数で指定できるし、goxc
のためにファイル増やすのも馬鹿らしいので、最近は、Makefileにcrossbuildっていうターゲットを作ってをそこにベタっと書くようにしている。
ghchのMakefile、より抜粋すると以下のような具合。
crossbuild: devel-deps
goxc -pv=v$(shell gobump show -r) -build-ldflags=$(BUILD_LDFLAGS) \
-d=./dist -arch=amd64 -os=linux,darwin,windows \
-tasks=clean-destination,xc,archive,rmbin
これで、 make crossbuild
を実行すれば、 dist/
配下に成果物を配置してくれる。
$ tree dist/
dist/
└── v0.1.2
├── ghch_v0.1.2_darwin_amd64.zip
├── ghch_v0.1.2_linux_amd64.tar.gz
└── ghch_v0.1.2_windows_amd64.zip
make crossbuild
とすれば、手元でもCI環境であっても同様に成果物が作られるのがポイント。
CGOを使っている場合
CGOを使っている場合は、そのプラットフォーム用のCI/CD環境を用意するなどしてビルドする必要がある。Windowsの場合は、AppVeyorが定番です。Macの場合は、TravisのOS X環境を使うなどすれば良さそうですが、あまり知見はない。
mackerel-agentの場合、AppVeyorを利用してビルドの他にインストーラーの作成やインストーラーへの署名などもおこなっています。
それらの環境でビルドした成果物をアップロードする手順を作るのは少し複雑にはなってはしまう。
成果物をGitHub Releasesにアップロードする
成果物のアップロードには、 ghr
を使っている。これはGitHub Releasesにアップロードすることに特化したシンプルで良いツールです。
参考: 高速に自作パッケージをGithubにリリースするghrというツールをつくった
環境変数 $GITHUB_TOKEN
を設定した状態で、
% ghr v0.1.2 dist/v0.1.2
などとすれば、第1引数に指定したバージョンタグのGitHub Releasesに対して、第2引数に指定したディレクトリ以下の成果物を一括アップロードしてくれる。
クロスコンパイルして、アップロードするところまでは実際には以下のようなシェルスクリプトを用いている。
#!/bin/sh
set -e
make crossbuild
ver=v$(gobump show -r)
ghr $ver dist/$ver
これで、Goで書いたツールを、GitHub Releaseにアップロードできるようになりました。
手元ではなくTravis上でビルドとアップロードをおこなう
これまでは手元でビルドしてアップロードする方法を書きましたが、git tagが打たれたのを契機に、CI/CD環境でビルドやデリバリーをおこなうのも定番スタイルです。CI/CD環境であればクリーンな環境でビルドを作れるのもメリットです。反面複雑さが増す部分もあります。
とは言え、上に挙げたシェルスクリプトを単にTravisなどの環境で実行させればよいだけの話ではあります。その際 $GITHUB_TOKEN
環境変数をセットする必要はあります。
また、Travisで実施する場合、ビルドは make crossbuild
でおこなうが、GitHub ReleasesへのアップロードはTravisの機能を使う手もあります。ghchではそのようにしています。
その場合、
% travis setup releases
とすれば、 .travis.yml
を書き換えてくれるのでそれを調整する手順になります。調整した、 .travis.yml
を抜粋すると以下のようになります。
before_deploy:
- make crossbuild
deploy:
provider: releases
skip_cleanup: true
api_key:
secure: ...
file_glob: true
file: "dist/**/*.{tar.gz,zip}"
on:
tags: true
branch: master
condition: "$TRAVIS_TAG =~ ^v[0-9].*$"
まあ、それなりに便利ではあるんですが、若干煩雑になる感はある。また、 travis setup
の度に、GitHubの個人Tokenがぽこぽこ作られる仕組みになっていて、ツールを提供しているリポジトリ毎にtokenが作られてしまうのは気持ち悪いので、あまりやらないようにしている。
以上です。