Posted at

Travis CI から複数ファイルを GitHub Releases にアップロードする

More than 1 year has passed since last update.


Travis CI から GitHub Releases にアップロードする

Go などのコンパイラ言語で書いたソフトウェアを配布する場所として、最近は GitHub Releases を使うことが多いと思います。単純に Git tag と紐付けてファイルをアップロードする場所ですが、手作業でやるのも面倒なので CI と連携させるのが便利です。

Travis CI には Deployment の機能があります。その名の通り、アプリケーションのテスト/ビルド後に、外部の指定した場所へ成果物をデプロイする機能です。デプロイするトリガーとして「特定のブランチ」「git tag がプッシュされた場合のみ」「Go 1.7 ビルドのみ」のような条件が指定できます。

Deployment は、標準で GitHub Releases のインテグレーションを備えています (GitHub Releases Uploading - Travis CI)。GitHub Access Token だけ与えればあとはよしなにアップロードしてくれる便利君ですが、複数ファイルアップロードしたいときに難がありました。


file にアップロード対象のファイルを列挙する

公式ドキュメントで紹介されている方法です。以下は ec2c のバイナリパッケージを12個アップロードする例です。

https://docs.travis-ci.com/user/deployment/releases/#Uploading-Multiple-Files


.travis.yml

deploy:

provider: releases
skip_cleanup: true
api_key: $GITHUB_TOKEN
file:
- dist/ec2c-0.1.0-darwin-386.tar.gz
- dist/ec2c-0.1.0-darwin-386.zip
- dist/ec2c-0.1.0-darwin-amd64.tar.gz
- dist/ec2c-0.1.0-darwin-amd64.zip
- dist/ec2c-0.1.0-linux-386.tar.gz
- dist/ec2c-0.1.0-linux-386.zip
- dist/ec2c-0.1.0-linux-amd64.tar.gz
- dist/ec2c-0.1.0-linux-amd64.zip
- dist/ec2c-0.1.0-windows-386.tar.gz
- dist/ec2c-0.1.0-windows-386.zip
- dist/ec2c-0.1.0-windows-amd64.tar.gz
- dist/ec2c-0.1.0-windows-amd64.zip
on:
tags: true
go: '1.7'

この書き方だと、対象プラットフォームを増やしたときや(バージョン番号含めるなら)バージョンアップのときに毎回 .travis.yml を修正する手間が発生して面倒です。対処法として、バージョン番号を含めなかったり Script deploymentghr を組み合わせてディレクトリ内一括アップロードという方法がありました。


file_glob: true でパターンマッチが使える

実は、file_glob: true というフィールドを付け加えることで file の値にワイルドカードを用いたパターンを指定することが可能となります。

以下は dist ディレクトリ内の tarball と zip archive をすべてアップロードする例です。前のに比べ、えらくシンプルになりました。


.travis.yml

deploy:

provider: releases
skip_cleanup: true
api_key: $GITHUB_TOKEN
file_glob: true
file: 'dist/*.{tar.gz,zip}'
on:
tags: true
go: '1.7'

これだと対象プラットフォームが増えてもバージョンが変わっても安心ですね。

file_glob については 2016/09/22 現在公式ドキュメントに書かれていない隠し機能となっていますが、Travis CI Deployment で使っている dpl gem の README にはその存在が記されています。

https://github.com/travis-ci/dpl/tree/db81ca9678428dfb7f3bcc3872d485df35b27d46#github-releases

ソースコードを見ると、file_glob: true の時は file の値を Dir.glob の引数へ渡すようになっています。というわけで、file に書くパターンは Dir.glob で展開できる形であればよいのです。複雑なパターンを書くときは irb, pry で挙動を確認しましょう。

https://github.com/travis-ci/dpl/blob/db81ca9678428dfb7f3bcc3872d485df35b27d46/lib/dpl/provider/releases.rb#L47-L53


lib/dpl/provider/releases.rb

        if options[:file_glob]

Array(options[:file]).map do |glob|
Dir.glob(glob)
end.flatten
else
Array(options[:file])
end


おわりに

file_glob: true で必要十分のことができるようになったので。外部ツールに頼らなくて良くなりました。めでたし