ぱすたけ日記

日記っぽいのを書きます。

npmモジュールのアップデートのハードルを下げたい話

このエントリーはKMC Advent Calendar 2018の13日目の記事であり、はてなエンジニア Advent Calendar 2018の13日目の記事でもあります。クロスポストです。よろしくおねがいします。

12日目の記事はそれぞれ以下の記事でした。

npmモジュールのアップデートとの向き合い

皆さん、npmモジュールのアップデート、やっていっていますか?

npmモジュールのアップデートをやっていくこうとしても、フロントエンドで使っている結果としてブラウザを用いた動作確認が大変だったり、そもそもnpmモジュールに詳しくないと影響範囲が分からなくて敬遠されてしまった結果、詳しい一部の人がnpmモジュールのアップデートを気が向いたときにやって治安をなんとか維持しているという状況も少なくないと思います。

  • npmモジュールのアップデートは頻繁に行いたい
    • しかし、ChangeLogの追随や差分検証、動作検証など色々やることがあって億劫
    • npmモジュールに対するコンテキストを有していないと、どれがどのように作用をするのかもイマイチ当たりがつかない
  • なので、npmモジュールのアップデートは気合がある人が月1とかにガッとやる羽目になっていて、なかなか横展開できていない
    • 依存性が高い
  • 月1くらいだと積まれているモジュールも多いので、なかなかその状態からmajorアップデートもやるぞとはならない

こういったnpmモジュールのアップデートのコストが高いとメンバーが感じている状況を少しでも緩和するためのアイデアとそれを具体化するCLIツールを作ったのでご紹介です。

npm-safety-updater

上記のような問題について話していたときにこの問題に向き合うアイデアとして次のようなことが挙がりました

  • ユーザーに配っているJSの中身が変わったら何はともあれ結局手で確認することからは逃れられない
  • 逆に言うと、それに差分が無いときはリリースに載せても問題ないと判断して良さそう
    • 今はここも手で上げてみて差分があるかないかを見ているので、それを自動化出来ると、人間は動作確認が必要だったり、複雑なメジャーバージョンアップに注力できそう
  • また、buildやテストのプロセスが成功するかどうかもコマンドを叩いてみれば分かるはずなので自動化されたい

こういったアイデアを元に作ったのがnpm-safety-updaterです。

主な機能として以下のようなものがあります。

  • アップデートしたいdepsの種類を指定できる
    • 例えば、devDependencies だけを指定するということが出来ます
  • アップデートするバージョン差分をpatch,minor,majorから選択できます
    • patchバージョンアップなら破壊的変更がない細やかな変更だけなので自動化できそうということで対象にするとか出来る
  • テストコマンドを実行して成功したものだけアップデート
    • 設定ファイルで諸々指定できます
  • 失敗するとpackage.jsonやlockを巻き戻す
    • npm ciなどのコマンドを使った掃除もやってくれます

例えば次のような設定ファイルを用意すると、初期状態でbuildしたものとjs,cssのdiffが無い場合に成功となった後にgitのcommitまでやってくれるような設定を書くことが出来ます。

{
  "prepare": [
    "yarn run build",
    "mkdir -p /tmp/safety-build",
    "cp -f public/dist/{admin,application}.{js,css} /tmp/safety-build"
  ],
  "testCommand": [
    "yarn run build",
    "diff public/dist/admin.js  /tmp/safety-build/admin.js",
    "diff public/dist/admin.css /tmp/safety-build/admin.css",
    "diff public/dist/application.js /tmp/safety-build/application.js",
    "diff public/dist/application.css /tmp/safety-build/application.css"
  ],
  "onlySuccess": [
    "cp -f public/dist/{admin,application}.{js,css} /tmp/safety-build",
    "git add package.json yarn.lock",
    "git commit -m 'update %PACKAGE_NAME% to v%GOTO_VERSION%'"
  ]
}

1つずつのモジュールをインストールしてはビルドし検証しnpm ci等で環境を整えというのが行われるので、実行自体には時間がかかりますが、それでも人間がちまちまと確認していたのを空き時間やJenkinsなどを利用して実行することが出来るので、まずはこのコマンドを叩いてみるだけでも、アップデート一部は出来るようになるので便利だと感じています。

また、この結果例えば@typesから持ってきているものがpatchバージョンアップで型定義が改善された結果buildに失敗するということにも気づけるので助かっています(こういったものは後で結果を見て人間が手で調整することになるのですが、それでも対象モジュールを手で眺めていくのに比べれば大きな進歩なのではないでしょうか)。

オススメはひとまず npx npm-safety-updater patch,minor --only-devを実行してみることです。普段なかなかアップデートしていないと初回は時間がかかりがちですが、2回目移行は数も減り、確認が本当に必要なものだけに注力できるようになると思います。

また、以前id:masawadaが紹介していたyarn-outdated-formatterとmackerelの組み合わせなどでアラートを出すようにして、そのタイミングでひとまずsafety-updaterを使うというのも良いのではないかなと思っています。

今後の展望について

  • 現在、npm|yarn outdated --json の出力順に結果が依存しているのでなんか上手いこと順番に依存しないようにしたい
  • 設定ファイルの良い感じの雛形を提供したい

何かあれば是非GitHubのissueなどで教えてください → https://github.com/pastak/npm-safety-updater/issues/new

宣伝コーナー

京大マイコンクラブでは部内のシステムのアップデートをやっていきたい新入部員を年中無休で募集しています。京大生はもちろん、他学の大学生や社会人、高校生でも歓迎です。詳細は以下を御覧ください。

株式会社はてなではこのような開発における問題をエンジニアリングで解決するのが好きな方を募集しています。正社員はもちろん僕みたいなアルバイトでも歓迎です。まずはお気軽にランチでもどうですか?