Skip to content

Migrate to bzlmod and update Bazel, rules_go and gazelle - #63

Open
kogai wants to merge 3 commits into
claude/drop-rules-nodejsfrom
claude/bzlmod-migration
Open

kogai wants to merge 3 commits into
claude/drop-rules-nodejsfrom
claude/bzlmod-migration

Conversation

@kogai

@kogai kogai commented Sep 13, 2026

Copy link
Copy Markdown
Owner

Bazel 側の依存は 2020 年から止まっていました。base は #61rules_nodejs を外した PR)。

依存 変更前 変更後
Bazel 3.7.0 9.2.0
rules_go 0.24.7 0.63.0
bazel-gazelle 0.22.2 0.54.0
rules_shell 0.8.0

なぜ bzlmod への移行になるのか

バージョンだけ上げる選択肢が実質ありません。Bazel 9 は WORKSPACE を廃止しており、rules_go 0.63.0 も Bazel 8/9 でテストされています。WORKSPACE を保つには上げ幅をかなり小さく取るしかなく、それは同じ移行を後日やり直すことを意味します。

BUILD ファイルの変更は 1 行だけ

bazel_deprepo_name を指定して、既存のラベルをそのまま通します。

bazel_dep(name = "rules_go", version = "0.63.0", repo_name = "io_bazel_rules_go")
bazel_dep(name = "gazelle", version = "0.54.0", repo_name = "bazel_gazelle")

当初「BUILD ファイルは 1 行も変えていない」と書きましたが、CI がそれを否定しました

ERROR: e2e/go/BUILD.bazel:35:1: name 'sh_test' is not defined (did you mean 'cc_test'?)

Bazel 9 はネイティブの shell ルールを rules_shell に移しています。bazel_dep を足し、load("@rules_shell//shell:sh_test.bzl", "sh_test") を追加しました。ADR-0006 も訂正済みです。Bazel を上げる際に「無くなったネイティブルールを提供する rules_* を足す」作業が今後も発生しうる、という点も記録しました。

スキーマ取得への影響はありません

EDItEUR の zip は use_repo_rule で従来どおり http_archive として宣言。URL も sha256 も不変なので、ADR-0003 の取得問題は良くも悪くもなりません。

その他

判断は ADR-0006 に記録しています。

確認

  • 全 BUILD ファイルの load() を確認し、repo_name で維持される範囲を特定
  • rules_go 0.63.0 / gazelle 0.54.0 / rules_shell 0.8.0 / Bazel 9.2.0 が実在することを各リリースページで確認。sh_test の load パスは rules_shell v0.8.0 の shell/BUILD を読んで確定
  • make -n test がマージ後も stack test --trace --fast のみを出すことを確認
  • Bazel の実行は未検証。この PR の e2e ジョブが唯一の検証手段で、実際 sh_test の件はそれで判明しました

🤖 Generated with Claude Code

https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z

kogai and others added 2 commits September 13, 2026 07:32
The Bazel side had not moved since 2020: Bazel 3.7.0, rules_go 0.24.7,
gazelle 0.22.2. Updating them runs straight into WORKSPACE itself —
Bazel 9 removed it, and rules_go 0.63.0 is tested against Bazel 8 and 9 —
so there is no version-only bump available except a small one that just
schedules this same migration for later.

Replace WORKSPACE with MODULE.bazel: Bazel 9.2.0, rules_go 0.63.0,
gazelle 0.54.0.

Every bazel_dep carries repo_name, so @io_bazel_rules_go and
@bazel_gazelle keep resolving and not one BUILD file changes. That is
deliberate: it confines everything that can break to the dependency
declarations, which matters because Bazel cannot be run here at all
(releases.bazel.build is blocked by egress policy) and CI is the only
thing that can confirm this.

The EDItEUR archives are declared with use_repo_rule, same URLs and same
sha256, so the download problem in ADR-0003 is neither helped nor made
worse.

Also drop the Makefile's WORKSPACE target: it ran `gazelle update-repos`,
which bzlmod replaces with the go_deps extension — and go.sum is empty,
so there are no external Go dependencies to declare either way. go.mod's
directive moves from 1.14 to 1.21.

Recorded as ADR-0006.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
First CI run on this branch:

    ERROR: e2e/go/BUILD.bazel:35:1: name 'sh_test' is not defined
           (did you mean 'cc_test'?)

Bazel 9 finished moving the native shell rules out of the global
namespace and into rules_shell. Add the bazel_dep and load sh_test from
@rules_shell//shell:sh_test.bzl.

This falsifies the claim ADR-0006 and the pull request both made, that no
BUILD file changes — one load line does. Corrected there, along with a
note that further Bazel bumps can be expected to need the same treatment
as more native rules are Starlarkified.

The Makefile conflict from merging #61 is resolved by taking both
deletions: that branch removed the dead `json` target and this one
removed the `WORKSPACE` target, and neither should come back.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z

kogai commented Sep 13, 2026

Copy link
Copy Markdown
Owner Author

判定

マージ可。ブロッカーは無い。 sh_test の修正は完全で、その後の CI (run 34745684253 / job 103693094130、head d3f0365) の e2e は success//e2e/go:snapshot_test PASSED まで到達している。独立に検証した範囲でも、Bazel 9.2.0 の AutoloadSymbols.java が持つ「グローバルから外された記号」の全表とリポジトリ内 6 つの BUILD/*.bazel の使用ルールを突き合わせた結果、影響を受けるのは sh_test 1 箇所だけで、filegroup / genrule / exports_files / glob は Bazel 9 でもネイティブのまま。repo_nameuse_repo_rulego_sdk 拡張の使い方もいずれも現行の正しい書き方で、rules_go 0.63.0 / gazelle 0.54.0 / rules_shell 0.8.0 / Bazel 9.2.0 / Go 1.24.7 はすべて実在する。以下は落ちる話ではなく、再現性と一貫性の指摘である。


指摘

推奨 1 — MODULE.bazel.lock はコミットする (.gitignore から外す)

ファイル: .gitignore:8MODULE.bazel:26

問題: lock を無視しているため、CI は毎回 BCR を生で解決する。さらに go_sdk.download(version = "1.24.7")sha256 を持たないので、rules_go は毎回 Go のバージョン索引 (fetch_sdks_by_version) をネットワークから取りに行く。実際のログでも Computing main repo mapping に約 10 秒かかっている。

なぜ問題か: ビルドグラフの根が、実行時の外部レジストリと go.dev の応答に依存したままになる。ADR-0003 で「外部からのダウンロードに依存する構成は壊れる」と学んだばかりのリポジトリとしては一貫しない。lock があれば Go SDK を含む全依存の sha256 が固定され、供給側が変わったときに差分として見える。Bazel 7 時代にあった「lock の差分が環境依存で暴れる」問題は 8 以降ほぼ解消している。

修正: .gitignoreMODULE.bazel.lock 行を削除し、生成された lock をコミットする。あわせて .bazelrccommon --lockfile_mode=error を足すと、MODULE.bazel と lock の乖離が CI で落ちるようになる。ADR-0006 の「コミットするかどうかは、CI が通ってから決める」は、CI が通った今が決めどき。

推奨 2 — Go SDK 1.24.7 と go.modgo 1.21 が食い違っている

ファイル: MODULE.bazel:26go.mod:3

問題: SDK は 1.24.7、go.mod は 1.21。しかも現状この go ディレクティブを読むものは 1 つも無い (rules_go は from_file ではなく明示 version を使っている)。つまり 1.14 → 1.21 の変更は効果を持たず、SDK と 3 マイナーずれた数字を新たに置いただけになっている。ADR-0006 にも 1.21 を選んだ理由が書かれていない。

なぜ問題か: ローカルで go build や gopls を使う人が、Bazel とは別の言語バージョンで動く。数字が 2 箇所にあって同期する仕組みが無い。

修正: どちらかに寄せる。

  • (a) go_sdk.from_file(go_mod = "//:go.mod") にして go.mod を単一の情報源にする (この場合 go.mod を 1.24 以降へ)。管理点が 1 つになるのでこちらを勧める。
  • (b) go.mod を SDK に合わせて go 1.24 にする。

推奨 3 — Go 1.24.7 は 1 年前のパッチ

ファイル: MODULE.bazel:26

golang/go のタグを引くと本日時点で go1.24.9 / go1.25.x / go1.26.x が出ている。1.24.7 は 2025-09 のリリース。「2020 年から止まっていた依存を現行に上げる」PR で SDK だけ 1 年前のパッチに固定するのは目的と噛み合わない。推奨 2 の (a) を採れば go.mod 側で一括管理できる。

任意 1 — ADR-0003 への参照が、このツリーに存在しないファイルを指している

MODULE.bazel:31docs/adr/0006-migrate-to-bzlmod.md の 3 箇所 (51, 77, 85 行) が docs/adr/0003-editeur-schema-acquisition.md / ADR-0003 を参照するが、このブランチにも base の #61 にも 0003 は無い (別ブランチ claude/adr-schema-acquisition にある)。docs/adr/README.md の一覧にも 0003 の行が無い。マージ順によってはリンク切れが残る。

あわせて番号の状況: 0005 は claude/fast-xml-parser-v5 / claude/fix-package-metadata / claude/ts-reader-no-value-coercion の 3 ブランチが同時に主張している。0006 は本 PR 単独なので採番の衝突は無いが、docs/adr/README.md の表はどのブランチ同士でも必ず衝突するので、マージ順は意識したほうがよい。

任意 2 — @bazel/bazelisk が 1.7.3 (2021-02) のまま

ファイル: package.json

Bazel 9.2.0 の取得自体は動いた (CI ログで確認済み) ので急ぎではない。ただ Bazel を 3.7 → 9.2 に上げる PR で、その Bazel を取ってくる launcher だけ 2021 年のまま残るのは据わりが悪い。node 側を触る別 PR で一緒に上げるのが自然。

任意 3 — ADR-0006 の「結果」節に lock の結論を書く

「この移行はローカルで検証できていない…唯一の検証手段は CI の e2e ジョブ」は書いた時点では正しく、ADR は当時の判断を残すものなので書き換える必要は無い。ただ MODULE.bazel.lock の「コミットするかどうかは、CI が通ってから決める」だけは、宙ぶらりんの決定を後から読む人に引き継いでしまうので、結論を追記しておきたい。それ以外の ADR-0006 の記述 (Bazel 9 が WORKSPACE を廃止した / rules_go 0.63.0 が Bazel 8・9 でテストされている / go.sum が空で外部 Go 依存が無い / sh_test の load 1 行だけ BUILD が変わった) は、後述のとおりすべて事実と一致していた。


何をどう検証したか

1. CI 実測 — 失敗した run 34745475760 (9c52425) と成功した run 34745684253 (d3f0365) のログを読み比べた。後者では Bazel 9.2.0 が releases.bazel.build から取得され、rules_go++go_sdk+main___download_0_linux_amd64 で Go SDK が展開され、GoStdlib → GoCompilePkg generated/go/v2/go.a//e2e/go:snapshot_test PASSED108 packages loaded なのでルート BUILD.bazel (= @bazel_gazelle//:def.bzl の load) も評価されている。両者の差分は sh_test の load 1 行のみ。

2. sh_test 修正の完全性 (最重要) — Bazel 9.2.0 タグの src/main/java/com/google/devtools/build/lib/packages/AutoloadSymbols.java を読み、グローバル名前空間から外された記号の全表を抽出した: android_*, cc_*, java_*, objc_*, proto_*, py_*, sh_binary / sh_library / sh_test, xcode_*, fdo_profile, memprof_profile, aar_import。同ファイル 842 行が sh_test@rules_shell//shell:sh_test.bzl を指しており、PR の load パスと完全に一致する。次にリポジトリ内の BUILD.bazel 4 つと org_editeur_v{2,3}.bazel 2 つを全走査して使用ルールを列挙 → exports_files / filegroup / genrule / glob / gazelle / go_binary / go_library / sh_test。表に載るのは sh_test のみ、かつ e2e/go/BUILD.bazel の 1 箇所だけ。修正は完全で、filegroupgenrule は Bazel 9 でもネイティブのまま (表に無い)。

3. バージョンの実在 — BCR の modules/{rules_go,gazelle,rules_shell}/metadata.json で 0.63.0 / 0.54.0 / 0.8.0 がいずれも最新エントリとして存在し、yanked_versions に含まれないことを確認。Bazel は raw.githubusercontent 経由でタグを解決し、9.0.0 / 9.1.0 / 9.2.0 が存在し 9.3.0 は存在しないことを確認 (= ADR-0006 の「実在を確認できた最新版が 9.2.0」は正しい)。Go は golang/gogo1.24.7 タグの存在を確認。

4. use_repo_rulehttp.bzl のラベル — Bazel 9.2.0 タグの tools/build_defs/repo/http.bzl が存在し、その docstring 自体が「MODULE.bazel から use_repo_rule で直接呼べる」と例示している。ラベルも書き方も現行のまま。

5. repo_name の機構 — rules_go 0.63.0 の BCR MODULE.bazelmodule(repo_name = "io_bazel_rules_go")、gazelle 0.54.0 は module(repo_name = "bazel_gazelle") を持つ。ただしこれは各モジュールが自分自身を指す名前であって、依存側から見える apparent name は既定ではモジュール名 (rules_go / gazelle) になる。したがって bazel_dep(..., repo_name = ...) を書くのは正しく、かつ必要。4 つの BUILD の load が CI で全部通ったことで実証済み。

6. go_sdk 拡張@io_bazel_rules_go//go:extensions.bzlgo/private/extensions.bzlgo_sdk を再エクスポートしており、ラベルも拡張名も正しい。_download_tagversion 属性を持つ (go/private/extensions.bzl:62-65)。実装末尾 (同 412 行付近) で全モジュールのタグをまとめて go_multiple_toolchains(name = "go_toolchains", ...) を生成し、rules_go 自身の MODULE.bazelregister_toolchains("@go_toolchains//:all") している。ルートモジュール側に use_reporegister_toolchains も不要で、PR の書き方で正しい。CI でツールチェーン解決が成功したことが裏付け。

7. gazelle × rules_go の組み合わせ — gazelle 0.54.0 は rules_go 0.59.0 を、rules_go 0.63.0 は gazelle 0.51.3 を宣言しており、MVS でそれぞれ 0.63.0 / 0.54.0 に引き上げられるだけ。どちらも前方向。rules_go 0.63.0 の .bazelversion9.2.0.bazelci/presubmit.yml8.*9.* を回している (ADR-0006 の記述は正確)。gazelle の def.bzl@bazel_gazelle_go_repository_config//:go_env.bzl@bazel_gazelle_is_bazel_module//:defs.bzl を load するが、どちらも gazelle 自身の MODULE.bazeluse_repo 済みなので、ルート側で go_deps 拡張を使わなくても解決する# gazelle:prefix は gazelle が実行時に BUILD のコメントを読むだけなので bzlmod で意味は変わらない。

8. strip_prefix — 不要で、無いのが正しい。ルート BUILD.bazel の filegroup が @org_editeur_v2//:ONIX_for_Books_Release2-1_rev03_schema+codes_Issue_36/... とアーカイブ内トップディレクトリ込みで参照しているため、旧 WORKSPACE と同じく strip_prefix 無しが整合する。sha256 と URL も旧 WORKSPACE と一字一句同じであることを diff で確認した。

9. module(name = "onix_codegen") — 依存側のモジュール名 (rules_go / gazelle / rules_shell) とも、repo_name で持ち込む apparent name (io_bazel_rules_go / bazel_gazelle) とも衝突しない。

10. Makefile と go.sum — 削除された WORKSPACE: go.mod 以外に gazelle を呼ぶ箇所は無い。schema/%$(BZL) build onix_$(@F)BZL_BIN = $(shell $(BZL) info bazel-bin) は bzlmod でもそのまま通る。go.sum が空であることを確認したので、「外部 Go 依存が無く go_deps の宣言自体が不要」という ADR の主張は正しい。

検証できなかったこと

  • EDItEUR の 2 つの http_archive が実際に取得・展開できるか。 これらは //e2e/go:snapshot_test の依存に入らないため CI でも解決されておらず (そもそも ADR-0003 のとおり editeur.org からの取得が未解決)、build_file = "//:org_editeur_v2.bazel" が bzlmod 下で意図どおり効くかは未実証。make schema / bazel build //:onix_v2 を実行できる環境で一度確認しておきたい。
  • bazel run //:gazelle の実行。 ルート BUILD.bazel の load とルール宣言までは CI で評価されているが、gazelle バイナリの実行は CI に無い。update-repos が無くなった後の使い勝手は一度動かして確かめたほうがよい。
  • このレビュー環境で Bazel を動かしての確認。 releases.bazel.build が egress ポリシーで到達不可のため、上記はすべて (1) CI ログ、(2) Bazel 9.2.0 / rules_go v0.63.0 / gazelle v0.54.0 / rules_shell v0.8.0 の各タグのソース、(3) BCR の metadata.json / MODULE.bazel / source.json、の読解による。

Generated by Claude Code

Review points, now that CI has confirmed the migration works.

The Go SDK was 1.24.7, roughly a year old, in a change whose whole point
is catching up; 1.27.1 is current. go.mod's directive stays at 1.21 on
purpose and the ADR now says why: it is the floor required of anyone
using the generated Go client, while the SDK is what this repository
builds with. Raising the floor to match the toolchain would narrow who
can consume the output for no benefit.

MODULE.bazel.lock should be committed rather than ignored — go_sdk.download
carries no sha256, so without the lock every build re-fetches the Go
version index and re-resolves BCR over the network. It cannot be
generated here (bazel does not run in this environment), so the
.gitignore entry is removed and the ADR asks whoever next runs bazel
locally to commit it. `common --lockfile_mode=error` is deliberately not
added yet: with no lock file present it would fail the build.

Also drop the reference to docs/adr/0003 from MODULE.bazel — that file
lives on another branch and does not exist here — and state the reason
for the failing downloads inline instead.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z

kogai commented Sep 13, 2026

Copy link
Copy Markdown
Owner Author

レビューありがとうございます。推奨 3 件と任意 1 件を反映しました (10fae47)。

AutoloadSymbols.java から de-globalize 対象シンボルの表を抽出し、sh_test@rules_shell//shell:sh_test.bzl の対応を確認したうえで、このリポジトリの全 BUILD ファイルで影響を受けるのが sh_test だけfilegroup / genrule / exports_files / glob はネイティブのまま)と確定していただけたのが、この PR で一番効きました。「次の CI で落ちる箇所を予測する」という依頼に対して、まさにそれをやっていただいた形です。

推奨 1: MODULE.bazel.lock はコミットすべき

同意です。go_sdk.download が sha256 を持たない以上、ロックが無いと毎回ネットワークに出る、という指摘はそのとおりでした。

ただしこのファイルは Bazel を実行しないと生成できず、この環境では実行できません。そこで .gitignore から外し、ADR-0006 に「次に手元で Bazel を動かした人がコミットしてほしい」と明記しました。

common --lockfile_mode=error今は入れていません。ロックファイルが無い状態でこのフラグを足すとビルドが落ちるためです。ファイルが入った時点で追加すべき、という形で ADR に書いています。

推奨 2・3: Go SDK のバージョン

1.24.7 → 1.27.1proxy.golang.org の toolchain 一覧で現行の安定版を確認)。「catch up が目的の PR で 1 年前のパッチ」というのはもっともです。

go.modgo 1.21 はそのままにしました。from_file に寄せる案もありましたが、この 2 つは役割が違うと考えています。go ディレクティブは生成された Go クライアントを使う側に要求する最低バージョン、SDK はこのリポジトリがビルドに使う処理系です。前者を SDK に合わせて上げると、生成物の利用者を絞ることになります。ADR-0006 にその旨を明記しました。「1.14 のままで inert だった」という指摘自体はそのとおりなので、1.21 という意味のある値にはしています。

任意 4: ADR-0003 への参照

MODULE.bazel から削除し、失敗の理由(editeur.org が CAPTCHA チャレンジを返す)をインラインで書くようにしました。別ブランチのファイルを指す参照は、確かに壊れています。

なお ADR 番号の衝突(0005 が複数ブランチで主張されている件、docs/adr/README.md が毎回衝突する件)はご指摘のとおりです。実際 0005 は #59 で、0007 は #64 で使っており、このブランチには無い番号があります。マージ順が決まった時点で索引を整理します。

任意 5: @bazel/bazelisk 1.7.3

これは #57 で 1.28.1 に上げています(この PR の base チェーンには入っていないため、ここでは 1.7.3 のままに見えます)。


Generated 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