Skip to content

Replace generated_file_test with a plain sh_test and drop rules_nodejs - #61

Open
kogai wants to merge 6 commits into
mainfrom
claude/drop-rules-nodejs
Open

kogai wants to merge 6 commits into
mainfrom
claude/drop-rules-nodejs

Conversation

@kogai

@kogai kogai commented Sep 13, 2026

Copy link
Copy Markdown
Owner

Bazel 側のライブラリ更新の第一歩です。base は #56。

実態

build_bazel_rules_nodejs 3.1.0 が使われているのは 2 箇所だけでした。

WORKSPACE:18          name = "build_bazel_rules_nodejs",
WORKSPACE:25          load(... "npm_install")
e2e/go/BUILD.bazel:2  load(... "generated_file_test")

このうち npm_install が定義する @npm は、どの BUILD ターゲットからも参照されていません(#57 のレビューでも指摘された点です)。//e2e/go:snapshot_test が使うのは Go のバイナリと JSON 2 つだけです。つまり実質的な用途は generated_file_test ひとつでした。

なぜ「上げる」ではなく「外す」のか

やっていることは「2 つのファイルが同一か」の比較です。そのために外部リポジトリを丸ごと取得するのは釣り合っていません。

加えて、この依存はライブラリ更新の妨げになっています。3.1.0 は 2021 年のリリースで新しい Bazel との組み合わせが保証されず、一方 generated_file_test は rules_nodejs 5.x/6.x には存在しません。上げるにせよどのみち比較の仕組みを書き換える必要があり、書き換えたうえで依存だけが残ります。

変更内容

e2e/go/snapshot_test.sh を追加し、sh_test から呼びます。diff -u で比較し、差分があれば差分そのものを表示して失敗します(generated_file_test は不一致の事実しか出しませんでした)。スナップショットの更新手順はスクリプト冒頭のコメントにあります。

bazel_skylib の diff_test に置き換える案も検討しましたが、依存を別の依存に入れ替えるだけで減らず、しかも skylib のどのバージョンが Bazel 3.7.0 と組み合わせられるかをこの環境では検証できません(releases.bazel.build に到達不可)。検証できない選択肢を抱えるより、依存を減らす方を採りました。ADR-0004 に記録しています。

npx bazelisk は npm の devDependency 由来で、rules_nodejs とは無関係なので影響ありません。

確認

  • rules_nodejs への参照が 0 件になったことを確認(grep -c 'nodejs\|npm' WORKSPACE → 0)
  • Bazel の実行は未検証。この環境では bazel を動かせないため、sh_test の $(location) 展開や runfiles の解決が期待どおりかは、この PR の e2e ジョブが唯一の検証手段です。赤が出たら追って直します

🤖 Generated with Claude Code

https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z


Generated by Claude Code

kogai and others added 5 commits September 13, 2026 06:49
Both CI jobs currently fail two seconds after starting, before any build
step runs:

    ##[error]This request has been automatically failed because it uses a
    deprecated version of `actions/cache: v2`.

GitHub has closed down actions/cache v1 and v2 and now auto-fails runs
that reference them at action-download time, so the workflow cannot get
as far as `make test` or the bazel e2e target.

Bump actions/cache to v4 to unblock that, and bump the remaining actions
still on the Node 12 runtime at the same time:

- actions/checkout v2 -> v4
- actions/setup-node v2.1.4 -> v4
- haskell/actions/setup v1 -> haskell-actions/setup v2 (repository moved)

Tool versions are left as they are (GHC 8.8.3, stack 2.5.1, Node 12.x) so
this change is limited to action versions. haskell-actions/setup v2 still
exposes the stack-path output the cache step depends on.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
With the deprecated actions bumped, the Haskell job now reaches `make
test` and fails there instead: `make test` depends on the `schema`
target, which fetches the EDItEUR archives, and editeur.org now answers
bazel's request with `202 Accepted` instead of the zip.

The test suite does not need those archives. Everything under test/ reads
fixtures/test_*.xsd; the only reader of ./schema is schemaRoot in
src/Lib.hs, which is the code-generation path. The dependency was an
over-specification that tied the whole feedback loop for the parser to
the availability of an external service.

Drop it from `test` and keep it on `build`, where generating code really
does need the schema. This does not fix the 202 itself: generation and
tracking new schema releases still need the download.

Also introduce docs/adr/ to record decisions like this one, with a
template, an index, and the two decisions made here.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
The previous commit dropped the `schema` prerequisite from `make test` on
the claim that nothing under test/ reads schema/. That claim was wrong,
and review caught it: fixtures/test_mixed_html.xsd included
../schema/v2/ONIX_XHTML_Subset.xsd directly. Xsd.getSchema follows
includes recursively and resolves that relative path with readFile, which
throws when the file is absent, and schema/ is gitignored — so on a clean
checkout the suite would have failed instead of running.

Commit 9352123 confirms the dependency was deliberate: it added
`test: schema` in the same change that deleted the vendored
2_1_rev03_schema/ tree and repointed this fixture at ../schema/v2/.

Rather than restore the prerequisite, move what the fixture needs into
the repository. test_mixed_html_xhtml_subset.xsd declares the 40 element
names the fixture refers to, each as a mixed complex type. That is the
property the assertions actually rest on: TestModel expects
Model.collectElements to come back empty, and that filter keeps only
elements with complexMixed = False, so the test means "XHTML elements do
not leak into models". Deleting the include instead would have made the
assertion vacuous.

The stand-in is written here rather than copied from the EDItEUR
distribution, so it raises no redistribution question.

ADR-0002 is rewritten around what is actually true, including why the
dependency was real and why a stand-in is enough.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
BZL_BIN used `:=`, so `$(shell npx bazel info bazel-bin)` ran while make
parsed the file — on every target, `make test` included. The Haskell job
runs `make test` without ever installing node_modules, so that expansion
just fails there. Measured in this environment: `make -n test` took
18.1s and printed a bazel download error before doing anything, and
0.011s with the assignment deferred to `=`. Nothing outside the schema
recipes reads BZL_BIN, so deferring it costs nothing.

Also drop the `ls -lah` step that printed the stack tool path; it was
debugging output for the cache setup, not a check anything depends on.

Both spotted in review of this PR.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z
build_bazel_rules_nodejs 3.1.0 was pulled in for two things. One of them,
the @npm repository from npm_install, is referenced by no BUILD target at
all — //e2e/go:snapshot_test only consumes a Go binary and two JSON
files. The other, generated_file_test, compares two files.

That is not worth an external repository, and it actively blocks updating
Bazel: 3.1.0 predates current Bazel releases, and generated_file_test
does not exist in rules_nodejs 5.x/6.x, so bumping the dependency would
mean rewriting the comparison anyway and keeping the dependency for
nothing.

Compare with diff -u in a sh_test instead. It has no Bazel version
constraints of its own, so it stops being a factor in the version bump,
and it prints what actually differs rather than only that something does.
Snapshot refresh instructions are in the script.

bazel_skylib's diff_test was the obvious alternative, but it swaps one
dependency for another, and which skylib version pairs with Bazel 3.7.0
cannot be checked from here (releases.bazel.build is blocked by egress
policy). Removing the dependency leaves nothing to verify.

npx bazelisk is unaffected — that comes from the npm devDependency, not
from rules_nodejs.

Recorded as ADR-0004.

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

総評

Bazel の配線は正しく、意図どおり動きます。args の中の $(location) は Bazel 3.7.0 では rootpath (runfiles 相対) に展開されるので、$(rootpath) や $(execpath) に直す必要はなく、素の diff で開けます (むしろ $(execpath) にすると bazel-out/…/bin/ 付きの実行ルート相対パスになって壊れます)。ソース側の裏取りに加えて、この HEAD (71d2457) の e2e ジョブが既に通っています — //e2e/go:snapshot_test PASSED in 0.1s (run 34745063205)。なので PR 本文の「Bazel の実行は未検証」はもう古い記述です。一方で ADR-0004 の事実関係に 1 つ誤りがあります: generated_file_test は rules_nodejs 5.x には存在します (6.x には無い)。決定そのものは変わりませんが、ADR は残る記録なので前提は直すべきです。


指摘

必須

1. docs/adr/0004-…md L22-23 / L54-55 と PR 本文: 「generated_file_test は rules_nodejs 5.x/6.x には存在しない」は 5.x について誤り

  • 事実: 5.x 系最終の 5.8.5 に存在します。

    # https://raw.githubusercontent.com/bazelbuild/rules_nodejs/5.8.5/index.bzl
    26:load("//internal/generated_file_test:generated_file_test.bzl", _generated_file_test = "generated_file_test")
    47:generated_file_test = _generated_file_test
    

    実体 internal/generated_file_test/generated_file_test.bzl も 5.8.5 で HTTP 200 で取得でき、3.1.0 とほぼ同じシグネチャ (generated, src, substring_search, src_dbg) のままです。4.7.0 にもあります。6.x については主張どおりで、v6.0.0 / v6.7.6 とも root に index.bzl が無く、internal/generated_file_test/generated_file_test.bzl は 404 です。

  • なぜ問題か: 「上げても比較の仕組みを書き換えることになる」という論拠が 5.x では成立しません。ADR-0004 は「なぜ上げずに外したか」を後から読む人のための記録なので、ここが崩れると決定の根拠ごと疑わしく見えます。

  • 実際の障壁はバージョン組み合わせのほうで、そちらは検証済みで固いです。

    # rules_nodejs 5.8.5 index.bzl
    89:BAZEL_VERSION = "5.0.0"
    96:SUPPORTED_BAZEL_VERSIONS = ["4.2.2", BAZEL_VERSION]
    # 5.8.5 の .bazelversion も 5.0.0
    # 参考: 4.7.0 は SUPPORTED_BAZEL_VERSIONS = ["4.1.0"]、3.1.0 は ["3.6.0"]
    

    このリポジトリの .bazelversion は 3.7.0 なので、5.x に上げるには 先に Bazel 本体を 4.2.2 以上へ上げる必要があり、それは今この PR でやりたいこととは別物です。

  • 修正案: L22-24 を次の趣旨に差し替える。

    5.x は SUPPORTED_BAZEL_VERSIONS = ["4.2.2", "5.0.0"] で、.bazelversion が 3.7.0 のままでは上げられない (generated_file_test 自体は 5.x にはまだあるが、6.x で index.bzl ごと無くなっている)。つまり「rules_nodejs を上げる」は Bazel 本体の更新とセットになり、しかもその先の 6.x では結局この比較の仕組みを書き換えることになる。

    L54-55 の「検討した他の選択肢」も同じ前提に乗っているので合わせて。PR 本文の該当箇所も同様です。

推奨

2. Makefile に既存のスナップショット更新経路があり、しかも壊れている

ADR L65-66 は「更新は手作業になった、手順は snapshot_test.sh の冒頭」としていますが、Makefile には同じ目的の target が既にあります。

json: fixtures/20201200.json
fixtures/20201200.json: run
	go run github.com/kogai/onix-codegen/go/helper
  • run という target はこの Makefile に存在しないので make json は No rule to make target 'run' で落ちます。
  • github.com/kogai/onix-codegen/go/helper というパッケージも存在しません (helper は e2e/go、importpath = github.com/kogai/onix-codegen/e2e/go)。root に go/ ディレクトリはありません。
  • なぜ問題か: この PR で更新手順を新たに 1 箇所に書いたことで、「死んでいる手順」と「生きている手順」が 2 つ並ぶ状態になります。ADR が「手作業になった」と宣言する以上、既存の自動化のなれの果てを残したままにするのは記録として不正確です。
  • 修正案: この PR で Makefile の json / fixtures/20201200.json target を削除する (推奨) か、npx bazelisk build //e2e/go:snapshot && cp $(BZL_BIN)/e2e/go/out.json fixtures/20201200.json に直して、ADR L65-66 からそちらを指す。なおスクリプト冒頭 (L7) は npx bazelisk build、ADR L65 は bazel build と表記が割れているので、どちらかに揃えると親切です。

任意

3. e2e/go/BUILD.bazel L35-46: size の指定がない

CI ログに毎回出ています。

//e2e/go:snapshot_test   PASSED in 0.1s
There were tests whose specified size is too big. ...

sh_test の既定は medium (300s) で、実測 0.1s なので警告になります。base ブランチ (generated_file_test 時代、run 34744637620) でも同じ警告が出ているのでこの PR による退行ではありませんが、どのみちこの target を書き直しているので size = "small" を足すなら今が安い。

4. e2e/go/snapshot_test.sh L19: $0 がサンドボックス内のパスになる

echo "If the change is intended, refresh the snapshot as described in $0." >&2

テスト実行時の $0 は …/execroot/__main__/bazel-out/k8-fastbuild/bin/e2e/go/snapshot_test.sh のような runfiles/サンドボックス内パスで、読み手がリポジトリ内で開くべきパスではありません。e2e/go/snapshot_test.sh とベタ書きするほうが親切です。

5. ADR の「結果」に、旧 :snapshot_test.update は元から機能していなかった旨を足すと正確

旧定義は引数が逆でした。

generated_file_test(
    name = "snapshot_test",
    src = "snapshot",                      # ← ルールの定義では src = ワークスペース側のソース
    generated = "//:fixtures/20201200.json",  # ← generated = Bazel が生成した出力
)

rules_nodejs 3.1.0 の docstring は generated: a Label of the output file generated by another rule / src: Label of the source file in the workspace で、この BUILD は 2 つが入れ替わっています。等値比較としては対称なのでテストの意味は変わっていませんが、同ルールが生成する //e2e/go:snapshot_test.update (templated_args = ["--out", loc % src, …]) は「生成物である snapshot 側に書き戻す」動作になっていたので、実質使えないものでした。つまり ADR L65「更新は手作業になった」で失われたものは、実際にはほぼありません。逆に新しい sh_test は expected = fixture / actual = out.json と向きが正しく、diff -u の -/+ が期待値/実測の意味になっています。ここは ADR に書く価値のある改善点です。

6. docs/adr/README.md: 0002 → 0004 と番号が飛ぶ

0003 は claude/adr-schema-acquisition 側にあるので意図的な採番と理解しています (claude/fast-xml-parser-v5 は 0005)。マージ順によっては index の行が欠けた状態で main に入るので、統合時に一覧の補完が要ります。


確認したこと

args 内の $(location) の展開 (Bazel 3.7.0 のソースを直接確認)

  1. sh_binary/sh_test は RunfilesSupport.withExecutable を使う — src/main/java/com/google/devtools/build/lib/bazel/rules/sh/ShBinary.java:87-88
  2. RunfilesSupport.computeArgs は args を withDataLocations() で展開する — RunfilesSupport.java:432
    ruleContext.getExpander().withDataLocations().tokenized("args")
  3. withDataLocations() = withLocations(execPaths=false, allowData=true) — Expander.java:83-85
  4. execPaths=false のとき $(location) は Artifact.getPathForLocationExpansion() を使い、これは getRootRelativePath() — LocationExpander.java:310-317, Artifact.java:641-643
  5. allowData=true により data 属性の依存が location map に入る — LocationExpander.java:390-394
  6. テストは $TEST_SRCDIR/$TEST_WORKSPACE に cd してから実行される — tools/test/test-setup.sh:136-148

結論: $(location :out.json) → e2e/go/out.json、$(location //:fixtures/20201200.json) → fixtures/20201200.json。いずれも runfiles のワークスペースルート相対で、テストの cwd がそこなので素の diff で開けます。@bazel_tools//tools/bash/runfiles は不要。$(rootpath) に書き換えても等価、$(execpath) は誤り。

:out.json vs :snapshot: data に入っている :out.json は宣言済み prerequisite で、genrule の唯一の出力なので $(location) は一意に解決します。:snapshot (genrule ターゲット) と書いても出力が 1 つなので同じ文字列になります。どちらでも可、現状のままで問題なし。

実行権限: git ls-tree で 100755 blob c425b94 e2e/go/snapshot_test.sh を確認。

//:fixtures/20201200.json の可視性: root BUILD.bazel の exports_files([... "fixtures/20201200.json", "fixtures/20201200.onix"]) に含まれ、exports_files は既定で public。同パッケージの //:fixtures/20201200.onix を e2e/go の filegroup が既に参照して通っているので、実績としても確認済み。

@npm が参照されていないこと: このブランチの全 BUILD.bazel / *.bzl / *.bazel / WORKSPACE を @npm|nodejs|generated_file_test|npm_install で grep して 0 件。リポジトリ全体の git grep でも ADR-0004 の本文にしか現れません。PR 本文の grep -c 'nodejs\|npm' WORKSPACE → 0 も再現しました。

ADR の引用行番号: base (aa33895) で WORKSPACE:18 name = "build_bazel_rules_nodejs"、WORKSPACE:25 load(...)、e2e/go/BUILD.bazel:2 load(... "generated_file_test") — すべて一致。

CI が壊れないこと: .github/workflows/test.yml の e2e ジョブは npm install → npx bazelisk test //e2e/go:snapshot_test。@bazel/bazelisk は package.json の devDependency で、WORKSPACE の npm_install (Bazel の repository rule) とは無関係。実ログでも npm install → added 3 packages → bazelisk が 3.7.0 を取得 → テスト成功、と通っています。ADR L63-64 の「package.json / package-lock.json が Bazel のビルドグラフから完全に外れた」も、WORKSPACE / 全 BUILD ファイルから参照が消えていることを確認済み。

ADR のその他の記述: 「WORKSPACE の外部依存が 1 つ減る」(http_archive 5 → 4)、「3.1.0 は新しい Bazel との組み合わせが保証されない」(3.1.0 の SUPPORTED_BAZEL_VERSIONS = ["3.6.0"] のみ) — いずれも正しい。

確認できなかったこと

  • 手元での Bazel 実行: releases.bazel.build に到達できないため未実施。ただし上記のとおり CI が本ブランチの HEAD で実際に通っているので、この点は実証済みと見なせます。
  • rules_nodejs 6.x に別名/別パスで同等物が残っていないか: v6.7.6 の root に index.bzl が無いこと、internal/generated_file_test/generated_file_test.bzl が 404 であることは確認しましたが、GitHub のコード検索はサインインが必要でリポジトリ全文検索はできていません。「6.x には無い」の主張は否定材料が見つからなかった、というレベルです。
  • 3.1.0 のリリース年: リリースページの表示が「02 Feb」で年が読めませんでした。3.1.0 が Bazel 3.6.0 世代であることとは整合します。

Generated by Claude Code

ADR-0004 said generated_file_test does not exist in rules_nodejs 5.x/6.x.
That is only true of 6.x; 4.7.0 and 5.8.5 still ship it. The actual
blocker on 5.8.5 is SUPPORTED_BAZEL_VERSIONS = ["4.2.2", "5.0.0"], which
does not include the 3.7.0 this repo pins — so upgrading rules_nodejs
alone was never possible, and going all the way to 6.x means rewriting
the comparison regardless. The decision is unchanged; the reason it gave
was wrong.

The ADR declared snapshot updates manual while leaving Makefile's `json`
target in place. That target was broken twice over: it depends on a `run`
target that does not exist, and runs
github.com/kogai/onix-codegen/go/helper, which is not a real package —
the helper lives in e2e/go. Remove it, and record in the ADR that the old
generated_file_test had src and generated the wrong way round, so its
.update path wrote in the wrong direction too.

Also give the sh_test size = "small", which silences the "test size is
too big" warning Bazel prints, and make the failure message name the
script by path rather than $0, which resolves to a sandbox path at test
time.

All from review of this PR.

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

レビューありがとうございます。必須・推奨・任意すべて反映しました (7a6d7de)。

必須: ADR-0004 の事実誤認

ご指摘のとおりです。「generated_file_test は 5.x/6.x に無い」は誤りで、正しくは 6.x に無いでした。4.7.0 と 5.8.5 には存在します。

より重要なのは、ご提示いただいた本当の行き止まりの理由です。5.8.5 の SUPPORTED_BAZEL_VERSIONS が ["4.2.2", "5.0.0"] で、このリポジトリが固定している 3.7.0 を含みません。つまり「rules_nodejs だけ上げる」は最初から成立しませんでした。ADR を次のように書き直しています。

  • 4.7.0 / 5.8.5: generated_file_test はある。ただし対応 Bazel が 4.2.2 / 5.0.0 で、Bazel も同時に上げる必要があり変更が連鎖する
  • 6.x: ルート index.bzl ごと無くなり、generated_file_test は存在しない

結論(外す)は変わりませんが、理由が間違っていたので直しました。ADR は後から読む人が信頼する記録なので、ここが誤っているのは実質的な欠陥だと思います。

推奨: Makefile の死んだ更新経路

確認しました。二重に壊れています。

json: fixtures/20201200.json
fixtures/20201200.json: run                                    ← run ターゲットは存在しない
	go run github.com/kogai/onix-codegen/go/helper             ← 実体は e2e/go

ADR で「更新は手作業」と宣言しながらこれを残すのは矛盾なので、削除しました。

任意

  • size 未指定: size = "small" を追加しました。ログの "test size is too big" が消えます。
  • $0 がサンドボックスのパスになる: 失敗メッセージがスクリプトのパスを直書きするようにしました。
  • 旧 generated_file_test の src/generated が逆で .update が使い物にならなかった: これは面白い発見でした。比較自体は対称なので検証は機能していた、という整理を含めて ADR の「結果」に記録しました。新しいスクリプトは向きが正しくなっています。
  • ADR 索引が 0002 → 0004 に飛んでいる: 0003 が別ブランチ (ADR-0003: EDItEUR スキーマの取得方法 (要判断) #58) にあるためです。マージ時に索引の行が揃うよう調整します。

検証について

$(location) が Bazel 3.7.0 で rootpath に展開されることを、ShBinary.java → RunfilesSupport.java → Expander.java → LocationExpander.java と実際に追って確認していただけたのは非常に助かりました。$(execpath) に直すのは誤りだった、という判断まで含めて、こちらでは辿れていなかった部分です。

なお e2e ジョブは 71d2457 で実際に緑になっています(//e2e/go:snapshot_test PASSED in 0.1s、bazel-bin/e2e/go/snapshot_test が生成され、旧 snapshot_test_loader.js 等が消えていることも確認済み)。


Generated by Claude Code

kogai added a commit that referenced this pull request Sep 13, 2026
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
Base automatically changed from claude/bump-deprecated-github-actions to main September 13, 2026 10:36
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