Dokumi (日本語)

(English version here)

技術部モバイル基盤グループのヴァンサン(@vincentisambart)です。今日は最近作ったツール「Dokumi」の話をしようと思います。

紹介

他部署のエンジニアの仕事をもっと楽にすることが、技術部の重要な目的の1つです。その中で、Dokumiはモバイル開発者のコードレビューの負荷を減らすためのツールです。

なぜ「毒味」という名前にしたかと言うと、人間がレビューする前に、コードに毒(バグ、不自然なコードなど)が入っているかどうか毒味するツールだからです。別の言葉で言うと、少し進化したCI用のlintツールですね。pull requestが出る度に、Jenkinsがそのpull requestにDokumiをかけます。現在はDokumiはiOSアプリだけに対応してしていますが、今後はAndroidアプリへの対応も考えています。

現時点でDokumiは以下のことをやっています。

  • 静的解析(Xcodeの「Analyze」機能)をかけます。 f:id:vincentisambart:20150603121414p:plain
  • 自動テストを走らせます。 f:id:vincentisambart:20150603121409p:plain
  • コミットされたけどXcodeのバージョンデータしか変わっていないXIB/Storyboardファイルを指摘します。 f:id:vincentisambart:20150603121400p:plain
  • pull requestにmilestoneが指定されていないとそれを指摘します。 f:id:vincentisambart:20150603121419p:plain
  • 静的解析や自動テストを走らせるためにアプリをビルドするので、ビルド中に出ている警告やエラーも同時に拾います。

以上のキャプチャーで見られるように、Dokumiは、GitHub Enterpriseと連動して、指摘をpull requestのコメントとして投稿します。指摘の対象がこのpull requestで変わる行であれば、行にコメントを付けます。対象が変わっていない行であれば、pull requestと関係ありそうなものは普通のコメントにまとめて投稿します。pull requestと関係なさそうなもの(例えばこのpull requestで変わっていないファイルに出る警告)は無視されます。

メリット

XcodeのTestやAnalyzeは、開発者が自分自身でかけることができますが、時間かかるし、かけるのを忘れる時もあります。また、 gitに変更を入れるのを忘れることもあります。なのでDokumiはすべてのpull requestに強制的にかけます。因みにXcodeの静的解析のお陰で人間がレビューしたコードでも不具合や変なコードを見つけることができたのでやってみることをおすすめします。

また、直接GitHub Enterpriseのpull requestにコメントを付けるメリットも大きいと思います。pull requestの度に自動テストを走らせるのは、以前から行われていました。しかし、失敗したテストを知るには、Jenkinsのログのxcodebuildの出力を見るしかなく、簡単ではありませんでした。

実は元々Dokumiの結果はウェブページとして整えようと思っていたけれど、良いデザインが思いつかなかったし、わざわざデザイナーに頼んでもな…と思っていたら、単に、普通の人間のレビューと同じようにすればいいだけだと気づきました。

困ったこと

GitHubのAPIを使って実装しようとした時に、特定の行にコメントを付けるには現時点(2015年6月頭)のAPIでは不足しているところがあると気づきました。

特定の行にコメントを付けるエンドポイントの説明を見ると、指定する必要あるのは「The line index in the diff to comment on.」です。ファイルの行番号ではなくdiffの中の行番号ですね。diffから計算するしかない…そしてこれだけだったらまだしも、そもそもAPIでdiffを取得する方法がない…

GitHubはpull requestのURLに.diffや.patchを付けるとdiffを取得できるのですが、そのdiffはpull requestのコメントに使われているdiffと相違があります:ファイル名変更の対応が違います。.diff/.patchで取得できるdiffはファイル名変更が:

  • 旧ファイル名の削除
  • 新ファイル名の追加

になります。pull requestのコメントで使われているdiffはファイル名変更が:

  • ファイル名変更自体
  • 変わっている行だけの追加・削除

になります。gitをコマンドラインで使うと、git diff--find-renames (略して-M) を付けるかどうかの違いと同じです。

GitHubのAPIで取得できるdiffに find-renames を指定できないならどうすればいいのでしょうか。いまDokumiはレポジトリを手元でcloneして、Ruggedというライブラリを使ってdiffを計算します。もし計算のやり方がGitHubのと違っていれば、ズレが出てくる可能性がありますが、それでも大きな問題にならないでしょう。

pull requestでnew-featuremasterにマージしたいと仮定すると、僕の理解が合っていれば、pull requestのページに出ているdiffをコマンドラインで見たいときは:

$ git diff --find-renames `git merge-base new-feature master`..new-feature

質問コーナー

どの言語で実装されていますか? Rubyですね。僕自身も昔からRubyを使っていますし、社内にはRubyエンジニアが多いからです。

どうやって警告やエラーを拾っているのですか? 主に正規表現を使ってxcodebuildの出力から拾っているだけです。静的解析の指摘はxcodebuild analyzeがビルドディレクトリに生成したplistファイルを見ています。

オープンソース化の予定はありますか? まだ未定です。どの環境でも動くようにするにはコストが高いと思いますし、他人が使えないものをオープンソースする意味もあまり感じないですね。でも実装に関する質問あればお答えします。ソースコードがGitHubにて公開されました