Skip to content

chore(deps): changesets ツールチェインを action v2 + CLI v3 へ移行する - #156

Merged
shinyaoguri merged 2 commits into
mainfrom
chore/changesets-v3
Sep 4, 2026
Merged

shinyaoguri merged 2 commits into
mainfrom
chore/changesets-v3

Conversation

@shinyaoguri

Copy link
Copy Markdown
Owner

目的

dependabot が出していた 2 件は片方だけマージするとリリースが壊れる組み合わせだったので、1 PR にまとめて移行する。

理由:

  1. 相互依存。action v2 はプロジェクトが Changesets CLI v3 であることを検証し、v2 なら changesets/action@v1 を使えと言って落ちる(action v2.0.0 / Validate that projects use Changesets CLI v3 and direct Changesets CLI v2 users to changesets/action@v1 changesets/action#699)。逆に CLI v3 だけ上げても action v1 は v2 系パッケージ前提。
  2. 入力名が全面改名 + GITHUB_TOKEN env 廃止Rename root action inputs and outputs changesets/action#681・#674)。versionversion-scriptpublishpublish-scriptcommitcommit-messagetitlepr-title。GitHub Actions は未知入力を警告のみで無視するので、SHA だけの bump はリリースを黙って無効化する。
  3. CI では検知できないci.ymlrelease.yml を実行しないため、chore(deps): bump changesets/action from 1.9.0 to 2.1.1 in the actions group across 1 directory #148 単独でも check は green。dependabot PR が構造的に落ちる 3 パターンの再発防止 #136 で整理した「dependabot はマニフェストしか書き換えず、手で追随すべき箇所は黙ってドリフトする」パターンそのもの。

変更点

  • .github/workflows/release.yml: pin を v2.1.1 の SHA へ、入力を v2 名へ移行し、github-token を明示(v2 は env を見ない)。commit-message / pr-title は v2 の既定値 Version Packages ではなく Conventional Commits を保つため明示継続(squash merge のコミット要約になる)。npm 認証は従来どおり OIDC trusted publishing でトークンは持たない。
  • package.json: @changesets/cli^3.0.0engines.node>=22.11(CLI v3 の engines は ^22.11 || ^24 || >=26)。
  • .changeset/config.json: $schema@changesets/config@4.0.0 へ(CLI v3 が引くのは config v4)。削除された prettier は未使用、privatePackages の既定変更で影響を受ける private パッケージ(site/)に changeset は無いので他の移行は不要。
  • test/dependency-consistency.test.ts: 再発防止のガードを 2 本追加。
    • action の pin(# vX.Y.Z コメント)の major と @changesets/cli の major が対応表(1↔2, 2↔3)どおりであること。表に無い major が pin されたら落として手で判断させる。
    • pin した major の入力名だけが使われていること(v1 名の残留と GITHUB_TOKEN: env 依存を落とす)。
    • .changeset/config.json$schema の major が package-lock.json の解決済み @changesets/config と一致すること。major のみの比較にしたのは、こちらが transitive で minor が npm install のたびに動きうるため(chore(deps): bump the minor-and-patch group across 1 directory with 2 updates #145 の「無関係な PR が赤くなる」の回避)。
  • ADR 0004: action と CLI の major を同時にしか動かせない制約と、その整合をテストで担保していることを追記。

changeset は無し(packages/* を触らないので公開物に変化なし)。

確認方法

  • npm run build / npm test(36 files・367 tests green)/ npm run typecheck(0 errors)
  • 新ガードが赤くなるのを見てから仕上げた: 入力名を v1 に戻す・CLI を ^2 に戻す・$schema3.0.0 に戻す・pin のバージョンコメントを外す、の 4 ケースで期待どおり該当テストだけが落ちる
  • CLI v3 の疎通: 捨て changeset で npx changeset status@cosense-site-kit/core -> 0.4.4 を提示)→ npx changeset version(bump + CHANGELOG + changeset 消費)まで確認し、変更は戻した。依存パッケージまで連鎖しない挙動は v2 のときと同じ(cf. b80edbc
  • pin した SHA 8488615a… が v2.1.1 タグの実体と一致することと、入力名がその SHA の action.yml と一致することを確認
  • マージ後: main の Release 実行ログで action v2 が CLI v3 検証を通り、未知入力の警告が出ていないことを確認する(changeset ゼロなので publish モードで no-op が正しい)。壊れていても release.yml の 1 ステップの revert で v1 系に戻せる

補足

npm run lint はこの worktree(.claude/worktrees/* 配下)からは 0 files で落ちる。biome.json!**/.claude が biome へ渡す .(= 絶対パス)にマッチするためで、この PR とは無関係な既存の papercut(別途 Issue にする)。CI は .claude を含まないパスで走るので影響なし。変更ファイルは明示パスで biome を通して green を確認済み。


🤖 Assisted by Claude Code

dependabot の #148 (changesets/action v1.9.0 → v2.1.1) と #150
(@changesets/cli 2.31.1 → 3.0.0) は片方だけでは成立しない。action v2 は
プロジェクトが CLI v3 であることを検証して落ち (v2 なら action v1 を使えと言う)、
CLI v3 だけ上げても action v1 は v2 系パッケージ前提のままになる。

さらに action v2 は入力名を全面改名し (version → version-script、
publish → publish-script、commit → commit-message、title → pr-title)、
GITHUB_TOKEN 環境変数のサポートを削除した (github-token 入力が唯一の経路)。
GitHub Actions は未知入力を警告のみで無視するので、SHA だけの bump は
リリースを黙って無効化する。

- release.yml: pin を v2.1.1 の SHA にし、入力を v2 名へ移行して
  github-token を明示。commit-message / pr-title は v2 の既定値
  ("Version Packages") ではなく Conventional Commits を保つため明示継続
- package.json: @changesets/cli を ^3.0.0、engines.node を >=22.11
  (CLI v3 の engines は ^22.11 || ^24 || >=26)
- .changeset/config.json: $schema を @changesets/config@4.0.0 へ

pin した SHA が v2.1.1 タグの実体と一致することと、入力名がその SHA の
action.yml と一致することは確認済み。

Assisted-by: Claude <noreply@anthropic.com>
ci.yml は release.yml を実行しないので、リリース経路だけが壊れる変更は
CI が緑のまま通る。#136 で整理した「dependabot はマニフェストしか
書き換えず、手で追随すべき箇所は黙ってドリフトする」パターンなので、
既存の dependency-consistency ガードに 2 本足す。

- changesets/action の pin (# vX.Y.Z コメント) の major と
  @changesets/cli の major が対応表 (1↔2, 2↔3) どおりであること。
  表に無い major が pin されたらテストを落とす
- pin した major の入力名だけが使われていること (v1 名の残留と
  GITHUB_TOKEN env 依存を落とす)
- .changeset/config.json の $schema の major が package-lock.json の
  解決済み @changesets/config と一致すること。biome ガードが major.minor
  なのに対し major だけにしたのは、こちらが transitive で minor が
  npm install のたびに動きうるため (#145 の「無関係な PR が赤くなる」の回避)

いずれも該当箇所を壊すと赤くなることを確認した (入力名を v1 に戻す /
CLI を ^2 に戻す / $schema を 3.0.0 に戻す / pin のコメントを外す)。
ADR 0004 にも action と CLI の major を同時に動かす制約を追記。

Assisted-by: Claude <noreply@anthropic.com>
@shinyaoguri

Copy link
Copy Markdown
Owner Author

着手時のプラン

changesets ツールチェインを v3 系(action v2 + CLI v3)へ移行する

Context

open PR の棚卸しで、dependabot の 2 件が単独でマージすると必ずリリースが壊れる組み合わせだと分かった。

  • #148 changesets/action v1.9.0 → v2.1.1
  • #150 @changesets/cli 2.31.1 → 3.0.0

理由:

  1. 相互依存。action v2 は「プロジェクトが Changesets CLI v3 であること」を検証し、v2 なら
    changesets/action@v1 を使えと言って落ちる(action v2.0.0 / Validate that projects use Changesets CLI v3 and direct Changesets CLI v2 users to changesets/action@v1 changesets/action#699)。逆に CLI v3 だけ上げても
    action v1 は v2 系パッケージ前提。どちらか片方だけは成立しない。
  2. 入力名が全改名 + GITHUB_TOKEN env 廃止(action v2.0.0 / Rename root action inputs and outputs changesets/action#681・#674)。
    versionversion-scriptpublishpublish-scriptcommitcommit-message
    titlepr-title。現行 release.yml:50-57 は v1 名のままで、
    GitHub Actions は未知入力を警告だけで無視するため、chore(deps): bump changesets/action from 1.9.0 to 2.1.1 in the actions group across 1 directory #148 を素通しするとリリースが黙って壊れる。
  3. CI では検知できないci.ymlrelease.yml を実行しないので両 PR とも green。
    これは dependabot PR が構造的に落ちる 3 パターンの再発防止 #136 で整理した「dependabot が書き換えるのはマニフェストだけで、手で追随すべき箇所は
    黙ってドリフトする」パターンそのもの(既存ガード: test/dependency-consistency.test.ts)。

したがって 1 PR で action と CLI を同時に上げ、入力名を移行し、同じ罠を次から CI で落とす
pin 済み SHA 8488615a… は v2.1.1 タグの実体と一致することを確認済み(publish 権限を持つジョブのため検証)。
入力名は pin した SHA の action.yml を直接読んで確定済み。

なお #146(version packages)は移行前に現行 v1 系ツールチェインでリリース済みなので、
main は changeset ゼロの状態から移行に入れる。

変更点

1. .github/workflows/release.yml(本体)

Version or publish ステップを v2 の形へ。SHA pin の運用(可動タグを引かない)と理由コメントは維持。

        uses: changesets/action@8488615a623b1b9c987934bb89eae8af6a946ac1 # v2.1.1
        with:
          version-script: npx changeset version
          publish-script: npm run release
          commit-message: "chore: version packages"
          pr-title: "chore: version packages"
          # v2 は GITHUB_TOKEN 環境変数を見ない(入力で渡すのが唯一の経路)。
          github-token: ${{ secrets.GITHUB_TOKEN }}
  • env: ブロックは削除。npm 認証は従来どおり OIDC trusted publishing(id-token: write)で、
    トークンは持たない旨のコメントはこのステップに残す。
  • commit-message / pr-title は v2 の既定値が Version Packages なので、Conventional Commits を
    保つために明示継続(squash merge のコミット要約になる)。
  • 既定の挙動変更で影響がないことを確認済み: リリースコミット/タグは GitHub API push が既定
    push-with-git-cli 不要)、create-github-releases / push-git-tags は既定 true で従来と同じ。
    npm run release に環境変数はそのまま継承されるので CHANGESETS_OUTPUT の受け渡しも成立する。

2. package.json(root)

  • @changesets/cli^3.0.0
  • engines.node>=20>=22.11(CLI v3 の engines は ^22.11 || ^24 || >=26

3. .changeset/config.json

$schema@changesets/config@3.0.0@changesets/config@4.0.0(CLI v3 が引くのは config v4)。
他のキーは移行不要(削除された prettier は未使用、privatePackages の既定変更で影響を受ける
private パッケージ = site/ に changeset は無い)。

4. package-lock.json

npm install で再生成(cli 3.0.0 / config 4.0.0 系へ)。

5. test/dependency-consistency.test.ts(再発防止)

既存ファイルの作法(#136 パターンごとに describe + 理由コメント)に合わせてガードを 2 本追加。

  • changesets/action の pin と @changesets/cli の対応
    • pin が changesets/action@<40 桁 SHA> # vX.Y.Z の形であること(major はこのコメントから読む)
    • action major → 必要な CLI major の対応表(1 → 2, 2 → 3)と root devDependencies の一致。
      表に無い major が pin されたらテストを落とす(v3 が出たとき手で判断させる)
    • pin した major の入力名だけが使われていること。v2 では version-script / publish-script /
      github-token の存在を要求し、version: / publish: / commit: / title: / branch: /
      commit-mode: / setup-git-user: の残留と GITHUB_TOKEN: env 依存を落とす
    • 実装は release.ymlテキストで読み、キー行を行頭アンカーの正規表現で判定する
      (root に yaml の devDependency を増やさないため。対象は自分たちが書く 1 ステップだけなので十分)
  • .changeset/config.json$schema と解決済み @changesets/config
    • package-lock.jsonnode_modules/@changesets/config の version と $schema URL の
      major のみを比較する。biome ガードが major.minor なのに対して major だけにするのは、
      こちらが transitive で minor が npm install のたび動きうるため(chore(deps): bump the minor-and-patch group across 1 directory with 2 updates #145 と同じ「無関係な PR が
      赤くなる」を避ける)。この差はコメントで理由を残す

6. docs/decisions/0004-changesets-with-npm-trusted-publishing.md

「影響」に 1〜2 行追記: action の major と CLI の major は同時にしか動かせない / その整合は
test/dependency-consistency.test.ts が CI で担保する。

7. dependabot PR の後片付け

#148#150 は本 PR が置き換える旨を(署名付きで)コメントして close。

changeset は不要(packages/*/srcpackages/*/package.json も触らないので pre-push hook も鳴らない)。

検証

  1. npm installnpm run buildnpm testnpm run lintnpm run typecheck(CI の check と同じ順)
  2. 新ガードが赤くなるのを見てから仕上げる(3 ケースそれぞれ一時的に壊して確認 → 戻す)
    • release.yml の入力を v1 名に戻す → 入力名ガードが落ちる
    • @changesets/cli^2 に戻す → 対応表ガードが落ちる
    • $schema@changesets/config@3.0.0 に戻す → schema ガードが落ちる
  3. CLI v3 の疎通: 捨て changeset を作って npx changeset statusnpx changeset version
    正しく bump / CHANGELOG を書くのを確認し、git restore で戻す(実バージョンは上げない)。
    手元は Node 25 で CLI v3 の engines を外れるため EBADENGINE 警告が出る想定(動作自体はする。
    CI は Node 24 で適合)
  4. マージ後: main の Release 実行ログで、action v2 が CLI v3 検証を通し、未知入力の警告が
    出ていないことを確認する(changeset ゼロなので publish モードで no-op になるのが正しい)。
    ここで壊れていても、release.yml の 1 ステップを revert するだけで v1 系に戻せる
  5. 経過と根拠は PR 本文+着手時プランのコメントとして PR に残す

このプランは着手時点の判断です。実装の過程で変わった場合は、このコメントに返信する形で差分を残してください。

🤖 Assisted by Claude Code

@shinyaoguri

Copy link
Copy Markdown
Owner Author

マージ後の確認(action v2 の初回実行)

main(22aeaf1)の Release 実行 33845441537 は success。移行が実際に効いていることの確認:

  • Version or publish ステップが publish-script(= npm run release)を実行し、🦋 changeset v3.0.1 が動いて No unpublished projects to publish. で終了。changeset ゼロの状態での no-op として期待どおり
  • 未知入力の警告アノテーションは 0 件(ジョブのアノテーションも空)。v1 名が残っていれば Unexpected input(s) が出るので、入力の移行が成立していることの裏取りになる
  • action v2 の「プロジェクトが CLI v3 か」の検証も通っている(v2 のままなら action v1 を使えと言って落ちる)

残るリスクは version-script 経路(changeset がある push で「chore: version packages」PR を開く側)が実運用でまだ 1 回も走っていない点。ローカルでは CLI v3 の npx changeset status / npx changeset version が正しく bump することを確認済みで、次の changeset を含む push が最初の実運用になります。壊れていた場合も release.yml の 1 ステップの revert で v1 系に戻せます。

なお、この移行の直前に #146 を現行 v1 系ツールチェインでリリース済み(core 0.4.3 / astro 0.2.1 / cli 0.1.12 / theme-default 0.8.1 / theme-utils 0.5.1、タグ作成・npm 反映まで確認)。


🤖 Assisted by Claude Code

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.

1 participant