npm dependenciesを更新してGitHub Compare Viewのリンク付きでPRするツールを定期実行する

タイトルに要素を詰め込みすぎましたが、要は CircleCIを使ってbundle updateを定期実行する - Qiitanpm update 版です。web appのJavaScriptライブラリ管理にnpmを使うとき、依存関係のアップデートを継続的に行うためのツールです。

https://github.com/bitjourney/ci-npm-update

これはいまのところGitHub専用です*1。CIサービスはドッグフーディングも兼ねてCircle CI用の起動スクリプトを同梱してますが、実際には ci-npm-update を定期実行するだけなので簡単に代替可能です。

これはCircle CI + Heroku Schedulerで動かしていて、以下のようなフローです。Circle CIはJenkins含め他のCIでも動かせますし、Heroku Schedulerはcronなどでも代替できます。

  1. Heroku Schedulerはci-npm-updateを実行するためのパラメータを渡してCircle CIのビルドを起動する
  2. ビルドのdeploymentフェーズで ci-npm-update --execute を実行する
  3. ci-npm-updateは npm-shrinkwrap.json を削除したあと npm install をしなおす((npm update --depth 9999 のほうが効率がいいはずなのですが、こちらはある程度の規模のプロジェクトだとOOMで落ちてしまうので npm install しなおすことにしました。))
  4. ci-npm-updateはさらに npm shrinkwrap で依存関係のバージョンを固定し、変更をcommitし、pushし、githubのpull-requestをつくる
  5. このときpull-requestはアップデートの前後のnpm-shrinkwrap.jsonをもとにgithub compare viewへのリンクをつくり、PRの本文に入れる

送られるpull-requestはこんな感じです。

https://github.com/gfx/ci-npm-update/pull/8

f:id:gfx:20160728000115p:plain


さて、それではこれを定期的に実行する必要がありますが、これは元エントリのとおりCircle CIのparameterized buildをHeroku Schedulerで起動します。

そのアプリのテンプレートも同リポジトリに入っているので、簡単に試したければ "Deploy to Heroku" ボタンで適当にHeroku appをつくり、Heroku Schedulerで定期実行します。たとえばci-npm-update自身の設定はこんな感じ。

f:id:gfx:20160728000608p:plain

あとは各種設定が必要ですね。

設定

Heroku

"Deploy to Heroku" ボタンでアプリを生成するときにCIRCLECI_TOKEN などの設定が必要なので、それらを指定してください。

TRIGGER_NAME は circle.yml でci-npm-updateを起動する条件分岐に使います。必要なければデフォルトでかまいません。

circle.yml

Heroku appの TRIGGER_NAME が渡ってきたらci-npm-updateを起動する、という設定を追加します。

ci-npm-update自身の設定はこんな感じです。

https://github.com/gfx/ci-npm-update/blob/master/circle.yml

抜粋:

deployment:
  update-dependencies:
    branch: master
    commands:
      - >
        if [ -n "${NPM_UPDATE}" ] ; then
          bin/ci-npm-update --execute
        fi

Circle CI

Circle Ciからは、(1) github repoにgit pushする権限 (2) github repoにpull-requestを送る権限 がそれぞれ必要です。

まずpushする権限をつくるために、repoに対してread/writeできるuser keyを作ります。

Circle CIの Project Settings -> Checkout SSH key -> Add user key

f:id:gfx:20160728002103p:plain

次に、GitHubのaccess tokenを生成してCircle CIに設定します。

GitHub Settings -> Personal access tokens で "repo" scopeをもつaccess tokenを生成し、 Circle CI projectの環境変数で GITHUB_ACCESS_TOKEN という名前で設定してください。

また、Circle CIでgit commitをするために git config user.namegit config user.email が必要なので、それぞれ環境変数GIT_USER_NAMEGIT_USER_EMAILを通じて設定します。

設定が済むとこんな感じです。

f:id:gfx:20160728091520p:plain

検証

もろもろうまくいっていれば、以下のコマンドでHeroku Schedulerを待たずにci-npm-updateを起動でき、pull-requstが送られるはずです。

heroku run -a $app './build-circleci'

成功すると、create pull-request apiの結果であるJSONが表示されます。

また、ローカルで実行する場合は、無引数で実行するとdry runモードで実行しPRの内容を確認できます。ただし、dry-runモードでも node_modules/ の内容はアップデートされるのでご注意ください。

まだ作ったばかりで導入実績も少ないですが、よければ使ってみてフィードバックをいただけると嬉しいです。

*1:github enterpriseでも動くはずですが試してません。他のgit hosting serviceも要望があれば対応するかも。