GitHubActions上にreviewdog🐶を導入して、自動でPRコメント形式でTypescriptのエラーを注釈させよう


したいこと、やったこと

Typescriptの型エラーが含まれるコードをGitHubの保護ブランチにマージさせないように、GitHub Actionsを用いてtscに失敗したらチェックを落としたい。さらに、tscが検知した箇所にPRコメントで注釈して欲しい日がある。今回はreviewdogを使って、自動で注釈させるようにした。

reviewdogが使われている既製のGitHub Actionに、eslintのエラーを自動で注釈してくれるRun eslint with reviewdogが公開されているので、これと同様にTypeScriptのエラーも自動注釈できるんじゃなかろうかという考え。

注釈されている様子

実装したworkflow

前提

プロジェクトにnpmパッケージtypescriptが導入されている。

yarn add -D typescript

実装したWorkflow

実装したWorkflowにおけるポイントは以下2点。

  1. Github Actionreviewdog/action-setup@v1を用いることで、Github Actions上でreviewdogを使えるようにしている。
  2. Typecheckステップ。
.github/workflows/main.yml
name: Test
on: [pull_request]

jobs:
  build:
    name: build
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      # ref: https://github.com/actions/setup-node#v2
      - uses: actions/setup-node@v2
        with:
          node-version: "14"
      # ref: https://github.com/reviewdog/reviewdog#github-action-reviewdogaction-setup
      - uses: reviewdog/action-setup@v1
        with:
          reviewdog_version: latest
      # ref: https://github.com/actions/cache/blob/main/examples.md#node---yarn
      - name: Get yarn cache directory path
        id: yarn-cache-dir-path
        run: echo "::set-output name=dir::$(yarn cache dir)"
      - uses: actions/cache@v2
        id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
        with:
          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-
      - name: Install Dependencies
        run: yarn --frozen-lockfile
      # ref: https://github.com/reviewdog/reviewdog#available-pre-defined-errorformat
      - name: Typecheck
        run: tsc --pretty false --noEmit | reviewdog -f=tsc -reporter=github-pr-review -fail-on-error=true
        env:
          REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.github_token }}

それぞれのポイントについて

reviewdog/action-setup@v1
reviewdog/action-setup@v1GitHub Actions上にreviewdogをインストールしている。reviewdogは種々のチェックツールの出力に対応しており-listオプションをつけて実行するとその一覧が見れる。これらチェックツールの出力を受け取り、その結果をGitHubのPRにコメントをすることができる。

reviewdog -listした結果
terminal
 ❯❯❯ reviewdog -list
rdjson          Reviewdog Diagnostic JSON Format (JSON of DiagnosticResult message)                                             - https://github.com/reviewdog/reviewdog
rdjsonl         Reviewdog Diagnostic JSONL Format (JSONL of Diagnostic message)                                                 - https://github.com/reviewdog/reviewdog
diff            Unified Diff Format                                                                                             - https://en.wikipedia.org/wiki/Diff#Unified_format
checkstyle      checkstyle XML format                                                                                           - http://checkstyle.sourceforge.net/
ansible-lint    (ansible-lint -p playbook.yml) Checks playbooks for practices and behaviour that could potentially be improved  - https://github.com/ansible/ansible-lint
brakeman        (brakeman --quiet --format tabs) A static analysis security vulnerability scanner for Ruby on Rails applications- https://github.com/presidentbeef/brakeman
cargo-check     (cargo check -q --message-format=short) Check a local package and all of its dependencies for errors            - https://github.com/rust-lang/cargo
clippy          (cargo clippy -q --message-format=short) A bunch of lints to catch common mistakes and improve your Rust code   - https://github.com/rust-lang/rust-clippy
dotenv-linter   Lightning-fast linter for .env files. Written in Rust                                                           - https://github.com/dotenv-linter/dotenv-linter
dotnet          (dotnet build -clp:NoSummary -p:GenerateFullPaths=true --no-incremental --nologo -v q) .NET Core CLI            - https://docs.microsoft.com/en-us/dotnet/core/tools/
eslint          (eslint [-f stylish]) A fully pluggable tool for identifying and reporting on patterns in JavaScript            - https://github.com/eslint/eslint
eslint-compact  (eslint -f compact) A fully pluggable tool for identifying and reporting on patterns in JavaScript              - https://github.com/eslint/eslint
fasterer        Speed improvements suggester                                                                                    - https://github.com/DamirSvrtan/fasterer
go-consistent   Source code analyzer that helps you to make your Go programs more consistent                                    - https://github.com/quasilyte/go-consistent
golangci-lint   (golangci-lint run --out-format=line-number) GolangCI-Lint is a linters aggregator.                             - https://github.com/golangci/golangci-lint
golint          linter for Go source code                                                                                       - https://github.com/golang/lint
gosec           (gosec -fmt=golint) Golang Security Checker                                                                     - https://github.com/securego/gosec
govet           Vet examines Go source code and reports suspicious problems                                                     - https://golang.org/cmd/vet/
haml-lint       Tool for writing clean and consistent HAML                                                                      - https://github.com/sds/haml-lint
hlint           Linter for Haskell source code                                                                                  - https://github.com/ndmitchell/hlint
msbuild         (msbuild /property:GenerateFullPaths=true /nologo /v:q) Microsoft Build Engine                                  - https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild
pep8            Python style guide checker                                                                                      - https://pypi.python.org/pypi/pep8
phpstan         (phpstan --error-format=raw) PHP Static Analysis Tool - discover bugs in your code without running it!          - https://github.com/phpstan/phpstan
psalm           (psalm --output-format=text) Psalm is a static analysis tool for finding errors in PHP                          - https://github.com/vimeo/psalm
puppet-lint     Check that your Puppet manifests conform to the style guide                                                     - https://github.com/rodjek/puppet-lint
reek            (reek --single-line) Code smell detector for Ruby                                                               - https://github.com/troessner/reek
rubocop         A Ruby static code analyzer, based on the community Ruby style guide                                            - https://github.com/rubocop-hq/rubocop
sbt             the interactive build tool                                                                                      - http://www.scala-sbt.org/
sbt-scalastyle  Scalastyle - SBT plugin                                                                                         - http://www.scalastyle.org/sbt.html
scalac          Scala compiler                                                                                                  - http://www.scala-lang.org/
scalastyle      Scalastyle - Command line                                                                                       - http://www.scalastyle.org/command-line.html
slim-lint       Tool to help keep your Slim files clean and readable                                                            - https://github.com/sds/slim-lint
sorbet          A fast, powerful type checker designed for Ruby                                                                 - https://github.com/sorbet/sorbet
standardjs      (standard) JavaScript style guide, linter, and formatter                                                        - https://github.com/standard/standard
standardrb      (standard) Ruby style guide, linter, and formatter                                                              - https://github.com/testdouble/standard
stylelint       A mighty modern CSS linter                                                                                      - https://github.com/stylelint/stylelint
tsc             TypeScript compiler                                                                                             - https://www.typescriptlang.org/
tslint          An extensible linter for the TypeScript language                                                                - https://github.com/palantir/tslint

TypeCheckステップ

.github/workflows/main.yml部分
 - name: Typecheck
        run: tsc --pretty false --noEmit | reviewdog -f=tsc -reporter=github-pr-review -fail-on-error=true
        env:
          REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.github_token }}

TypeScriptのコンパイラであるtsc--pretty falseオプションをつけることでエラー出力が簡略化される。reviewdogが受け付けるtscの出力は簡素化された方であるので、このオプションを付与したものをパイプ(|)でreviewdogに送る。

tsc --prettyの有無による違い
terminal
❯❯❯ tsc
src/components/IndexPage.tsx:3:7 - error TS2322: Type 'string' is not assignable to type 'number'.

3 const a: number = "hoge";
        ~


Found 1 error.

❯❯❯ tsc --pretty false
src/components/IndexPage.tsx(3,7): error TS2322: Type 'string' is not assignable to type 'number'.

reviewdogには-fオプションでどのチェックツールの出力が入力されているのか伝えている。ここで-reporter=github-pr-reviewオプションと必要な環境変数をつけることで、自動でPRにコメントがされる。必要な環境変数は$REVIEWDOG_GITHUB_API_TOKENであり、GitHub ActionsWorkflowにおいては上記のような設定をすれば良い。

またreviewdog-fail-on-error=trueオプションをつけることで、エラーが入力されたらGitHubのPRのチェックを失敗させるようにしている。

終わりに

最近の私は、たとえ一人で作るものでも、GitHub Actionsなどを整えることを楽しんでやっています。我が我に出すPRにコメントなんざ付かないところ、botにでもコメントされると賑やかで良いものなんですよね。一人で作るプロジェクトこそあれチェックされる必要がないのに、却って、ロボットなり猫なりタコなりに自分の不注意を指摘してもらいたいというのは、なんか作るにあたって縛りプレイに面白みを感じる手合いだからだと思っています。