graphql-schema-linterの結果をreviewdogに食べさせる🐶

これは kawasaki.rb #77 で発表する予定の記事です。

Tl; Dr;

  • これを参考にlintの結果をformatする
  • CIに設定書く
  • 🐶に怒られるようになる

graphql-schema-linterを使いたかった

最近の業務では複数のマイクロサービスのレスポンスを束ねるBFF的な役割でgraphqlサーバーをフロントエンドの後ろに立てている。最近出たvvakameさんの薄い本graphql-schema-linter が紹介されており、我々のプロダクトにも導入したいと思ったので早速実行してみた。

f:id:Peranikov:20191022231640p:plain

> ✖ 411 errors detected

こんなもの入れたらCI通るまでにいつまで掛かるかわからないだろ!いいかげんにしてください。こういうlinterを後からプロダクトに入れようと思ったらPRの差分にだけ当てたくなるのが人間ってものです*1。なのでみんな大好きreviewdogちゃんに食べさせてあげましょう。

reviewdogとは

github.com

reviewdogはPRの差分にCI上で実行したlintの結果が含まれていたらその部分にコメントを付けてくれる大変便利なツールです。プリセットとしてgolintやgovetが含まれていますが、lintの結果をformatしてあげることでどんなlintも対応することができます。

lintの結果をformatする

formatはreviewdogのInput formatを参考にします。graphql-schema-linterは結果をjsonで出力できるので、jsonを読み込んで一行ずつのフォーマットになるようにパースする下記のようなスクリプトをnode.jsで書きました。node.jsで書いたのはgraphql-schema-linterを動かすのに必要だったからで、何の言語で書いてもいいです*2

'use strict';

// see: https://github.com/cjoudrey/graphql-schema-linter#jsonformatter
// see: https://github.com/reviewdog/reviewdog#input-format

const process = require('process');
process.stdin.resume();
process.stdin.setEncoding('utf8');

let input = "";
process.stdin.on('data', function(chunk){
    input += chunk;
});

process.stdin.on('end', function(){
    const result = JSON.parse(input);

    result["errors"].forEach((err) => {
        // ex. comment_iowriter.go:11:6: exported type CommentWriter should have comment or be unexported

        const loc = err["location"];
        console.log(`${loc["file"]}:${loc["line"]}:${loc["column"]}: ${err["message"]} (${err["rule"]})`)
    });
});

CIにconfigを設定する

.reviewdog.ymlに設定を追加していく。.reviewdog.ymlについてはこちらを参照。

  # https://github.com/cjoudrey/graphql-schema-linter
  graphql-schema-linter:
    # これが何故か途中で出力が止まうので一度ファイルに吐き出している。恐らくpipeのバッファに引っかかっている。
    # cmd: graphql-schema-linter schema/**/*.graphql -f json | node .graphql-linter/format.js
    cmd: graphql-schema-linter schema/**/*.graphql -f json > graphql-schema-linter.json; cat graphql-schema-linter.json | node .graphql-linter/format.js
    errorformat:
      - "%f:%l:%c: %m"

怒られてみる

以上で設定は完了です。よろしくないschemaを書いて怒られてみましょう。

f:id:Peranikov:20191022234517p:plain

無事に怒られが発生しました。ちなみにreviewdogさんはcheckstyle-formatなら直接読み込んでくれるそうで、linterがこのformatに対応しててくれると自分でパースをしなくて済みます。

ぜひお好みのlinterをreviewdogに食べさせてみてください 🐶

*1:ですよね?

*2:そして別にnodeが得意な訳ではないので見様見真似で書いた