Danger「Unused import」僕「ウザ!ww」

CIでktlintCheckを実行してからその結果をDangerでコメントさせていたのですが、報告するだけじゃなくてお前が直してくれという気持ちになったのでCIに修正させようという少年少女の物語である。

背景

Dangerでlintの結果をコメントさせると、unusaed importneedless blank line(s)を自動でレビューしてくれて非常に便利なのですが、

  • 結局ローカルで走らせるktlint Formatは地味に時間がかかって嬉しくない
  • 大きいPRだとDangerからのコメントが大量に来て、レビュワーからのレビューがhidden conversation扱いされることがあってウザい

という嬉しくないポイントをしばしば感じていました。

これどうにかならんかとまずググってみるとpre-commitでlintを実行するものが出てきたのですが、チームの面々のgit commitの実行方法が異なっていて各々設定が必須なのがうむぅなのと、ktlintFormatで時間がかかって嬉しくないのは同じでもっとなんとかならんのかと。そこでCIでやればまじで完全にktlintFormatを意識する必要がなくなって最強無敵、天衣無縫のアイドルテロリスト*1ではと思いました。

どうやったか

before

./gradlew ktlintCheck
bundle exec danger

after

git reset --hard origin/${BITRISE_GIT_BRANCH}
./gradlew ktlintFormat
# ktlintFormatで変更がなければDangerを実行、あれば変更をcommit
if [ $(git status --porcelain | grep .kt$ | wc -l) -eq 0 ] ; then
  ./gradlew ktlintCheck
  bundle exec danger
else
  git config --local user.email "マシンアカウントのメアド"
  git commit *.kt -m "ktlintFormat"
  git push origin HEAD:${BITRISE_GIT_BRANCH}
fi

です。
だいたい書いてある通りなのですが、いくつか説明したいと思います。

まず、git reset --hard origin/${BITRISE_GIT_BRANCH}ですが、これをしないと自ブランチをPRを向けた先にマージしたマージコミットが一緒にpushされてしまうことがあるので最初にpush時と同じ状態に戻しています。

あとは、なんか忘れましたけど一行にいっぱい書くんじゃないよ!みたいなktlintFormatじゃ直らないやつについてはコメントしたいので、lintで差分が出なかったら普通にDangerを走らせてます。

適当なpush -> CIでktlintFormatを実行して差分をpush -> そのpushに対してCIでktlintFormatをかけるが差分が出ないのでDangerが実行

って感じです。

で、どうなん

なんというか、感じてた嬉しくなさは解決できたけど意外と微妙でした。

まずよかったのは、手元で全くlintを意識する必要がなくなった所に尽きます。

で、よくなかったのが、

  • ローカルよりもリモートリポジトリが進んでいる状態になるので、脳死でやってると次にpushした時にリモートの自ブランチをマージしたマージコミットがコミットログに入る。
  • シンプルに二回CIが走る

の二点です。

一つ目に関しては、lintのコミットがリモートリポジトリに入ったらresetなりcherry-pickなりしてローカルリポジトリにもそのコミットを取り込めば問題なくなるんですが、それだと結局lintを意識することになって本末がコケる。で、脳死でlint意識しないでやってるとpush時にAndroidStudioさんから「リモートの方に知らんコミットあったからマージするかい?マージするやで!」って言われてマージコミットが入るんですよね。

二つ目は個人開発とかならモーマンタイなのですが、僕のインターン先ではCIが走るとQA用のビルドが作られてそれが社内でテストできる環境にデプロイされるようになっているので、それが二つ作られてしまうんですよね。しかもlintかけただけなので挙動は全く同じビルドが違ったバージョンで二つ作られる。ぐぬぬぬ。

結論

完璧なktlintFormatなどといったものは存在しない。完璧な絶望が存在しないようにね。
ナナシスを始めませんか?

*1:ナナシスをやってくれ