自作の CLI ツール matchfile について紹介します。
https://github.com/suzuki-shunsuke/matchfile
この記事の執筆時点で最新バージョンは v0.1.1 です。
変更されたファイルの一覧から実行する必要のあるタスクを導出するための CLI ツールです。 Go で書かれていて、バイナリをダウンロードしてくれば使えます。
Pull Request (以下 PR) の CI では PR で変更されたファイルに応じて 必要なタスク(build, test, lint, etc) だけを実行したかったりします。
そこで、 PR で変更されたファイルパスのリスト と タスクが依存するファイルパスの条件 を元に、そのタスクを実行する必要があるか判定するためのコマンドとして matchfile を開発しました。
ただし、 matchfile の機能としては PR や CI とは独立しているので、もっと別の目的でも使えるとは思います。
matchfile は PR で変更されたファイルパスのリスト や タスクが依存するファイルパスの条件 を取得したりする機能はありません。
PR で変更されたファイルパスのリスト は ci-info という自分が作った別のツールを使うと取得できます。
タスクが依存するファイルパスの条件 はタスクに大きく依存するので matchfile はカバーしていません。
matchfile の使い方としては
$ matchfile run <PR で変更されたファイルパスのリストが書かれたファイルへのパス> <タスクが依存するファイルパスの条件が書かれたファイルへのパス>
で、 PR で変更されたファイルパスのリスト のうち一つでも タスクが依存するファイルパスの条件 にマッチすれば true を、マッチしなければ false を標準出力します。
コマンドの exit code で結果を表現することも考えられましたが、そうすると set -e しているときに若干面倒くさいので、標準出力で表現しました。
ごく簡単な例を示します。
$ echo template/foo.tpl > changed_files.txt
$ echo template > template_dependencies.txt
$ matchfile run changed_files.txt template_dependencies.txt
true
タスクが依存するファイルパスの条件 は独自のフォーマットで指定します。
gitignore のフォーマットにインスパイアされていますが、正規表現が使えるなど、独自のフォーマットになっています。
CI の中でシェルスクリプトで動的に生成することを想定し、行指向のフォーマットになっています。
Go 実装のパーサーが提供されたよく知られた行指向の(コマンドで生成しやすい)フォーマットがあれば良かったんですが、見つからなかったので簡単にフォーマットを定義してみました。
[#][!][<kind>,...] <path>
...
1行に1つ条件を書きます。
上から全部評価されます(どれかマッチしても終わりません)。
# はコメントです。行の途中にコメントを書くことはできません。
! は gitignore と似ていますが、その行を評価する時点で評価結果が true であり、! を除いたその行の評価が true の場合、評価結果が false になります。
日本語が下手くそですね。
簡単な例を示すと、 foo/foo.txt 以外の foo ディレクトリ直下のファイル としたい場合、次のようになります。
glob foo/*
!glob foo/foo.txt
kind は path をどう扱うかを示していて、幾つか種類があります。
- equal: ファイルパスが文字列として完全に一致すればマッチ
- dir: ファイルパスが
<path>/で始まればマッチ - regexp: 正規表現
- glob: グロブ。
**はサポートされてません
kind はカンマつなぎで複数指定でき、複数指定した場合は、先に指定したものからマッチするかテストされ、一つでもマッチしたらその条件がマッチするものとして扱われます。
kind の指定は任意で、指定しない場合、 kind は equal,dir,glob として扱われます。
つまり
foo.txt
は
equal,dir,glob foo.txt
と同じです。
