NPM パッケージを最新に保つ方法を考える

皆さんは、フロントエンドで使っている NPM パッケージを更新してますか？

私は意識が低いので、約 1 年くらい放置してました。。

放置してしまうと、差が大きいバージョンアップのリスクが増えたり、
パッケージのセキュリティリスクが見つかった時にすぐに対処できなくなる可能性があるので、
定期的に更新した方が良いと思います

今回は、以下の 2 つを紹介します

- バージョンアップが行われたパッケージを定期的に通知する仕組みを作成
- `yarn upgrade-interactive`を使ったバージョンアップ

NPM パッケージを通知／更新するサービスは既にありますが、通知するだけなら簡単に実装できるので作ってみます

## バージョンアップが行われたパッケージを定期的に通知する仕組みを作成

### 準備

##### Slack と CircleCI を連携して、HookURL を発行

https://my.slack.com/apps
こちらから CircleCI を検索して、追加する

HookURL をコピーしておく
`https://hooks.slack.com/services/...`

##### HookURL を CircleCI の環境変数に登録しておく

SETTINGS -> Projects -> 対象の GitHub リポジトリを選択 -> 設定アイコンをクリック -> Environment Variables -> Add Variable

今回は SLACK_WEBHOOK_URL っていう変数名で登録

### CircleCI の改修

修正箇所だけ抜粋します

```yml:.circleci/config.yml
version: 2
jobs:
  outdated:
    <<: *setup-docker
    steps:
      - checkout
      - restore_cache:
          name: Download and cache dependencies
          keys:
            - v1-dependencies-{{ checksum "package.json" }}
            - v1-dependencies-
      - run:
          name: Install
          command: yarn install
      - run:
          name: Outdated
          command: |
            PAYLOAD=`cat << EOF
            {
              "attachments": [
                {
                  "pretext": "outdated",
                  "text": '$(yarn outdated --json | $(yarn bin)/format-yarn-outdated)',
                  "mrkdwn_in": ["text"]
                }
              ]
            }
            EOF`
            curl -X POST -d "payload=$PAYLOAD" $SLACK_WEBHOOK_URL

...

workflows:
  version: 2
  nightly:
    triggers:
      - schedule:
          cron: '00 0 * * *'
          filters:
            branches:
              only:
                - master
    jobs:
      - outdated
```

##### 流れ

1. workflows の triggers 機能を使って、cron を使った定期ジョブを登録しておく  
   （時間は UTC なので、上記例だと午前 9 時に実行されることになる）
1. outdated ジョブ内で HookURL に cURL

`$(yarn outdated --json | $(yarn bin)/format-yarn-outdated)`がやっていることは、
`yarn outdated`を Slack 上で見やすくするために、以下のパッケージを使って加工している
https://www.npmjs.com/package/yarn-outdated-formatter

##### 補足

- CircleCI 2.0 以上
- 使う Docker イメージは Node.js ベースのやつ

##### 結果

<img width="421" alt=" 2018-12-18 14.42.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/168197/49068dc5-1e03-1275-8bd4-d05b968ba301.png">

届いた！

でも Slack で Markdown 見れるようにしたけど、テーブルは対応してないのね。。:cry:
でも`yarn outdated`の結果を定期的に通知できるようになったので、とりあえずはオッケーです

1 日 1 回の通知だと多いので、週 1 回とかでもいいかなと思う（`cron: '00 0 * * 1'`）

## `yarn upgrade-interactive`を使ったバージョンアップ

パッケージの更新を定期的に通知してくれるようになったので、今度は実際にバージョンアップする作業です

今までは、パッケージの最新バージョンを確認して、`yarn upgrade autoprefixer@9.4.3`とかやってたけど、
`yarn upgrade-interactive`を使えば、それらがまとめて出来ます（しかも複数パッケージをまとめて）

試しに、package.json があるルートディレクトリ内で`yarn upgrade-interactive`を実行してみてください

すると、以下のような画面になります
<img width="1083" alt=" 2018-12-18 14.53.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/168197/1a3d27ee-d489-7b6b-1022-14adc0ee36fd.png">

バージョンアップしたいパッケージを Space キーで選択
全選択は a キー

<img width="1072" alt=" 2018-12-18 14.57.12.png" src="https://qiita-image-store.s3.amazonaws.com/0/168197/4aa96c45-0e4e-044a-3a9b-307735db237f.png">

実行は Enter キー

オプション無しで`upgrade-interactive`を実行すると、package.json の範囲内でのみバージョンアップが行われる
なので、yarn.lock のみを更新する

レジストリの最新を見て、バージョンアップを行いたい場合は、`--latest`オプションを付けて実行する

```sh
yarn upgrade-interactive --latest
```

メジャーバージョンアップされたパッケージも出てくるようになったかと思います
ちなみに`--latest`オプションを付けてパッケージを更新した場合は、yarn.lock と package.json の両方を更新します