Backlogの課題内容に自動バリデーションをかける

<img width="363" alt="2019-12-15 00-08-45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15611/85b05d88-d2d7-ce1e-5478-3001f1dc20ef.png">

Backlog の課題登録時に、項目を未入力のまま課題登録をしてしまうケースがよくありました。
手作業でのチェックが面倒だったので、自動でバリデーションをかけて、問題がある場合には担当者を課題作成者に差し戻す簡単な処理を、API Gateway/Lambda/CDK で作成してみました。

方針としては、以下の通りです。

- Backlog 上での課題登録・更新時に webhook でチェックツールにデータを飛ばす
- API Gateway で POST リクエストを受け、Lambda でバリデーション処理を行う
- チェックのルール定義には、とりあえず [JsonLogic] を用いる
    - もっと良いものがないか探し中
- バリデーションエラー時は、状態を「未着手」に、担当者を課題登録者に変更する
- 構築には [AWS CDK] を用いる

## 準備

### Backlog の API キーを取得

以下のように、個人設定 -> API に進み、新しく API キーを発行してください。

<img width="1020" alt="2019-12-15 00-20-23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15611/8054a055-c78f-1a58-7c46-99c56944b8b8.png">

> Backlog の API キーは個人単位でしか発行できないようなので、自分自身のユーザー権限で発行しても良いですが、システム連携用のユーザーを作成しておくと便利です。

### AWS CDK のインストール

[AWS CDK] を一度も利用したことがない場合は、`npm i -g aws-cdk` 等で cdk コマンドをインストールし、 `cdk bootstrap` を行ってください。

> switch role や profile を切り替えて利用している人は、`--profile` オプションや `AWS_PROFILE` 環境変数を利用してください。

## 環境構築

https://github.com/u-minor/backlog-issue-validator を clone します。

- `npm install` でパッケージをインストールします。
- TypeScript で CDK のインフラ設定や Lambda function が記述されているため、`npm run build` でビルドしておきます。
- config/environment.yml.example を複製して config/production.yml を作成し、`backlogApiKey` と `backlogBaseUrl` を自身の環境に合わせて設定します。
- `NODE_ENV=production cdk deploy` でデプロイします。

## Backlog の webhook 設定

CloudFormation の Stack の画面に行くと、Outputs の項に API Gateway の endpoint URL が記載されていますので、コピーしておきます。

<img width="1001" alt="2019-12-15 00-41-43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15611/78435a11-0cbf-cc82-5e17-6d6698adbde2.png">

Backlog のプロジェクト設定 -> インテグレーション -> Webhook と進み、Webhook URL にコピーした API Gateway の endpoint URL を入力します。

<img width="1045" alt="2019-12-15 00-43-55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15611/cbdb312c-79c2-253a-6354-10469b8e12dc.png">

以上で設定完了です。

## バリデーションルールのカスタマイズについて

Backlog課題のバリデーションには、[JsonLogic] を用いています。
初期のルールは、

- 課題種別チェック: 未選択の場合にエラー
- カテゴリーチェック: 1つも選択されていない場合にエラー

の2つが登録されています。
課題情報の JSON データに対して比較的柔軟な判定が書けるようになっていますので、好みに応じて好きなルールを追加してみても良いでしょう。

> ルールを追加した場合は、再度 build/deploy が必要になります。

```lambda/logic.yml
課題種別チェック:
  rule:
    '!':
      - in:
        - 未選択
        - var: issueType.name
  error: 課題種別が選択されていません。正しく設定してください。

カテゴリーチェック:
  rule:
    '!!':
      - var: category
  error: カテゴリーは最低1つ選択してください。
```

ルールについての具体的な記述方法は、[JsonLogic] のドキュメントを参照してください。

Backlog の課題情報の JSON フォーマットに関しては、[Backlog API:課題情報の取得](https://developer.nulab.com/ja/docs/backlog/api/2/get-issue/)を参照してください。

## 所感

IaC については、もともと CloudFormation で作成していたのですが、実験も兼ねて AWS CDK に乗り換えてみました。
リソースが自動で生成されるため便利な半面、「何が作られているのか」の把握がしにくいので、`cdk synth` で生成される CloudFormation テンプレートを目視する、ということを繰り返しています。慣れの問題かもしれませんが。
また、CDK 周りのテストの書き方が不慣れで、スナップショットを取ることしかできていないため、要改善。

JsonLogic については、Backlog 課題の JSON データに対して柔軟なロジックによるチェックを簡単にしたかったために採用したのですが、現在 json-logic-js がメンテされておらず、かなり微妙な状態。代替手段を探したいところです。
また、現状は Lambda 内に logic.yml を埋め込んでしまっているため、柔軟にロジックだけ修正できるように、 S3 など別の場所に切り出す等の改修はしたいところです。

[AWS CDK]: https://www.npmjs.com/package/aws-cdk
[JsonLogic]: http://jsonlogic.com/