Travis CI 上の環境変数(PULL_REQUEST, BRANCH, TAG)を使って、ワークフローの改善とリリース自動化を実現する

More than 1 year has passed since last update.

CI を中心としたワークフローやリリース(デプロイ)自動化システムを構築するには、現在対象としているコードベースの状態を把握する必要があります

  • ブランチは、feature か master か
  • プルリクエストをマージしたのか
  • タグはついているのか

Travis CI でそれらを把握するためには表題にある 3 つの環境変数の意味と組み合わせを理解しないと出来ないのですが、まとまった公式のドキュメントやネット上のレファレンスが見つからなかったので書きます

http://aniszczyk.org/2012/04/05/travis-ci/ より引用

http://aniszczyk.org/2012/04/05/travis-ci/ より

Travis CI を使ったリリース自動化の例

例えば、最近試した iOS のプロジェクトでは、次のような、Travis CI を使った比較的複雑な、ワークフローの構築とリリース自動化を行いました

  • なぜこうしているのかという意図などは、リンク先の README にある程度詳細に書いているのでご参照ください

feature ブランチを master ブランチに対してプルリクエストした場合

  • テストする
  • ビルドしてバイナリを生成する
  • そのバイナリをチームメンバーがインストールできるホスティングサービスにデプロイする

feature ブランチを master ブランチにマージした場合

  • プルリクエストした場合とやることは同じ
  • ただし、デプロイ先アドレスは変える(= マスターブランチから生成したバイナリとフィーチャーブランチから生成したバイナリは分けてホスティングする)

タグをつけたコミットをプッシュした場合

  • テスト、ビルド、ホスティングサービスにデプロイ までは同じ(マージの時と同じようにデプロイ先アドレスは変える)
  • 次に、GitHub Releases に生成したバイナリをデプロイする
  • さらに、このレポジトリに依存したレポジトリのリリース作業も行っていく
    • 依存レポジトリの appledoc 更新、バージョン番号の更新、コミット、マスターにプッシュする
    • 依存レポジトリの GitHub Pages を更新する
    • 依存レポジトリを GitHub Releases に公開する

状態を把握するために、.travis.yml で参照できる 3 つの環境変数

上記に書いたような、場合分けを伴うリリース自動化をするために参照する環境変数は次の 3 つです(これらの環境変数は、Travis CI 側で値を設定しているものです)

  • TRAVIS_PULL_REQUEST
  • TRAVIS_BRANCH
  • TRAVIS_TAG

TRAVIS_PULL_REQUEST

  • 文字列

取りうる値

  • false
    • プルリクエストではない場合
  • 1 など
    • プルリクエストである場合
    • プルリクエスト番号が入る

TRAVIS_BRANCH

  • 文字列

取りうる値

  • master や feature1 など
    • タグのプッシュではない場合
    • ブランチ名が入る
  • v1.0.0 など
    • タグのプッシュである場合
    • タグ名が入る

TRAVIS_TAG

  • 文字列

取りうる値

  • 空白
    • タグコミット(= タグプッシュ)ではない場合
  • v1.0.0 など
    • タグコミット(= タグプッシュ)である場合
    • git tag でつけたタグ名が入る

Git / GitHub 上での操作を例に、3 つの環境変数の組み合わせをまとめる

  • GitHub 上で Travis CI と連携している前提です
  • 運用フロー(≒ ワークフロー)は、GitHub Flow を採用している前提です
    • ただし、iOS などネイティブアプリを念頭に置いているので、master をすぐにリリースするわけではなく、リリースはタグをつけて別に行うという点は注意ください
  • 仮に、feature ブランチ名を created-readme とする
  • 仮に、プルリクエスト番号を 8 とする
  • 仮に、タグ名を v10.0.13 とする

feature ブランチをプッシュした

TRAVIS_PULL_REQUEST TRAVIS_BRANCH TRAVIS_TAG
"false" "created-readme" ""

feature ブランチのプルリクエストを master ブランチに出した

TRAVIS_PULL_REQUEST TRAVIS_BRANCH TRAVIS_TAG
"8" "master" ""

feature ブランチを master ブランチにマージした

TRAVIS_PULL_REQUEST TRAVIS_BRANCH TRAVIS_TAG
"false" "master" ""

タグをプッシュした

TRAVIS_PULL_REQUEST TRAVIS_BRANCH TRAVIS_TAG
"false" "v10.0.13" "v10.0.13"

注意点

  • feature ブランチのプルリクエストを master ブランチに出したときに、TRAVIS_PULL_REQUEST8TRAVIS_BRANCHcreated-readme でも実行されるのかなと思ったのですが、されません

最後に

参考になるかもしれない、蛇足を書きます

タグをプッシュするときの例

release:
    if [ -z "$(NEXT_VERSION)" ] ; then exit 1; fi
    $(eval CURRENT_VERSION := $(shell echo $$(git for-each-ref --sort=-taggerdate --format="%(tag)" refs/tags | head -n 1 | sed -e "s/v//")))
    git checkout master
    sed -i '' -e"s/$(CURRENT_VERSION)/$(NEXT_VERSION)/g" \
        DemoApp/DemoApp-Info.plist
    git add .
    git commit -m"Updated version to v$(NEXT_VERSION)"
    git tag -a v$(NEXT_VERSION) -m"Updated version to v$(NEXT_VERSION)"
    git push --tags origin master

.travis.yml にて、環境変数を使った例

before_script:
  - '[ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" != "false" ] && MTB_PR=1 || echo "This is master or not PR"'
  - '[ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ] && MTB_MERGE_MASTER=1 || echo "This is not master or PR"'
  - 'DEPLOYGATE_MESSAGE=$(git rev-parse --short HEAD)'
  - '[ "$MTB_PR" ] && DEPLOYGATE_MESSAGE+=#"$TRAVIS_PULL_REQUEST" || echo "Not append PR number"'
  - echo TRAVIS_BRANCH=${TRAVIS_BRANCH}
  - echo TRAVIS_PULL_REQUEST=${TRAVIS_PULL_REQUEST}
  - echo TRAVIS_TAG=${TRAVIS_TAG}
  - echo MTB_PR=${MTB_PR}
  - echo MTB_MERGE_MASTER=${MTB_MERGE_MASTER}
  - echo DEPLOYGATE_MESSAGE=${DEPLOYGATE_MESSAGE}

script:
  - make test
  - '[ "$MTB_PR" ] && make append-pr-to-bundleid || echo "Not append -pr to bundleid"'
  - '[ "$MTB_MERGE_MASTER" ] && make append-master-to-bundleid || echo "Not append -master to bundleid"'
  - '( [ "$MTB_PR" ] || [ "$MTB_MERGE_MASTER" ] || [ "$TRAVIS_TAG" ] ) && make ipa || echo "Skip to make ipa"'
  - '( [ "$MTB_PR" ] || [ "$MTB_MERGE_MASTER" ] || [ "$TRAVIS_TAG" ] ) && make deploygate DEPLOYGATE_MESSAGE="$DEPLOYGATE_MESSAGE" || echo "Skip to make deploygate"'

after_success:
  - make send-coverage

before_deploy:
  - 'NEXT_VERSION=$(echo ${TRAVIS_TAG} | sed -e "s/v//")'
  - echo NEXT_VERSION=${NEXT_VERSION}
  - make release-public-repo NEXT_VERSION=$NEXT_VERSION

deploy:
  provider: releases
  api_key:
    secure: gvj2V09zMPsHDPhNoQCpP4ouMUqq7mdq7g2l79dRSTOqGh/diJpgRWKCOZdZ5hYibpe0ynDckixS3ZLyPGhsvx7qfCxNcWDpdmtZtSSv7yuoc3PEbV56QtFfaoCCJacHWohKjRd2+hymDs6bxfPQ3WjnaMAbA48CdEY3QQEftpg=
  file: DemoApp.ipa
  skip_cleanup: true
  on:
    repo: yoheimuta/mtburn-ios-sdk-demoapp
    tags: true
    all_branches: true  # https://github.com/travis-ci/travis-ci/issues/1675

after_deploy:
  - gem install dpl
  - make deploy-public-repo

iOS のリリース自動化に関連して、cocoapods ライブラリのリリースについて

https://github.com/yoheimuta/mtburn-ios-sdk-demoapp#only-manual-operation-to-be-required に書いたのですが、2015/03/07 まではできませんでしたが、COCOAPODS_TRUNK_TOKEN という環境変数を使うことで、Travis CI などの CI を使ったリリースが出来るようになりました

  • 手元で出来ることは確認しました
  • 以前、自分がやろうとしたときに出来ないことを確認するのはけっこう大変だったので、メモ書き程度ですがひとこと書きました(最近追加されたので、出来ないままだと思っている人もいるかもしれないので)

Travis CI に関連して、Caching Ubuntu packages に http://packages.treasuredata.com が加わってます

2015/02/09 まで、cache apt:true を追加すると、sudo curl -L http://toolbelt.treasuredata.com/sh/install-ubuntu-precise-td-agent2.sh | sh が失敗していたと思います

  • travis が管理している cached APT repositories に http://packages.treasuredata.com が含まれていなかったためです
  • http://docs.travis-ci.com/user/caching/#Caching-Ubuntu-packages にメールしてくれと書いてあるのでメールしたら追加してくれたので、今は cache apt:true しても失敗しません(docs の url リストにはなぜかまだ追加されていないですが)
  • 前に 1 回やろうとしてこれを理由に apt キャッシュを見送った経緯もあるので(そのときの担当は自分でないので予想ですけど)、共有する場所もないので、メモ書き程度ですがひとこと書きました