Travis から Bintray へのデプロイでバージョンを自動で設定してアップロードする

漢なら GitHub コミットして Travis ビルドして Bintray へデプロイですね!

[travisCI + Bintrayによる自動デプロイを試したメモ](http://soma.hatenablog.jp/entry/2015/12/04/142621)

参考になります, ありがとうございます.

しかし Travis が用意しているサンプル手順 https://docs.travis-ci.com/user/deployment/bintray/ だと, バージョン番号は手動で JSON に書く必要があります.

毎回手作業はめんどうですね... 人間の欲望は飽きない. git tag を打ったら自動でよろしく tag 名でバージョンを設定してよろしく Bintray にアップロードしたくなりますね.

そこで sed でバージョン番号とリリース日を travis ビルド後に書き換えた .json を作り bintray にアップロードする手を考えてみました.
tinyobjloader で使ってみました.

https://github.com/syoyo/tinyobjloader

https://bintray.com/syoyo/tinyobjloader/releases

## 手順

最初に Binray でプロジェクトとパッケージディレクトリを作っておきます.

その後, bintray json テンプレート(.bintray.in)を用意します.

```
{
    /* Bintray package information.
       In case the package already exists on Bintray, only the name, repo and subject
       fields are mandatory. */

    "package": {
        "name": "releases", // Bintray package name
        "repo": "tinyobjloader", // Bintray repository name
        "subject": "syoyo" // Bintray subject (user or organization)
    },

    /* Package version information.
       In case the version already exists on Bintray, only the name fields is mandatory. */

    "version": {
        "name": "@VERSION@",
        "desc": "@VERSION@",
        "released": "@DATE@",
        "vcs_tag": "@VERSION@",
        "gpgSign": false
    },

    /* Configure the files you would like to upload to Bintray and their upload path.
    You can define one or more groups of patterns.
    Each group contains three patterns:

    includePattern: Pattern in the form of Ruby regular expression, indicating the path of files to be uploaded to Bintray.
    excludePattern: Optional. Pattern in the form of Ruby regular expression, indicating the path of files to be removed from the list of files specified by the includePattern.
    uploadPattern: Upload path on Bintray. The path can contain symbols in the form of $1, $2,... that are replaced with capturing groups defined in the include pattern.

    Note: Regular expressions defined as part of the includePattern property must be wrapped with brackets. */

    "files":
        [ {"includePattern": "dist/(.*)", "uploadPattern": "$1"} ],
    "publish": true
}
```

`@VERSION@`, `@DATE@` をビルド日付と git tag(Travis の場合は TRAVIS_TAG で取得できる)で置き換えるスクリプト(`./tools/travis_postbuild.sh`)を用意します.

```
#!/bin/bash

DATEVAL=`date +%Y-%m-%d`
VERSIONVAL=master

# Use tag as version
if [ $TRAVIS_TAG ]; then
  VERSIONVAL=$TRAVIS_TAG
fi

# MacOSX sed(BSD sed) は inplace(-i) が使えないことに注意!
sed -e s%@DATE@%${DATEVAL}% .bintray.in > .bintray.tmp
sed -e s%@VERSION@%${VERSIONVAL}% .bintray.tmp > .bintray.json
```

**注意!** Bintray では日付のフォーマットが制限されています. 

* Date in the format of 'yyyy-MM-dd'T'HH:mm:ss.SSSZZ'
* java.util.Date instance

のどちらかになります.  Bintray がサポートする日付フォーマットに合わせておきます.

これを travis の `before_deploy` で走らせて, .bintray.json を作る様にします.

```
before_deploy:
  - echo "Creating description file for bintray."
  - ./tools/travis_postbuild.sh
```

```
deploy:
  - provider: bintray
    file: ".bintray.json"
    user: "syoyo"
    key:
      secure: XXXXXXXX
    all_branches: true
    on:
      repo: syoyo/tinyobjloader
      condition: -n "$DEPLOY_BUILD"
      tags: true
    skip_cleanup: true
```

tinyobjloader では build matrix を使っているので, `condition` をつけないとすべてのビルドで bintray にアップロードしようとします. 特定のビルド(DEPLOY_BUILD=1)のときだけアップロードするようにします.
また, tag のビルド時だけデプロイするようにします(`all_branches: true`, `tags: true`)

## github commit

あとは git で tag を打って github へ push するだけです.

https://bintray.com/syoyo/tinyobjloader/releases/v0.9.21/view

Voala! めでたく tag 名ごとにファイルを bintray にアップロードすることができました!

## 問題点

Travis での bintray デプロイ対応機能(deploy provider = bintray)だと, すでに bintray にファイルがアップロードされていた場合は更新(上書き)に失敗します. そのため `master` のようなブランチや, まちがって tag を打ったときにリリースをやりおすときは Bintray で一度ファイルを削除する必要があります.

.json 設定ファイルではファイル上書きのようなパラメータは無いようなので, 結局は Curl(REST API) ベースでの運用がよいかもしれません. 参考例はこちら.

https://github.com/bintray/bintray-examples/tree/master/bash-example