にゃみかんてっくろぐ

猫か百合を見守る壁になりたい

yarn/npm outdated は、古いパッケージがあると終了コード 1 を返すバージョンもある

コードリーディングのメモ。

まとめ

outdated コマンドで古いパッケージが見つかった場合の終了コード:

パッケージマネージャ バージョン リリース日 終了コード
Yarn >=0.26.0 2017/06/06 1
<0.26.0 - 0
npm >=7.0.0 2020/10/13 0
>=4.0.0 <7.0.0 2016/10/21 1
<4.0.0 - 0

※記事執筆時点の最新バージョンは、 Yarn 1.22.10 (2020/10/02), npm 7.3.0 (2020/12/19)

outdated コマンド

yarn outdated あるいは npm outdated は、 古いパッケージを表示してくれるコマンド。 upgrade コマンドと異なり、アップグレードされることはない。

$ npm outdated
Package                 Current  Wanted  Latest  Location
@holiday-jp/holiday_jp    2.2.3   2.3.0   2.3.0  yarn-update-check

これを CI で活用するとして、終了コードが 0 以外になればとてもお手軽だ。 outdated コマンドを CI で実行させておくだけで、最新バージョンがあると勝手に CI が失敗するようになる。

しかし、残念ながらドキュメントに終了コードの記載はない。実際の動きを確かめつつ、ソースコードで歴史を紐解く必要がある。

Yarn

Yarn は yarnpkg/yarn@c4f264f で終了コード 1 を出力するようになっている。タグを見る限り v0.26.0 (2017/6/6) のようだ。

yarn/outdated.js at master · yarnpkg/yarn · GitHub

export async function run(config: Config, reporter: Reporter, flags: Object, args: Array<string>): Promise<number> {
  // 略
  let deps = await PackageRequest.getOutdatedPackages(lockfile, install, config, reporter);
  // 略
  if (deps.length) {
    // 略
    return 1;
  }
  return 0;
}
$ yarn outdated
yarn outdated v1.22.10
info Color legend :
 "<red>"    : Major Update backward-incompatible updates
 "<yellow>" : Minor Update backward-compatible features
 "<green>"  : Patch Update backward-compatible bug fixes
Package                Current Wanted Latest Package Type URL
@holiday-jp/holiday_jp 2.2.3   2.2.3  2.3.0  dependencies https://github.com/holiday-jp/holiday_jp-js
Done in 0.11s.

$ echo $?
1

この変更の元となる Issue #3483 には、「 npm outdated はこういうとき 1 を返している」とある。

npm

>=4.0.0 <7.0.0

npm はリリースノートによれば v4.0.0 (2016/10/21) で終了コード 1 を出力するようになっている。

BRIEF OVERVIEW OF BREAKING CHANGES
(略)
- npm outdated exits with exit code 1 if it finds any outdated packages.

npm/outdated.js at v4.0.0 · npm/npm · GitHub

function outdated (args, silent, cb) {
  // 略
      if (er || silent || list.length === 0) return cb(er, list)
      // 略
      process.exitCode = 1
$ npm -v
6.14.0
$ npm outdated
Package                 Current  Wanted  Latest  Location
@holiday-jp/holiday_jp    2.2.3   2.2.3   2.3.0  yarn-update-check

$ echo $?
1

>=7.0.0

ただし、 v7.0.0 からはふたたび終了コード 0 を出力するようになっているようだ。リリースノートには特に破壊的変更のアナウンスは見当たらず、意図したものかそうでないものかを調べきれていない。

cli/outdated.js at v7.0.0 · npm/cli · GitHub

$ npm -v
7.3.0
$ npm outdated
Package                 Current  Wanted  Latest  Location                             Depended by
@holiday-jp/holiday_jp    2.2.3   2.2.3   2.3.0  node_modules/@holiday-jp/holiday_jp  node15

$ echo $?
0

おわりに

例えば grep のマニュアルには終了コードについて明記されている。

通常では、選択される行が見つかったときの終了ステータスは 0 であり、 見つからなかったときは 1 であり、エラーが起きた場合は 2 です。 ただし、 -q , --quiet , --silent といったオプションが使われていて、選択される行が見つかったときは、 エラーが起きたときでも終了ステータスは 0 です。

Man page of GREP

yarn/npm outdated のマニュアルには記載がない。そして、仕様として挙動が維持されるかは分からない。これをどこまでアテにしていいのだろうか、いささか不安が残る結果になってしまった。 --json オプションをつけて JSON を解釈したほうがいいだろうか。