Edited at

GitHub で CI をパスしたら自動マージさせたい。特定のファイル変更のみ限定 with Mergify.IO


GitHub で PR 後、CI のテストをパスしたら自動的にマージさせたい。

ただし、特定のファイルが変更された場合のみ自動マージさせるように限定したい。


例えばリポジトリが、下記の構成だとします。


リポジトリ内のファイル

$ ls

my-script.sh data1.json data2.json run-test-data.sh

このリポジトリに PR(Pull Request)があった場合、テストをパスしてもデータ・ファイルが変更された場合のみ自動マージさせたいのです。(.json=データファイル)

逆に言えば、CircleCI のテストをパスしても my-script.shrun-test-data.sh などのデータ・ファイル以外に変更があった場合は自動マージさせないでレビューさせたいのです。


TL;DR(Automated Merging with Mergify.IO)


自動マージには、マージ処理に特化した GitHub アプリ「Mergify.IO」を利用すると楽。

ただし条件設定に、一工夫が必要。


PR 時の条件設定 pull_request_rules で「変更されたファイル名とファイル数が条件にマッチした」場合にマージさせる設定にします。



  1. files 属性に対象となるファイル名を指定


  2. "#files=1" と個数の設定にファイル数を限定

ポイントは、この時に「FILE_A OR FILE_B」と「FILE_A AND FILE_B」の2種類の記述を追加することです。



  • OR 処理(FILE_A OR FILE B


    • 変更を許可したいファイルごとにルールセットを作成します。




  • AND 処理(FILE_A NAD FILE_B


    • 変更を許可したいファイル名すべてを記載したルールセットを作成します。




OR処理

pull_request_rules:

- name: automatic merge on CircleCI success if data1.json is changed
conditions:
- "status-success=ci/circleci: build"
- base=master
- files=data1.json
- "#files=1"
actions:
merge:
method: merge
strict: true

- name: automatic merge on CircleCI success if data2.json is changed
conditions:
- "status-success=ci/circleci: build"
- base=master
- files=data2.json
- "#files=1"
actions:
merge:
method: merge
strict: true



AND処理

pull_request_rules:

- name: automatic merge on CircleCI success if data1.json is changed
conditions:
- "status-success=ci/circleci: build"
- base=master
- files=data1.json
- files=data2.json
- "#files=2"
actions:
merge:
method: merge
strict: true


TS;DR


Mergify.IOとは

Mergify.IO とは PR 時のマージ操作に特化した CI の1種です。GitHub App として提供されており GitHub Marketplace から追加できます。オープンソースの場合は無料で利用できます。

PR があった場合に「CI のテストをパスし、コードレビューで n 件の承認(Approve)が付いたら自動的にマージさせ、作業ブランチを削除する」といった自動化ができます。

基本的な仕組みはシンプルです。


  1. PR 時の他のサービスやユーザーの操作から付いたコメントを解析

  2. コメントが指定された文字列を含んだ場合にトリガー(発動)する

そのため、CI は CircleCI に限らず TravisCI や自作 GitHub App でも条件に追加できます。

少人数で開発されており、まだ若いサービスなので細かいところでドキュメントの情報が足りないのですが、2019/06/11現在、本体エンジン精力的に開発されています。


Mergify.IO の使い方


  1. アカウント作成(GitHub アカウントで OAuth ログイン)

  2. GitHub 上のリポジトリに .mergify.yml をアップロード(コミットしてプッシュ)

  3. 別途何か PR をして動作を確かめる

一般的な GitHub App の追加同様、GitHub Marketplace を開き、GitHub アカウントでログイン後、リポジトリに紐づけます。

次に、Mergify.IO の設定ファイルである .mergify.yml ファイルをリポジトリのルートに置き、一度監視対象のブランチ(master など)に反映させると、以降の PR で、その設定ファイルにそったマージ操作を行えます。


Mergify.IO の使い道

なんでも無条件でマージするのは危険です。悪意あるスクリプトを埋め込まれる可能性もあるからです。

しかし、クリティカルでなく Linter によるチェックや CI のテストでパスすれば問題がないファイルで、マージ権限のあるメンバーの手をわずらわせたくない場合に重宝します。例えば README.md の typo だったり、単純なデータの追加などです。

もしくは、レビュー権限のあるユーザーの承認を過半数得た場合にはマージさせるといった具合です。


サンプルを触ってみる

Qiita ユーザとして個人的に興味あるニュース・フィードを集めたリポジトリを用意しました。JSON 形式です。

気になる未登録のフィードを見つけたら、このリポジトリを clone → 追加 → PR をかけてみてください。以下の条件を網羅した場合、自動的にマージされるようにしました。追加できるフィードの趣旨に同意できるならお触り自由です。



  1. *.json ファイルのみが変更されている。

  2. 以下の CI のテストをパスした。(validate_json.sh


    1. 有効な JSON である。(JSON 構文にミスがない)

    2. フィードの URL が重複していない。

    3. 各フィードの登録(要素)の並び順が URL の ABC 順である。

    4. URL 先のフィードが解析可能な状態である。


      • 404 エラーでない。(URL 先が有効である)

      • XML/Atom として有効な構文である。

      • 非可視文字が含まれていない。





なお、URL 先のフィード(XML/Atom)の構文チェックには、URL を指定すると JSON フォーマットに変換するコマンドを作ったので、正常に JSON 形式で取得できたら OK としています。

このリポジトリのポイントは、やはり CircleCI をパスしたら自動マージされる点です。

- files=<FILE NAME> と対象ファイルを限定し、- "#files=n" で変更されたファイル数を指定する組み合わせで、特定のファイルのみの変更の条件を作れます。

複数のファイルを指定したい場合、- files=["FILE1", "FILE2"] といった形式には対応していないので、 - files=<FILE NAME> を複数個指定します

また、同じ条件(condition)内での or には対応していないのですが、ルールを追加(別々の conditionに)することで or 対応できます。

この方法がわからず、Issue で聞いたら親切に教えてもらったので記事にしてみました。