先日の goreleaserを使ってGoで書いたツールのバイナリをGithub Releasesで配布する - $shibayu36->blog; で、Goツールのバイナリ配布ができるようになった。しかし、アーカイブ周りの処理が少し期待と違い、作成したzipをunzipコマンドで取り出すとファイルのアクセス権がおかしくなり、バイナリに実行権限がつかなくなるという問題が起こった。これは困る。
goreleaserを深追いをしても良いけど、ひとまず別の方法も試してみようと思って、goxc + ghrを使うようにしてみた。これがうまくいったので、メモしておく。
今回のコードは以下のところで確認できる。
goxcとghrをインストールする
先にgo getでインストールしておく。
$ go get -v -u github.com/laher/goxc
$ go get -v -u github.com/tcnksm/ghr
goxcで成果物を作成する
まずgoxcで成果物を作成する設定を行う。
作りたい成果物
作りたい成果物は以下のようなものとする。
.goxc.jsonで成果物作成ルールを作る
以上の成果物を作るには、.goxc.jsonを作り、成果物作成ルールを作っておくと良い。
まず、コマンドから雛形を作る。-wcコマンドを使うと、コマンド引数を考慮した.goxc.jsonを作ってくれる。
$ goxc -os="linux darwin windows" -arch="386 amd64" -d=dist -tasks="clean-destination,xc,archive-zip,rmbin" -wc
すると以下のような設定ができる。
{
"ArtifactsDest": "dist",
"Tasks": [
"clean-destination",
"xc",
"archive-zip",
"rmbin"
],
"Arch": "386 amd64",
"Os": "linux darwin windows",
"ConfigVersion": "0.9"
}
しかし、archive-zipというタスクはデフォルトだとlinuxの成果物をzip圧縮してくれない。このままだとうまくいかない。
これをなんとかするために、goxc -help archive-zip
でarchive-zipのヘルプを見てみると、platformsというオプションでどのプラットフォームをzip圧縮するか設定できることが分かった。また、include-top-level-dirというオプションで、ディレクトリごとzipで固めるかを設定できた。そこで、.goxc.jsonを書き換えて以下のように変更する。
{
"ArtifactsDest": "dist",
"Tasks": [
"clean-destination",
"xc",
"archive-zip",
"rmbin"
],
"TaskSettings": {
"archive-zip": {
"include-top-level-dir": "windows darwin linux",
"platforms": "windows darwin linux"
}
},
"Arch": "386 amd64",
"Os": "linux darwin windows",
"ConfigVersion": "0.9"
}
あとはREADME.mdとLICENSEファイルをzipに含める設定だが、goxcはデフォルトでINSTALL*,README*,LICENSE*
というルールのファイルをアーカイブに含めてくれるため、明示的に設定しなくても良い。
成果物を生成する
あとはgoxcコマンドを打つだけ。
$ goxc
$ tree dist
dist
└── snapshot
├── shibayu36_darwin_386.zip
├── shibayu36_darwin_amd64.zip
├── shibayu36_linux_386.zip
├── shibayu36_linux_amd64.zip
├── shibayu36_windows_386.zip
└── shibayu36_windows_amd64.zip
$ unzip dist/snapshot/shibayu36_darwin_amd64.zip
Archive: dist/snapshot/shibayu36_darwin_amd64.zip
inflating: shibayu36_darwin_amd64/shibayu36
inflating: shibayu36_darwin_amd64/README.md
inflating: shibayu36_darwin_amd64/LICENSE
$ ls -l shibayu36_darwin_amd64
total 7120
-rw-r--r-- 1 shibayu36 staff 560 Oct 8 17:30 LICENSE
-rw-r--r-- 1 shibayu36 staff 400 Oct 8 17:30 README.md
-rwxr-xr-x 1 shibayu36 staff 3637000 Oct 9 01:11 shibayu36
期待通りに成果物が作成できた。
ghrでGithub Releasesに成果物をアップロードする
あとはこのdist/snapshot/以下に存在するファイルをすべてGithub Releasesにアップロードすれば良い。これはghrを使えば簡単に行える。
例えば、shibayu36ユーザのshibayu36レポジトリに、v0.0.7というリリースタグ名でdist/snapshot/以下のファイルをアップロードするには、以下のようなコマンドを発行するだけで良い。
$ GITHUB_TOKEN=... ghr -u shibayu36 -r shibayu36 v0.0.7 dist/snapshot/
あとは、goxcして、一番最新のgitのタグ名を使ってghrで上げるというスクリプトを用意しておけば、簡単にリリースができるようになる。次のとおり。
script/release
set -e
latest_tag=$(git describe --abbrev=0 --tags)
goxc
ghr -u shibayu36 -r shibayu36 $latest_tag dist/snapshot/
これで手元からクロスコンパイルしてGithub Releasesにアップロードするには、タグを打ってscript/releaseすれば良いだけとなった。
$ git tag vx.y.z
$ GITHUB_TOKEN=... script/release
TravisCIを使い自動で成果物をアップロードする
これまででとりあえずやりたいことはできた。しかし、やはりTravisCIで自動で成果物生成とアップロードを行えるようにしておきたい。
これまでの設定と簡単なMakefileさえあれば、非常に簡単に設定できる。
Makefile
setup:
go get -v -u \
github.com/Masterminds/glide \
github.com/laher/goxc \
github.com/tcnksm/ghr
deps: setup
glide install
test: deps
go test -v $$(glide novendor)
.PHONY: setup deps test
.travis.yml
language: go
go:
- 1.9
script:
- make test
after_success:
- test -n "$TRAVIS_TAG" && script/release
GITHUB_TOKEN環境変数も指定する必要はあるので、それは https://docs.travis-ci.com/user/environment-variables/#Defining-Variables-in-Repository-Settings あたりを見ながらTravisCI側で設定したら良い。
これでタグをpushした時にのみ、TravisCIでscript/releaseが動き、成果物生成からGithub Releasesへのアップロードまで自動で行われるようになった。自分がやるのはタグ付けだけとなる。
$ git tag vx.y.z
$ git push --tags
便利!!