TL; DR:
yarn v1 の場合、 yarn.lock から当該のパッケージのセクションを削除して yarn install
すればアップグレードできる。
2021年9月9日追記: yarn v2 以降では yarn up -R パッケージ
でアップグレードできるようになった。
困ったこと
GitHub にソースコードをホストしているとある npm パッケージにおいて、 GitHub の Security Alerts が fstream < 1.0.12
の脆弱性を報告した。
yarn upgrade fstream
で最新バージョンにアップグレードしようとしたが……
$ cd my_npm_pkg
$ yarn upgrade fstream
yarn upgrade v1.16.0
[1/5] 🔍 Validating package.json...
[2/5] 🔍 Resolving packages...
[3/5] 🚚 Fetching packages...
[4/5] 🔗 Linking dependencies...
warning " > react-on-rails@8.0.3" has unmet peer dependency "babel-runtime@>= 6".
[5/5] 🔨 Rebuilding all packages...
success Saved lockfile.
success Saved 0 new dependencies.
✨ Done in 7.07s.
$ git diff
(出力なし)
実行しても yarn.lock が変化しない。これは、この npm パッケージが fstream に直接的に依存していないためだった。
調査
どのパッケージが fstream に依存しているかは yarn why fstream
で分かる:
$ yarn why fstream
yarn why v1.16.0
[1/4] 🤔 Why do we have the module "fstream"...?
[2/4] 🚚 Initialising dependency graph...
[3/4] 🔍 Finding dependency...
[4/4] 🚡 Calculating file sizes...
=> Found "fstream@1.0.11"
info Reasons this module exists
- "node-sass#node-gyp" depends on it
- Hoisted from "node-sass#node-gyp#fstream"
- Hoisted from "node-sass#node-gyp#tar#fstream"
info Disk size without dependencies: "140KB"
info Disk size with unique dependencies: "416KB"
info Disk size with transitive dependencies: "788KB"
info Number of shared dependencies: 12
✨ Done in 0.70s.
元を辿れば、(この npm パッケージが直接的に依存している) node-sass が間接的に fstream を引き入れたようだ。
解決策
1. node-sass をインストールし直す
yarn remove node-sass && yarn add -D node-sass
で node-sass をインストールし直せば今回は解決すると思われる。
ただ、こうすると node-sass が依存するパッケージがすべてアップグレードされてしまう。互換性のある semver の範囲内でアップグレードされるとはいえ、一応差分をチェックしないと安心できない。もし今後同様の状況になって、 fstream に依存するパッケージが複数に増えていたら、差分はさらに大きくなることが予想される。可能なら fstream だけアップグレードしたい。
2. yarn.lock から fstream を消して yarn install
yarn.lock から fstream を消して yarn install
すればどうかと思い試してみた。
まずは yarn.lock から fstream で始まる行を探し、そのセクションを丸ごと削除する。
$ git diff
diff --git a/yarn.lock b/yarn.lock
index 3983d00b8b..9a3e1ef0cf 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3624,15 +3624,6 @@ fsevents@^1.2.7:
nan "^2.9.2"
node-pre-gyp "^0.10.0"
-fstream@^1.0.0, fstream@^1.0.2:
- version "1.0.11"
- resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171"
- dependencies:
- graceful-fs "^4.1.2"
- inherits "~2.0.0"
- mkdirp ">=0.5 0"
- rimraf "2"
-
function-bind@^1.0.2, function-bind@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.0.tgz#16176714c801798e4e8f2cf7f7529467bb4a5771"
yarn install
を実行し、 yarn.lock が更新されたか見てみる。
$ yarn install
(略)
$ git diff
diff --git a/yarn.lock b/yarn.lock
index 3983d00b8b..3a44640600 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -3625,8 +3625,9 @@ fsevents@^1.2.7:
node-pre-gyp "^0.10.0"
fstream@^1.0.0, fstream@^1.0.2:
- version "1.0.11"
- resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171"
+ version "1.0.12"
+ resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045"
+ integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==
dependencies:
graceful-fs "^4.1.2"
inherits "~2.0.0"
fstream のセクションが復活し、最新バージョンにアップグレードされたことが分かる。
yarn.lock の一部を書き換えてもいいのか?
yarn の依存解決アルゴリズムを理解しているわけではないが、多分大丈夫だろう。 yarn.lock に書かれているべきパッケージが抜け落ちていれば、 yarn install
は自動的にパッケージをインストールして yarn.lock に追記すると思われる。 package.json の dependencies に手でパッケージを書き加えてから yarn install
するのと状況は同じなのだから。
備考:環境
- node 10.16.0
- npm 6.9.0
- yarn 1.16.0 (yarn lockfile v1)