Dart analyzer の出力を GitHub のファイル上に表示する

普段 Flutter の CI には GitHub Actions を使っているのですが、Typescript で eslint を実行したときにはエラーの内容が Pull Request の File chaged タブに表示されるのに Dart ではそれが効かなかったのが気になっていました。

調べてみると、GitHub Actions には Problem Matchers というファイルをハイライトする機能があって、 指定した正規表現にマッチしたログを自動的に File changed タブに出力してくれるらしいです。

GitHub Actions の setup-node や setup-go などには Problem Matchers を自動的に有効にする設定が入っているので何もしなくてもエラーの内容がハイライトされますが、 setup-dart にはそれがないため自前で設定する必要があります。

設定方法

まずどのようなエラーをハイライトするかを書いた json ファイルを用意します。

dart analyzer は以下のようなエラーを出力するので、

Analyzing problem_matcher_sample...

   info • Only use double quotes for strings containing single quotes • lib/main.dart:15:14 • prefer_single_quotes
warning • The receiver can't be null, so the null-aware operator '?.' is unnecessary • lib/main.dart:34:13 • invalid_null_aware_operator
  error • A value of type 'int' can't be assigned to a variable of type 'String' • lib/main.dart:40:16 • invalid_assignment

これに合わせて以下のような json を用意します。

{
  "problemMatcher": [
    {
      "owner": "dart-analyzer",
      "pattern": [
        {
          "regexp": "^\\s*(info|warning|error)\\s•\\s(.*)\\s•\\s(.*):(\\d+):(\\d+)\\s•\\s(.*)$",
          "severity": 1,
          "message": 2,
          "file": 3,
          "line": 4,
          "column": 5,
          "code": 6
        }
      ]
    }
  ]
}

problemMatcher > pattern > regexp がエラー文を拾うための正規表現です。その後に続く severitymessage はエラー文のどの部分がどういう情報かを教えるためのものです。 数字が出現する順番に紐づいています。

  error • A value of type 'int' can't be assigned to a variable of type 'String' • lib/main.dart:40:16 • invalid_assignment
  ^^^^^   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^    ^^^^^^^^^^^^^ ^^ ^^   ^^^^^^^^^^^^^^^^^^
  ①重要度                   ②エラー本文                                              ③ファイル   ④行⑤列     ⑥エラーコード

次に用意した json ファイルを使ってワークフロー上で Problem Matchers を有効化します。

GitHub Actions のコマンドを使って登録できるので、実際に analyze コマンドを走らせる前 step に以下のように追加します。

name: check

on:
  pull_request:

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: subosito/flutter-action@v1
        with:
          flutter-version: "3.0.1"
      - run: echo "::add-matcher::.github/analyzer-problem-matcher.json"
      - run: flutter pub get
      - run: flutter analyze
      - run: echo "::remove-matcher owner=dart-analyzer::"

これで準備は完了です。試しにエラーを含めたコードを push してみると以下のように File changed 部分にハイライトして表示されているのが分かります。

GitHub Actions のスクリーンショット

https://github.com/itome/problem_matcher_sample/pull/1/files

サンプルコードは以下のリポジトリです。

https://github.com/itome/problem_matcher_sample