Skip to content

パッケージマネージャを npm から pnpm へ移行する - #521

Merged
smellman merged 3 commits into
masterfrom
dev/issue-520
Oct 5, 2026
Merged

smellman merged 3 commits into
masterfrom
dev/issue-520

Conversation

@smellman

@smellman smellman commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

Closes #520

開発規約は pnpm のみを使うことになっているが、embed は npm のままでした。移行します。あわせて、移行検証の過程で見つけた maplibre-gl のライセンス表記が配布物から欠落している退行(#519 由来)も直しています。

コミットは 2 本に分けてあります。

9ad6cee chore: pnpm 移行
d147cb8 fix(build): embed-core.js のライセンス表記
8c67324 chore(ci): pnpm/action-setup を v6.1.0 / SHA 固定へ

1. pnpm 移行

配布物は変わりません

公開済み 6.0.0-pre.4 の tarball と npm pack / pnpm pack を突き合わせ、パス集合が一致することを確認しています(下の 2. で増える dist/embed-core.js.LICENSE.txt を除く)。

移行で判明したこと

@types/geojson が phantom dependency だった

素の pnpm install だとビルドが落ちます。

[tsl] ERROR in src/lib/parse-atts.ts(120,13)
      TS2503: Cannot find namespace 'GeoJSON'.

src/lib/parse-atts.ts が GeoJSON 名前空間を使っているのに宣言が無く、npm では maps-core → @turf/bbox → @types/geojson が hoist されたものを拾って偶然動いていました。devDependencies へ明示しています。maps-core が turf を外せば npm でも壊れるので、移行の有無に関わらず直すべきものでした。

pnpm 12 は .npmrc の ignore-scripts を読まない

既存の .npmrc には ignore-scripts=true がありましたが、pnpm 12 ではこの設定が黙って無効になり、esbuild のビルドスクリプトを無視したことが ERR_PNPM_IGNORED_BUILDS となって install が exit 1 になります。pnpm-workspace.yaml へ移設し .npmrc は削除しました。esbuild は 0.25 以降プラットフォーム別パッケージを optionalDependencies で解決するので、ビルドスクリプトを実行しなくても動作します(ビルドも e2e も通っています)。

pnpm pack は .gitignore / .npmignore を同梱する

npm は常に除外しますが pnpm は含めます。.npmignore に明示して公開物を一致させました。

publish も pnpm に

pnpm 12 が OIDC trusted publishing に対応していることをバイナリ内の文字列で確認しました(/-/npm/v1/oidc/token/exchange/package/、ACTIONS_ID_TOKEN_REQUEST_URL、provenance 生成)。現行の公開も実際に trusted publishing です。

_npmUser: {"name":"GitHub Actions","trustedPublisher":{"id":"github","oidcConfigId":"oidc:8d1e…"}}
attestations: provenance (https://slsa.dev/provenance/v1)

これを維持するため、publish ステップはこうしています。

run: pnpm publish --access=public --provenance --no-git-checks
  • --provenance: npm は OIDC publish で provenance を自動付与しますが、pnpm は明示が必要
  • --no-git-checks: 無いと落ちます。 publish ジョブはタグを checkout したうえにビルド成果物を作業ツリーへ展開するので、pnpm 既定の git チェック(ERR_PNPM_GIT_UNCLEAN / ERR_PNPM_GIT_NOT_CORRECT_BRANCH)に引っかかります
  • npm install -g npm@latest ステップは不要になったので削除

実際に publish が通るかはタグを打つまで確認できないので、ここだけ残存リスクです。

その他

  • pnpm/action-setup は setup-node より前に置く必要があります(cache: 'pnpm' が store path を引くため)
  • pnpm のバージョンは package.json の packageManager に固定(pnpm@12.9.1)。pnpm/action-setup はここから読みます
  • pnpm/action-setup は v6.1.0 を commit SHA で固定しています。当初 @v4 にしていましたが、pnpm v12 対応は v6.1.0(feat: support pnpm v12 pnpm/action-setup#288)で入ったもので、packageManager に pnpm@12.9.1 を固定している以上 v4 では動きません。サードパーティ製アクションなので SHA 固定にしました(既存の actions/* はタグ参照のままで、この PR では触っていません)

副次的な効果

Node 22 同梱の npm 10 は vitest ^4.1.1 の peer 解決で arborist が落ち、ローカルで lock を再生成できませんでした(#519 で実際に踏み、やむを得ず npm 11 で生成)。pnpm にすることでこの問題から外れます。

2. embed-core.js のライセンス表記(#519 由来の退行の修正)

移行検証中に気づきました。6.0.0-pre.4 の dist/embed-core.js は maplibre-gl v6 を 1.7 MB ぶん同梱しながら、ライセンス表記も dist/embed-core.js.LICENSE.txt も持たない状態で公開されています。 BSD-3-Clause の表示義務に関わります。

LICENSE ファイル
6.0.0-pre.3 dist/embed.js.LICENSE.txt、dist/embed-core.js.LICENSE.txt、チャンク 2 本
6.0.0-pre.4 dist/embed.js.LICENSE.txt、チャンク 2 本(embed-core は無し)

原因

terser です。maplibre のソース先頭の @license コメントは通常 extractComments が <bundle>.js.LICENSE.txt へ切り出しますが、terser はコメント単体ではなく「コメントが付いているコード」を基準に扱うため、そのコードが削除・並べ替えされるとコメントごと消え、extractComments まで届きません。minimize: false でビルドすると未圧縮バンドルには banner が残っていることを確認しました。

;// ./node_modules/.../maplibre-gl/dist/maplibre-gl-shared.mjs
/**
* MapLibre GL JS
* @license 3-Clause BSD. Full text of license: .../v6.11.2/LICENSE.txt
*/

embed.js だけ残るのは偶然です。embed.ts が Object.assign(..., maplibregl, ...) で名前空間を丸ごと使うため全体が生き残るのに対し、embed-core.ts は maps-core 経由の一部シンボルしか使わないので落ちます。pre.3 まで出ていたのも maplibre 5 系の構造でたまたま残っていただけで、明示していない以上いつ壊れてもおかしくない状態でした。

修正

BannerPlugin で明示します。バージョンは maplibre-gl/package.json から読むので手で追従する必要はありません。

$ head -c 67 dist/embed-core.js
/*! For license information please see embed-core.js.LICENSE.txt */

$ cat dist/embed-core.js.LICENSE.txt
/**
* MapLibre GL JS
* @license 3-Clause BSD. Full text of license: .../v6.11.2/LICENSE.txt
*/

pre.3 と同じ形に戻ります。BannerPlugin は terser より前の段階で走るので banner は通常どおり extractComments に拾われ、embed.js 側は terser が同一コメントを重複排除するため二重になりません(両方ビルドして確認済み)。チャンク側の LICENSE.txt(is-plain-object 等)も従来どおり出ます。

公開済み pre.4 の tarball とのパス差分は dist/embed-core.js.LICENSE.txt が 1 件増えるだけです。

3. CHANGELOG / リリース

pre.4 は公開済みなので ### Unreleased セクションを新設しました。バージョン番号の決定はリリース時の判断としてこの PR では触っていません。見出しの改名だけで済むようにしてあります。

4. 検証

pnpm 12.9.1 / Node 22.21.0 で、すべて green です。

  • pnpm install --frozen-lockfile(CI と同じ)
  • tsc --noEmit
  • pnpm run lint
  • pnpm run test — 15 passed
  • pnpm run build — Critical dependency 警告なし
  • pnpm exec playwright test --workers=1 — 20 passed(CI と同じ直列実行)

maplibre-gl が 1 コピーのままであること、ワークフロー YAML が意図どおりパースされること(build / e2e / publish のステップ順)も確認済みです。

5. 今回触っていないもの

  • files allowlist 化: files: ["dist"] にすると 65 → 23 ファイルになり、src/ / e2e/ / CI 設定 / エディタ設定が配布物から外れます(CHANGELOG.md と PLUGIN.md も消えるので、残すなら列挙が必要)。tarball は 1,539,857 → 1,530,217 bytes とほぼ変わらないので動機はサイズではなく衛生面です。.npmignore も丸ごと不要になります。別 issue にするのが筋だと思います。
  • types フィールドが壊れている: types と exports.*.types が dist/src/embed.d.ts を指していますが、このパスは公開物に存在しません(実体は dist/embed.d.ts)。既存バグです。
  • 兄弟リポジトリ: maps-core / maps-suite / maps-react はいずれも npm のままです。embed で先行して知見を溜める形にしています。

6. セルフレビューで確認したこと / 見ていないこと

zizmor を master と本ブランチで比較しました。この PR による新規の指摘はありません。

base  {"artipacked":5,"excessive-permissions":5,"template-injection":8,"unpinned-uses":17,"cache-poisoning":4,"adhoc-packages":1}
head  {"artipacked":5,"excessive-permissions":5,"template-injection":8,"unpinned-uses":17,"cache-poisoning":4}

adhoc-packages が 1 → 0 に減っているのは npm install -g npm@latest を削除したためです。@v4 のままだと unpinned-uses が 17 → 20 に増えていたので、SHA 固定で元に戻しています。

if: 条件はいずれも既存のままで、増減させていません。publish ジョブは startsWith(github.ref, 'refs/tags/v') が false なら丸ごとスキップ、latest / next の 2 ステップは -pre. の有無で排他です。fork からの PR では build / e2e だけが走り、どちらも secret を使いません。

見ていないもの:

  • pnpm-lock.yaml(7530 行)は行単位で読んでいません。--frozen-lockfile が通ること、テスト一式が通ることで担保しています
  • gh-pages / deploy ジョブは変更していません。npm を使っていないことの確認にとどめています
  • Netlify の設定。リポジトリに netlify.toml はなく、サイト側の設定を見られません。package-lock.json の削除が deploy preview に影響しないかは、この PR の Netlify チェックで確認します
  • publish の実動作。タグを打つまで確認できません(pnpm の OIDC 対応はバイナリ内の文字列で確認したにとどまります)

Summary by CodeRabbit

  • 改善
    • 開発・ビルド・テスト・公開の各手順を pnpm に統一しました。
    • 配布バンドルに MapLibre GL JS のライセンス表記が含まれるようになりました。
  • ドキュメント
    • pnpm の利用方法とバージョン管理について、開発手順に追記しました。

開発規約は pnpm のみを使うことになっているが embed は npm のままだった。
あわせて、Node 22 同梱の npm 10 では vitest ^4.1.1 の peer 解決で arborist が
落ちてローカルで lock を再生成できない問題 (#519 で実際に踏んだ) からも外れる。

配布物は変わらない。公開済み 6.0.0-pre.4 の tarball と npm pack / pnpm pack を
突き合わせ、パス集合が一致することを確認している。

移行で判明したこと:

- @types/geojson は phantom dependency だった。src/lib/parse-atts.ts が GeoJSON
  名前空間を使っているが宣言が無く、npm では maps-core -> @turf/bbox 経由で
  hoist されたものを拾って偶然動いていた。pnpm の厳格なレイアウトでは
  TS2503 でビルドが落ちるため devDependencies へ明示した。maps-core が turf を
  外せば npm でも壊れるので、移行の有無に関わらず直すべきものだった。
- pnpm 12 は .npmrc の ignore-scripts を読まない。設定が黙って無効になり
  esbuild のビルドスクリプトを無視したことが ERR_PNPM_IGNORED_BUILDS となって
  install が失敗する。pnpm-workspace.yaml へ移設し .npmrc は削除した。
  esbuild は 0.25 以降プラットフォーム別パッケージを optionalDependencies で
  解決するので、ビルドスクリプトを実行しなくても動作する。
- pnpm pack は npm と違い .gitignore / .npmignore をパッケージへ含めるので、
  .npmignore に明示して公開物を一致させた。

publish も pnpm にした。pnpm 12 は OIDC trusted publishing に対応している
(バイナリに /-/npm/v1/oidc/token/exchange/package/ と
ACTIONS_ID_TOKEN_REQUEST_URL を確認)。現行の公開も trusted publishing なので
これを維持する。npm は OIDC publish で provenance を自動付与するが pnpm は
明示が要るため --provenance を渡す。--no-git-checks は、publish ジョブが
タグを checkout したうえにビルド成果物を作業ツリーへ展開するため pnpm 既定の
git チェックに引っかかるのを避けるもの。npm install -g npm@latest は不要に
なったので削除した。

pnpm/action-setup は setup-node より前に置く必要がある (cache: 'pnpm' が
store path を引くため)。

検証はすべて green: pnpm install --frozen-lockfile / tsc --noEmit / lint /
test 15 passed / build / playwright --workers=1 20 passed。

Refs #520
6.0.0-pre.4 の dist/embed-core.js は maplibre-gl v6 を同梱しながら、ライセンス
表記も dist/embed-core.js.LICENSE.txt も持たない状態で公開されていた
(6.0.0-pre.3 までは出力されていた)。BSD-3-Clause の表示義務に関わるので直す。

原因は terser。maplibre のソース先頭の @license コメントは通常 extractComments
が <bundle>.js.LICENSE.txt へ切り出すが、terser はコメント単体ではなく
「コメントが付いているコード」を基準に扱うため、そのコードが削除・並べ替え
されるとコメントごと消え、extractComments まで届かない。minimize: false で
ビルドすると未圧縮バンドルには banner が残っていることを確認した。

embed.js だけ残るのは偶然で、embed.ts が Object.assign(..., maplibregl, ...) で
名前空間を丸ごと使うため全体が生き残るからにすぎない。embed-core.ts は
maps-core 経由の一部シンボルしか使わないため落ちる。pre.3 まで出ていたのも
maplibre 5 系の構造でたまたま残っていただけで、明示していない以上いつ壊れても
おかしくなかった。

BannerPlugin で明示する。バージョンは maplibre-gl/package.json から読むので
手で追従する必要はない。BannerPlugin は terser より前の段階で走るので banner は
通常どおり extractComments に拾われ、embed.js 側は terser が同一コメントを
重複排除するため二重にはならない (両方ビルドして確認済み)。

公開済み 6.0.0-pre.4 の tarball とのパス差分は
dist/embed-core.js.LICENSE.txt が 1 件増えるだけで、他は変わらない。

Refs #520
@coderabbitai

coderabbitai Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: geolonia/coderabbit/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Essentials
  • Run ID: 92c32164-ef43-4efc-8d19-b56bbe6ff3fa
📥 Commits

Reviewing files that changed from the base of the PR and between 346a73d and 8c67324.

⛔ Files ignored due to path filters (2)
  • package-lock.json is excluded by !**/package-lock.json
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (9)
  • .github/workflows/build.yml
  • .npmignore
  • .npmrc
  • CHANGELOG.md
  • README.md
  • package.json
  • playwright.config.ts
  • pnpm-workspace.yaml
  • webpack.config.js
💤 Files with no reviewable changes (1)
  • .npmrc

Included review availability: This review used your included allowance. 4 included reviews remain after this review. Your included PR review attempts over the past 7 days set your current allowance at 5 reviews per hour.


📝 Walkthrough

Walkthrough

CI、開発手順、公開処理のパッケージマネージャを npm から pnpm に切り替えます。pnpm の設定と依存関係を追加し、webpack のバンドルに MapLibre GL JS のライセンス表記を付与します。

Changes

pnpmへの移行

Layer / File(s) Summary
pnpm設定とローカル手順
.npmrc, pnpm-workspace.yaml, package.json, .npmignore, playwright.config.ts, README.md
pnpm のバージョンを指定し、ignoreScripts を pnpm の設定ファイルに追加します。開発用依存関係と各種コマンドを更新し、README の手順も pnpm に合わせます。
CIのビルドとテスト
.github/workflows/build.yml
build と e2e のジョブで pnpm をセットアップし、インストール、lint、テスト、ビルド、Playwright の実行を pnpm に切り替えます。
pnpmによる公開
.github/workflows/build.yml
公開コマンドを pnpm に変更します。タグに -pre. を含まない場合は latest、含む場合は next を指定し、両方に provenance と git チェック無効化のオプションを指定します。

ライセンスバナー

Layer / File(s) Summary
MapLibre GL JSライセンスバナー
webpack.config.js, CHANGELOG.md
webpack の BannerPlugin が、インストール済み maplibre-gl のバージョンを含むライセンス表記をバンドルに追加します。変更履歴にこの修正と pnpm 移行を記載します。

Priority: ➖ Normal

Change: Other · Severity of issue fixed: Medium

Merge Risk: ⚪ Minimal · up to 8c673

The pnpm migration and license-banner change appear mergeable after normal checks. The first tagged publish remains unverified.

🚥 Pre-merge checks | ✅ 3 | ❌ 1 | ❓ 1

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning webpack の BannerPlugin による MapLibre GL JS ライセンス表記の追加と、対応する CHANGELOG の記載は、[#520] の pnpm 移行要件に関連しません。PR 説明もこの修正を #519 由来としており、#519 は今回の直接リンク対象ではありません。 ライセンス表記の修正を別の PR に分離してください。
Linked Issues check ❓ Inconclusive [#520] pnpm 移行に必要な @types/geojson、pnpm-workspace.yaml、CI と Playwright の変更、および README の更新を確認できます。PR の説明は install、lint、test、build、Playwright の成功も報告しています。ロックファイルの置換も #520 の要件ですが、package-lock.json と… ロックファイル置換の適合性を判断するには、除外された package-lock.json と pnpm-lock.yaml の追加・削除を確認できる証拠が必要です。
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed タイトルは npm から pnpm への移行を明確に示しており、変更の主目的と一致しています。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 2…
Full details: Linked Issues check

Explanation

[#520] pnpm 移行に必要な @types/geojson、pnpm-workspace.yaml、CI と Playwright の変更、および README の更新を確認できます。PR の説明は install、lint、test、build、Playwright の成功も報告しています。ロックファイルの置換も #520 の要件ですが、package-lock.json と pnpm-lock.yaml は除外対象で、追加・削除を確認できません。

  • Fix all pre-merge checks with AI
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Comment @coderabbitai help to get the list of available commands.

当初 @v4 を使っていたが、pnpm v12 対応は v6.1.0 (pnpm/action-setup#288) で
入ったものだった。packageManager には pnpm@12.9.1 を固定しているので v4 では
動かない。

あわせてサードパーティ製アクションなので commit SHA で固定する。zizmor を
master と比較すると @v4 のままでは unpinned-uses が 17 -> 20 に増えていた。
SHA 固定で 17 に戻り、この PR による新規の指摘は無くなる (npm install -g
npm@latest を削除したぶん adhoc-packages が 1 -> 0 に減る)。

既存の actions/* はタグ参照のままで、この PR では触っていない。

Refs #520
@smellman
smellman marked this pull request as ready for review October 5, 2026 08:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

パッケージマネージャを npm から pnpm へ移行する

1 participant