pockestrap

Programmer's memo

.travis.yml内のRubyのバージョンを更新するPull Requestを作る

こんにちは。Ruby 2.6が先日リリースされましたね。

Rubyの新しいバージョンがリリースされると、その度に.travis.ymlに書かれているRubyのバージョンを上げる作業をしている方は多いと思います。 今回はその作業を楽にするツールを作ったので紹介いたします。

ci_against

その名もCI Against gemです。安直な名前ですね。

このgemは、まず以下の2点について.travis.ymlを書き換えます。

  • 最新のRubyのteeny version1を使うように、既存のバージョン指定を書き換える
    • 例: rvm: 2.5.0 => rvm: 2.5.3
  • 新しいRubyのmajor / minor versionが出た時に、そのバージョンでもテストを行うように書き換える
    • 例: Ruby 2.6がリリースされたのでRuby 2.6でのテストも行うように追加する

そして、書き換えた変更でGitHubにPull Requestを開きます。

人が手で.travis.ymlを書き換えて、Pull Requestを作成するのに比べると作業がぐっと楽になりそうですね。

Installation

CI Againstはgemとして提供されているので、gem installによってインストールできます。 なおRuby 2.4以上が必要です。

$ gem install ci_against

Usage

CI AgainstはGitHubにアクセスするためにpersonal access tokenを使用します。 次のリンクからpersonal access tokenを取得して、GITHUB_ACCESS_TOKEN環境変数に値をセットしてください。 https://github.com/settings/tokens/new

$ export GITHUB_ACCESS_TOKEN=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

以下はこの環境変数がexportされた前提でコマンド例を記述します。

Dry Run

CI AgainstにはDry Runモードが存在します。 Dry Runモードを使用すると、Pull Requestを作成する前に変更内容を確認できます。2

コマンドの使い方は簡単です。ci_againstコマンドに、--dry-runオプションとGitHubリポジトリ名を渡すだけです。

$ ci_against --dry-run your_github_name/your_repo_name
CI against Ruby 2.5.3 and 2.6.0

## Added

* 2.5.3
* 2.6.0


## Changed

* 2.3.4 => 2.3.8
* 2.4.1 => 2.4.5
diff --git a/tmp/ci-against20181228-2141-qio4i0 b/tmp/ci-against20181228-2141-1hmqgc4
index 14298b9..5dd84a7 100644
--- a/tmp/ci-against20181228-2141-qio4i0
+++ b/tmp/ci-against20181228-2141-1hmqgc4
@@ -1,4 +1,6 @@
 language: ruby
 rvm:
-  - "2.3.4"
-  - "2.4.1"
+  - "2.3.8"
+  - "2.4.5"
+  - "2.5.3"
+  - "2.6.0"

Dry Runを実行すると、変更内容の説明とdiff3が表示されます。

Apply

ではこの変更内容でPull Requestを作成してみましょう。Pull Requestを作成するためには、単に--dry-runオプションを外すだけでokです。

$ ci_against your_github_name/your_repo_name
PR created: https://github.com/your_github_name/your_repo_name/pull/42

これで上記の内容でPull Requestが作成されました!あとはこのPull RequestがCIを通るのを待ってマージするだけです。

なお、ci_againstコマンドには一度に複数のリポジトリを渡すことができます。更新したいリポジトリが沢山ある場合には一度に複数渡してしまうと楽でしょう。

$ ci_against your_github_name/your_repo_name your_github_name/your_repo2 your_github_name/your_awesome_repo

CI Againstは渡されたリポジトリに変更がない場合単に無視するので、とりあえず管理しているリポジトリを全て渡してしまっても問題ありません。

注意点

CI Againstは最低限の実装しかないため、いくつか注意点があります。

まず、CI AgainstはPull Requestの重複確認をしません。 そのためci_againstコマンドを2回実行すると、全く同じPull Requestが2つできてしまうでしょう。運用でカバーしてください。 ただし、masterブランチ4の内容から差分がない場合にはPull Requestを作成しないので、既にPull Requestがマージされていれば心配はありません。

またCI Againstは.travis.yml内のrvmセクションの中身のみを更新します。 そのため、matrix.excludeなどを使っている場合にはそこで不整合が発生する可能性があります。 これは将来的には直したいと思っています。

CI AgainstはYAMLの全ての形式に対応しているわけではありません。 例えば既知の問題として、rvm: ['2.4.5', '2.5.3']のような指定方法には現在対応していません5。 その他にも対応漏れのスタイルがあるかもしれません。 もし対応していないスタイルを見つけたら、気軽にIssueを立てていただければと思います。

今後の課題

上記の注意点で述べた点を解決していく他にも、いくつか改善のアイディアが既にあります。 その中で一番大きなものが、Ruby以外の言語への対応です。 現在はRubyのみを対応していますが、仕組み上は他の言語の対応もそこまで難しいものではないと考えています。 .travis.ymlの更新はRubyに限らず様々な言語で行われるため、他の言語でも対応したいと思っています。

またCI AgainstをGitHub Appsを使ってWebサービス化して全自動でPRが飛んでくるようにしたら便利なのでは……という野望もありますが、めんどくさくて今の所やる予定はありません。 やりたい人がいたらチャレンジしていただけると嬉しいです。

まとめ

CI Againstを使うことで.travis.ymlの更新をサッと終わらせることができるようになります。 Ruby 2.6がリリースされたこの機会に、使っていただけると嬉しいです。


  1. x.y.zのzのことを、RubyではTEENYと言います。 https://www.ruby-lang.org/ja/news/2013/12/21/ruby-version-policy-changes-with-2-1-0/

  2. とはいえ、masterに直pushとかはしないようになっているし、どうせPull Requestの段階で確認をするので、Dry Runはあまり必要がないかもしれませんね。

  3. diffの表示は実装をサボっていてgit-diffを叩いています。git-diff依存消したいね

  4. 正確にはGitHubのデフォルトブランチ

  5. このケースは認識しているので、CI Againstは単に何もしません。