一言でいうとreviewdogの紹介をするだけなのですが、すごくタイミングよく罠にハマった?ので、それの暫定的な回避も書いておきます。
前提の解説
- GitHubのpull reqにはsuggestという、インラインのコメントで変更を提案する機能がある https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/incorporating-feedback-in-your-pull-request
- scalafmtはここ数年のScala界隈で完全にデファクトなformatter https://github.com/scalameta/scalafmt
- scalafixは、組み込み、あるいは任意の独自ルールを書いて、コード修正、リファクタするツール https://github.com/scalacenter/scalafix
- reviewdogはすごく色々機能あるのだけど、機能多いし全部詳しくないので公式見てくれ〜
個人的にはここ数年、いくつかのprojectで
- scalafmtはほぼ全部使ってる。projectによって、以下のようなことしてる
- scalafix
- チェックして、エラーにするか、警告出す
- 警告の表示にreviewdog使ってる場合もある
- cronで一定時間毎、あるいはpull reqで特定のコメントをトリガー、あるいはworkflow_dispatchでscalafix起動させる(適用したpull req出す)
などをやっているのですが、reviewdogのsuggestは機能使ってませんでした。
上記の運用でも大抵は十分なのと、動かし方理解するのと動作確認が面倒だっただけなのですが、やってみたら思った以上に特別な仕組み必要なくて簡単でした。
特別な仕組み必要なくて
とは、つまり
「CI上で コード修正した状態
を作って(gitでdiff出る状態作って)、reviewdogの特定のコマンド呼ぶだけ」
でいいんですね。何かこちらで特別なフォーマットで頑張って出力する必要とかないので、言語やツールに全く関係なく使えます。
むしろ、suggestではなく、警告やエラーをインラインコメントするほうが、原理上、言語毎の警告やエラーの出力のparserが必要で面倒ですね。 *1
つまり、最低限scalafmtをsuggestするだけなら、以下で動きました。 *2
on: pull_request: jobs: test: runs-on: ubuntu-latest timeout-minutes: 10 # ここは適当に調整しましょう steps: - uses: actions/checkout@v3 - uses: actions/setup-java@v3 with: java-version: 11 # あくまで例で、個々のprojectによって適切なversion distribution: adopt - run: sbt scalafmtAll scalafmtSbt # Checkの方ではない方を使うのがポイント - run: git diff --exit-code # このあたり雑だが、もう少し工夫していいかも - uses: reviewdog/action-suggester@v1 if: failure() with: tool_name: scalafmt
それで、これをいくつかに導入していこうかと思ったら、昨日まで動いていたのに、急に動かなくなりました。 reviewdogのinstall scriptがGitHub側の変更に影響受けたみたいです。
(reviewdogのscriptが、GitHubの普通のAPIじゃなくて、GitHub側の実装依存なものを呼び出してる?)
https://github.com/reviewdog/reviewdog/issues/1380
なので、reviewdogほぼ手動でinstallしてsuggest呼び出しも試したりしたので、それのパターンも貼っておきます。
正しいinstall方法が復活したとしても、原理的にはこのほうがversion固定で余計なアクセスしなくて安定するかも・・・?
ubuntu-latestだと Linux_x86_64
なので、そこは固定してしまってますが、必要なら適当に変えましょう。
(細かいところ雑なので、そもままカレントディレクトリに直接展開してるが、必要ならもっと丁寧にやったほうが良い)
https://github.com/wartremover/wartremover/commit/913a7746a2223ac95809ad8514c576354e26ce53
# ここより前は省略 - if: ${{ (github.event_name == 'pull_request') && failure() }} run: | REVIEWDOG_VERSION="0.14.1" FILE_NAME="reviewdog_${REVIEWDOG_VERSION}_Linux_x86_64" wget -q https://github.com/reviewdog/reviewdog/releases/download/v${REVIEWDOG_VERSION}/${FILE_NAME}.tar.gz gunzip ${FILE_NAME}.tar.gz tar -xf ${FILE_NAME}.tar chmod +x ./reviewdog ./reviewdog -version export REVIEWDOG_GITHUB_API_TOKEN=${{ secrets.GITHUB_TOKEN }} TMPFILE=$(mktemp) git diff > "${TMPFILE}" ./reviewdog \ -name="scalafmt" \ -f=diff \ -f.diff.strip=1 \ -reporter="github-pr-review" \ -filter-mode="diff_context" \ -fail-on-error="false" \ -level="warning" <"${TMPFILE}"
scalafmtの例で示しましたが、scalafixなら、単に警告出す系のlinterのruleではなく、直接書き換えるruleを scalafixAll
で実行してしまって、その後のreviewdogの呼び出し方は完全に同じでいけるはずです。
-name="scalafmt"
はsuggestの表示に使われる部分なので、適切に変えてください。