From dd4ae6c60567d57a005922a284db3837ec004db1 Mon Sep 17 00:00:00 2001 From: kogai Date: Sun, 13 Sep 2026 06:49:30 +0000 Subject: [PATCH 1/6] Bump deprecated GitHub Actions in the test workflow 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 Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z --- .github/workflows/test.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 4a87029..3b21b44 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -5,15 +5,15 @@ jobs: name: Test haskell codes runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 - - uses: haskell/actions/setup@v1 + - uses: actions/checkout@v4 + - uses: haskell-actions/setup@v2 id: haskell-setup with: ghc-version: "8.8.3" enable-stack: true stack-version: "2.5.1" - name: Restore caches - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: | ${{steps.haskell-setup.outputs.stack-path}} @@ -28,13 +28,13 @@ jobs: name: Test e2e runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Setup Node.js environment - uses: actions/setup-node@v2.1.4 + uses: actions/setup-node@v4 with: node-version: 12.x - name: Restore caches - uses: actions/cache@v2 + uses: actions/cache@v4 with: path: | ~/.npm From 8843e5131eb2e2a3ddf6d4501d72862fe851d490 Mon Sep 17 00:00:00 2001 From: kogai Date: Sun, 13 Sep 2026 06:55:58 +0000 Subject: [PATCH 2/6] Decouple `make test` from the schema download 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 Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z --- Makefile | 6 +- docs/adr/0000-template.md | 26 ++++++ .../adr/0001-record-architecture-decisions.md | 52 ++++++++++++ ...ple-unit-tests-from-the-vendored-schema.md | 81 +++++++++++++++++++ docs/adr/README.md | 26 ++++++ 5 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 docs/adr/0000-template.md create mode 100644 docs/adr/0001-record-architecture-decisions.md create mode 100644 docs/adr/0002-decouple-unit-tests-from-the-vendored-schema.md create mode 100644 docs/adr/README.md diff --git a/Makefile b/Makefile index b08d1dd..6a06415 100644 --- a/Makefile +++ b/Makefile @@ -12,8 +12,12 @@ generated/ts/%: build debug: build stack exec --trace -- onix-exe +RTS -xc --RTS --schemaVersion v3 --language go +# The unit tests read only fixtures/*.xsd, so they deliberately do not depend +# on the `schema` target: `make schema` downloads the EDItEUR archives over the +# network, and requiring it here made the test suite unrunnable whenever +# editeur.org was unreachable. See docs/adr/0002-decouple-unit-tests-from-the-vendored-schema.md .PHONY: test -test: schema +test: stack test --trace --fast .stack-work: $(HS_FILES) package.yaml stack.yaml diff --git a/docs/adr/0000-template.md b/docs/adr/0000-template.md new file mode 100644 index 0000000..f32c01b --- /dev/null +++ b/docs/adr/0000-template.md @@ -0,0 +1,26 @@ +# ADR-0000: タイトル + +- **ステータス**: Proposed | Accepted | Superseded by ADR-XXXX +- **日付**: YYYY-MM-DD + +## 背景 + +どういう状況で、何が問題になっているか。観測された事実 (エラーメッセージ、計測値、 +外部サービスの挙動) を具体的に書く。 + +## 決定 + +何を決めたか。 + +## 理由 + +なぜその選択肢を選んだか。 + +## 検討した他の選択肢 + +- **案 A**: 内容と、採らなかった理由 +- **案 B**: 内容と、採らなかった理由 + +## 結果 + +この決定によって何が変わるか。新しく発生する制約や、将来見直すべき条件も書く。 diff --git a/docs/adr/0001-record-architecture-decisions.md b/docs/adr/0001-record-architecture-decisions.md new file mode 100644 index 0000000..043bc9c --- /dev/null +++ b/docs/adr/0001-record-architecture-decisions.md @@ -0,0 +1,52 @@ +# ADR-0001: 設計判断を ADR として記録する + +- **ステータス**: Accepted +- **日付**: 2026-09-13 + +## 背景 + +onix-codegen には、コードを読むだけでは意図が復元できない判断がいくつもある。例えば次のようなもの。 + +- スキーマの版を `v2` / `v3` というディレクトリで分け、既存の出力を置き換えない +- 言語固有の知識をテンプレートに閉じ込め、`src/` を言語非依存に保つ +- 対応していない XSD 構造は暗黙に無視せず `unimplemented` / `unreachable` で落とす + +これらはいずれも「後方互換性を保ちながら ONIX 仕様に追従する」「サポート言語を増やしやすくする」という +このリポジトリの価値 (AGENTS.md) から導かれているが、根拠がコミットログに散っているため、 +後から来た人が「なぜこうなっているのか」を再構成しづらい。結果として、良かれと思った変更が +その判断を静かに壊すことがある。 + +外部依存の扱いも同じ問題を抱えている。EDItEUR の配布物、Bazel、Stackage のスナップショットは +どれも外部の都合で壊れるが、「なぜこのバージョンに固定しているのか」が残っていないと、 +更新のたびに同じ調査をやり直すことになる。 + +## 決定 + +設計判断を `docs/adr/` 配下の ADR として記録する。フォーマットは MADR を簡略化したもので、 +`0000-template.md` を雛形とする。連番は一度振ったら変えず、判断が変わったときは既存の ADR を +書き換えるのではなく、新しい ADR を書いて古いものを `Superseded` にする。 + +AGENTS.md には、どういう判断を ADR にすべきかの基準を書き、両者を相互に参照させる。 + +## 理由 + +ADR は「決定そのもの」ではなく「決定に至った制約」を残せる点が、コメントやコミットメッセージより優れている。 +このリポジトリで重要なのは、まさにその制約 (EDItEUR の配布形態、生成物の互換性、テンプレートの責務分担) が +時間とともに変わることなので、当時の前提ごと記録に残せる形式が要る。 + +Markdown をリポジトリ内に置くのは、スキーマや生成物と同じコミットで変更履歴が追えるため。 +外部の Wiki やイシューに書くと、コードとの対応が切れる。 + +## 検討した他の選択肢 + +- **AGENTS.md / README.md に全部書く**: 判断の履歴が積み上がると読みものとして破綻する。 + AGENTS.md は「今どうすべきか」を書く場所として保ち、「なぜそうなったか」は ADR に分ける。 +- **GitHub Issues / Discussions に残す**: 検索性はあるが、リポジトリを clone しただけでは読めず、 + コードとの対応も切れる。オフラインで完結しない。 +- **記録しない (現状維持)**: 調査のやり直しと、意図しない互換性破壊が続く。 + +## 結果 + +- 新しい設計判断、および後から言語化された既知の判断は ADR に書く。 +- ADR を追加したら `docs/adr/README.md` の一覧も更新する。 +- ADR はレビュー対象になる。判断に異論があれば、実装ではなく ADR に対してコメントできる。 diff --git a/docs/adr/0002-decouple-unit-tests-from-the-vendored-schema.md b/docs/adr/0002-decouple-unit-tests-from-the-vendored-schema.md new file mode 100644 index 0000000..af219d2 --- /dev/null +++ b/docs/adr/0002-decouple-unit-tests-from-the-vendored-schema.md @@ -0,0 +1,81 @@ +# ADR-0002: ユニットテストを取得済みスキーマから切り離す + +- **ステータス**: Accepted +- **日付**: 2026-09-13 + +## 背景 + +Makefile のテストターゲットは `schema` に依存していた。 + +```make +.PHONY: test +test: schema + stack test --trace --fast +``` + +`schema` ターゲットは Bazel の `http_archive` 経由で EDItEUR の zip をダウンロードし、 +`schema/v2` / `schema/v3` に展開する。つまり `make test` は毎回 editeur.org への +ネットワークアクセスを要求していた。 + +2026-09-13 時点で、CI からこのダウンロードが失敗するようになった。 + +``` +WARNING: Download from https://www.editeur.org/files/ONIX%202.1/ONIX_for_Books_Release2-1_rev03_schema+codes_Issue_36.zip + failed: UnrecoverableHttpException GET returned 202 Accepted +ERROR: An error occurred during the fetch of repository 'org_editeur_v2' +make: *** [Makefile:35: schema/v2] Error 1 +``` + +editeur.org が zip の代わりに `202 Accepted` を返しており、Bazel はこれを回復不能な +ダウンロードエラーとして扱う。結果として、`Test haskell codes` ジョブはテストを 1 件も +実行しないまま失敗する。 + +ここで重要なのは、**テストコードはそもそも `schema/` を読んでいない**という事実である。 +`test/` 配下が読むのは `fixtures/test_*.xsd` だけで、`./schema` を参照するのは +`src/Lib.hs` の `schemaRoot` (コード生成の実行時パス) のみ。つまりこの依存は、 +テストの実行に必要ではないのに、テストの実行可能性を外部サービスの可用性に縛り付けていた。 + +## 決定 + +`test` ターゲットから `schema` 依存を外す。 + +```make +.PHONY: test +test: + stack test --trace --fast +``` + +`build` ターゲットの `schema` 依存はそのまま残す。実際にコードを生成するには +スキーマの実体が要るため、こちらは本物の依存である。 + +## 理由 + +ユニットテストは「XSD をどう解釈して中間表現に落とすか」を検証するものであり、 +その入力は意図的に最小化された `fixtures/test_*.xsd` である。EDItEUR の完全なスキーマは +テストの対象ではない。依存として書かれていたのは事実の反映ではなく、単なる過剰指定だった。 + +この過剰指定には実害がある。外部サービスの都合で、リポジトリ内のロジックに対する +フィードバックループ全体が止まる。パーサのバグを直したいときに editeur.org の状態に +左右されるのは、依存の向きとして誤っている。 + +なお、この変更は 202 の問題そのものを解決しない。コード生成と、生成物を最新スキーマへ +追従させる作業は依然としてダウンロードを必要とする。これは別の判断として切り出す。 + +## 検討した他の選択肢 + +- **`http_archive` にリトライやフォールバック URL を足す**: Bazel 3.7.0 の `http_archive` は + カスタムヘッダに対応しておらず、202 を返す bot 対策を回避する手段がない。 + そもそもテストにダウンロードは不要なので、この層で解決するのは筋が悪い。 +- **スキーマをリポジトリに取り込む (vendoring)**: テストは通るようになるが、 + EDItEUR の配布物の再配布はライセンス上の検討を要する。テストを通すためだけに + 踏み込む判断ではない。生成のために必要かどうかは別途検討する。 +- **CI でだけ `stack test` を直接呼ぶ**: CI とローカルで手順が食い違い、 + 「手元で通るのに CI で落ちる」を生む。Makefile が唯一の入口である状態を保つ。 + +## 結果 + +- `make test` はネットワークなしで実行できる。CI の Haskell ジョブは editeur.org に依存しない。 +- コード生成 (`make build`、`make generated/...`) は引き続きダウンロードを必要とする。 + 最新スキーマへの追従が止まっている場合、原因はこちら側にある。 +- 新しいテストを書くときは `fixtures/` に最小の XSD を足す、という既存の慣習が + そのまま「テストを外部依存から切り離す」ことにもなっている。この性質は維持する。 diff --git a/docs/adr/README.md b/docs/adr/README.md new file mode 100644 index 0000000..fa8323f --- /dev/null +++ b/docs/adr/README.md @@ -0,0 +1,26 @@ +# Architecture Decision Records (ADR) + +このディレクトリには、onix-codegen の設計判断を記録する ADR を置く。 + +## 一覧 + +| # | タイトル | ステータス | +| ------------------------------------------------------------- | ---------------------------------------------- | ---------- | +| [0001](0001-record-architecture-decisions.md) | 設計判断を ADR として記録する | Accepted | +| [0002](0002-decouple-unit-tests-from-the-vendored-schema.md) | ユニットテストを取得済みスキーマから切り離す | Accepted | + +## 書き方 + +`0000-template.md` をコピーして、次の連番を付ける。番号は一度振ったら変えない。 + +ADR は「その時点で、どういう制約のもとに、なぜそう決めたか」を残すもの。 +後から判断が変わったら、既存の ADR を書き換えるのではなく、新しい ADR を書いて +古いものの Status を `Superseded by ADR-XXXX` に更新する。決定の履歴が消えないことが重要。 + +## どういう判断を ADR にするか + +このリポジトリの価値 (AGENTS.md 参照) に照らして、次のいずれかに影響するもの。 + +- **後方互換性**: 生成コードの公開 API に影響する判断、スキーマの版の扱い方 +- **サポート言語の増やしやすさ**: 中間表現とテンプレートの責務分担、言語追加の手順に影響する判断 +- **ビルドと CI の前提**: 外部依存 (EDItEUR の配布物、ツールチェーンのバージョン) の扱い方 From 5af27c01bae0a7cad4f482fd497cdc406905c85c Mon Sep 17 00:00:00 2001 From: kogai Date: Sun, 13 Sep 2026 07:08:42 +0000 Subject: [PATCH 3/6] Make the mixed-HTML fixture self-contained MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z --- Makefile | 10 +- ...ple-unit-tests-from-the-vendored-schema.md | 91 ++++++++++++------- fixtures/test_mixed_html.xsd | 2 +- fixtures/test_mixed_html_xhtml_subset.xsd | 53 +++++++++++ 4 files changed, 118 insertions(+), 38 deletions(-) create mode 100644 fixtures/test_mixed_html_xhtml_subset.xsd diff --git a/Makefile b/Makefile index 6a06415..e761507 100644 --- a/Makefile +++ b/Makefile @@ -12,10 +12,12 @@ generated/ts/%: build debug: build stack exec --trace -- onix-exe +RTS -xc --RTS --schemaVersion v3 --language go -# The unit tests read only fixtures/*.xsd, so they deliberately do not depend -# on the `schema` target: `make schema` downloads the EDItEUR archives over the -# network, and requiring it here made the test suite unrunnable whenever -# editeur.org was unreachable. See docs/adr/0002-decouple-unit-tests-from-the-vendored-schema.md +# The fixtures under fixtures/ are self-contained, so the tests deliberately do +# not depend on the `schema` target: `make schema` downloads the EDItEUR +# archives over the network, and requiring it here made the test suite +# unrunnable whenever editeur.org was unreachable. Keep fixtures from including +# anything outside fixtures/, or this dependency comes back. +# See docs/adr/0002-decouple-unit-tests-from-the-vendored-schema.md .PHONY: test test: stack test --trace --fast diff --git a/docs/adr/0002-decouple-unit-tests-from-the-vendored-schema.md b/docs/adr/0002-decouple-unit-tests-from-the-vendored-schema.md index af219d2..2de7097 100644 --- a/docs/adr/0002-decouple-unit-tests-from-the-vendored-schema.md +++ b/docs/adr/0002-decouple-unit-tests-from-the-vendored-schema.md @@ -17,7 +17,7 @@ test: schema `schema/v2` / `schema/v3` に展開する。つまり `make test` は毎回 editeur.org への ネットワークアクセスを要求していた。 -2026-09-13 時点で、CI からこのダウンロードが失敗するようになった。 +2026-09-13 時点で、この取得が機能しなくなった。 ``` WARNING: Download from https://www.editeur.org/files/ONIX%202.1/ONIX_for_Books_Release2-1_rev03_schema+codes_Issue_36.zip @@ -26,56 +26,81 @@ ERROR: An error occurred during the fetch of repository 'org_editeur_v2' make: *** [Makefile:35: schema/v2] Error 1 ``` -editeur.org が zip の代わりに `202 Accepted` を返しており、Bazel はこれを回復不能な -ダウンロードエラーとして扱う。結果として、`Test haskell codes` ジョブはテストを 1 件も -実行しないまま失敗する。 +その結果、`Test haskell codes` ジョブはテストを 1 件も実行しないまま失敗する。 +取得できない理由そのものは ADR-0003 で扱う。 -ここで重要なのは、**テストコードはそもそも `schema/` を読んでいない**という事実である。 -`test/` 配下が読むのは `fixtures/test_*.xsd` だけで、`./schema` を参照するのは -`src/Lib.hs` の `schemaRoot` (コード生成の実行時パス) のみ。つまりこの依存は、 -テストの実行に必要ではないのに、テストの実行可能性を外部サービスの可用性に縛り付けていた。 +### この依存は本物だった -## 決定 +当初、この依存は単なる過剰指定だと考えた。テストコードが直接読むのは +`fixtures/test_*.xsd` だけで、`./schema` という文字列は `src/Lib.hs` の `schemaRoot` +にしか現れないからである。しかしこれは誤りだった。 -`test` ターゲットから `schema` 依存を外す。 +`fixtures/test_mixed_html.xsd` が、EDItEUR の配布物を直接 include していた。 -```make -.PHONY: test -test: - stack test --trace --fast +```xml + ``` -`build` ターゲットの `schema` 依存はそのまま残す。実際にコードを生成するには -スキーマの実体が要るため、こちらは本物の依存である。 +`Xsd.getSchema` は include を再帰的にたどり (`src/Xsd.hs` の `go` / `goInclude`)、 +相対パスを `combineURIs` でローカルパスに解決して `Text.XML.readFile` で読む。 +ファイルが無ければ IOException で落ちる。このフィクスチャは +`test/TestMixed.hs` と `test/TestModel.hs` の両方から読まれており、`schema/` は +`.gitignore` されているので、clean checkout では必ず存在しない。 + +つまり `test: schema` は正しい依存だった。git の履歴もそれを裏づけている。 +`test: schema` を追加したコミット (9352123) は、リポジトリに置かれていた +`2_1_rev03_schema/` を削除し、このフィクスチャの include を `../schema/v2/` に +向け直した、まさにそのコミットである。 + +## 決定 + +依存を消すのではなく、**依存の対象をリポジトリ内に移す**。 + +1. `fixtures/test_mixed_html_xhtml_subset.xsd` を追加する。`test_mixed_html.xsd` が + `ref` している 40 個の要素名だけを宣言した、ONIX_XHTML_Subset.xsd の代替物である。 +2. `test_mixed_html.xsd` の include をそちらに向ける。 +3. そのうえで `test` ターゲットから `schema` 依存を外す。 + +`build` ターゲットの `schema` 依存は残す。実際にコードを生成するにはスキーマの実体が +要るため、こちらは今も本物の依存である。 ## 理由 -ユニットテストは「XSD をどう解釈して中間表現に落とすか」を検証するものであり、 -その入力は意図的に最小化された `fixtures/test_*.xsd` である。EDItEUR の完全なスキーマは -テストの対象ではない。依存として書かれていたのは事実の反映ではなく、単なる過剰指定だった。 +代替物は、テストが実際に検証している性質を保つように書いた。 +`test/TestModel.hs` は、このフィクスチャを読んだうえで `Model.collectElements` が +空になることを表明している。`collectElements` は `complexMixed = False` の要素だけを +拾うフィルタなので、この表明の意味は「XHTML の要素がモデルに漏れてこない」ことである。 +XHTML の内容要素はいずれも mixed content なので、代替物でも全要素を +`` として宣言した。要素名の集合が実物と一致していること、 +フィクスチャ側の `ref` 40 個すべてに宣言が対応することは機械的に確認した。 + +代替物で足りるのは、テストがこのファイルから必要としているのが**要素の宣言の存在と +mixed であること**だけだからである。ONIX_XHTML_Subset.xsd の完全な内容 (属性、 +コンテンツモデルの詳細) は、ここで検証されている性質に寄与していない。 -この過剰指定には実害がある。外部サービスの都合で、リポジトリ内のロジックに対する -フィードバックループ全体が止まる。パーサのバグを直したいときに editeur.org の状態に -左右されるのは、依存の向きとして誤っている。 +そのうえで、テストを外部サービスの可用性から切り離す価値は大きい。パーサのバグを +直したいときに editeur.org の状態に左右されるのは、依存の向きとして誤っている。 なお、この変更は 202 の問題そのものを解決しない。コード生成と、生成物を最新スキーマへ -追従させる作業は依然としてダウンロードを必要とする。これは別の判断として切り出す。 +追従させる作業は依然としてダウンロードを必要とする (ADR-0003)。 ## 検討した他の選択肢 -- **`http_archive` にリトライやフォールバック URL を足す**: Bazel 3.7.0 の `http_archive` は - カスタムヘッダに対応しておらず、202 を返す bot 対策を回避する手段がない。 - そもそもテストにダウンロードは不要なので、この層で解決するのは筋が悪い。 -- **スキーマをリポジトリに取り込む (vendoring)**: テストは通るようになるが、 - EDItEUR の配布物の再配布はライセンス上の検討を要する。テストを通すためだけに - 踏み込む判断ではない。生成のために必要かどうかは別途検討する。 -- **CI でだけ `stack test` を直接呼ぶ**: CI とローカルで手順が食い違い、 - 「手元で通るのに CI で落ちる」を生む。Makefile が唯一の入口である状態を保つ。 +- **`test: schema` を残す**: 事実としては正しい依存なので、これは筋が通っている。 + ただし、たった 1 ファイルの XSD のためにテスト全体を外部サービスに縛り続けることになる。 +- **ONIX_XHTML_Subset.xsd をそのまま `fixtures/` に取り込む**: 代替物より忠実だが、 + EDItEUR の配布物の再配布にあたる。ライセンスの判断が要るため、テストを通すためだけに + 踏み込むべきではない (ADR-0003 と同じ理由)。代替物は自前で書いたものなのでこの問題がない。 +- **include を単に削除する**: `Annotation` 以外に要素が無くなるので `collectElements` は + 空になり、表明は通ってしまう。だが「XHTML 要素が漏れてこない」ことを何も検証しなくなり、 + テストが意味を失う。**採らない。** ## 結果 - `make test` はネットワークなしで実行できる。CI の Haskell ジョブは editeur.org に依存しない。 +- `fixtures/test_mixed_html_xhtml_subset.xsd` は実物の代替物である。実物側の構造が変わって + テストの前提が動くことはあり得るので、スキーマの版を上げるときはこのファイルも見直す。 - コード生成 (`make build`、`make generated/...`) は引き続きダウンロードを必要とする。 - 最新スキーマへの追従が止まっている場合、原因はこちら側にある。 - 新しいテストを書くときは `fixtures/` に最小の XSD を足す、という既存の慣習が - そのまま「テストを外部依存から切り離す」ことにもなっている。この性質は維持する。 + そのまま「テストを外部依存から切り離す」ことにもなる。この性質は維持する。 + フィクスチャから `fixtures/` の外を include しないこと。 diff --git a/fixtures/test_mixed_html.xsd b/fixtures/test_mixed_html.xsd index 110ce0e..642cdf2 100644 --- a/fixtures/test_mixed_html.xsd +++ b/fixtures/test_mixed_html.xsd @@ -1,6 +1,6 @@ - + diff --git a/fixtures/test_mixed_html_xhtml_subset.xsd b/fixtures/test_mixed_html_xhtml_subset.xsd new file mode 100644 index 0000000..5be1621 --- /dev/null +++ b/fixtures/test_mixed_html_xhtml_subset.xsd @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From aa338951dd8c653c0cdc18c5098043fea7bbd28d Mon Sep 17 00:00:00 2001 From: kogai Date: Sun, 13 Sep 2026 07:12:04 +0000 Subject: [PATCH 4/6] Stop `make test` from invoking bazel, and drop a debug step MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z --- .github/workflows/test.yml | 1 - Makefile | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 3b21b44..b8f4f2e 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,7 +22,6 @@ jobs: key: ${{ runner.os }}-${{ hashFiles('**/package.yaml') }}-${{ hashFiles('**/onix.cabal') }}-${{ hashFiles('**/stack.yaml.lock') }} restore-keys: | ${{ runner.os }}- - - run: ls -lah ${{steps.haskell-setup.outputs.stack-path}} - run: make test e2e: name: Test e2e diff --git a/Makefile b/Makefile index e761507..46ad7d1 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,9 @@ TS_FILES := $(shell find ./ -type f -name '*.ts' | grep -v 'node_modules') HS_FILES := $(shell find ./ -type f -name '*.hs' | grep -v '.stack-work') BZL := npx bazelisk -BZL_BIN := $(shell npx bazel info bazel-bin) +# Deferred on purpose: `:=` would run bazel on every make invocation, including +# `make test`, which runs in a job with no node_modules and no need for bazel. +BZL_BIN = $(shell $(BZL) info bazel-bin) generated/go/%: build stack exec onix-exe -- --schemaVersion $(@F) --language go From 49950b1c397d13b68919e7a4e78b0ecb3db238b0 Mon Sep 17 00:00:00 2001 From: kogai Date: Sun, 13 Sep 2026 07:19:29 +0000 Subject: [PATCH 5/6] Drop three unused Haskell dependencies MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit flow, unordered-containers and mtl are declared in the library stanza but nothing imports them. $ grep -rh '^import' src app test | ... # no Flow, no Data.HashMap, # no Control.Monad.{State,Reader, # Writer,Except} The two "Flow" hits in the tree are ONIX type names in test expectations, not the package. The State, Reader and Except monad transformers the parser uses come from Control.Monad.Trans.*, which is transformers, not mtl; transformers stays declared. They are removed ahead of the resolver bump rather than with it: three fewer packages the snapshot has to satisfy, and three fewer candidates to rule out if that bump does not compile. onix.cabal is hpack output but it is committed, so it is updated to match by hand — the same three build-depends entries. Regenerating it properly needs stack, which cannot run here (haskell.org is blocked by egress policy), so CI is what confirms this. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z --- onix.cabal | 3 --- package.yaml | 3 --- 2 files changed, 6 deletions(-) diff --git a/onix.cabal b/onix.cabal index e696f33..c1ce21e 100644 --- a/onix.cabal +++ b/onix.cabal @@ -45,16 +45,13 @@ library , bytestring ==0.10.10.1 , containers ==0.6.2.1 , filepath ==1.4.2.1 - , flow ==1.0.21 , http-client ==0.6.4.1 , http-client-tls ==0.3.5.3 - , mtl ==2.2.2 , mustache ==2.3.1 , network-uri ==2.6.3.0 , parsec ==3.1.14.0 , text ==1.2.4.0 , transformers ==0.5.6.2 - , unordered-containers ==0.2.10.0 , vector ==0.12.1.2 , xml-conduit ==1.9.0.0 , yaml ==0.11.5.0 diff --git a/package.yaml b/package.yaml index 3e2f39d..50e6ae6 100644 --- a/package.yaml +++ b/package.yaml @@ -32,14 +32,11 @@ library: - mustache == 2.3.1 - text == 1.2.4.0 - yaml == 0.11.5.0 - - unordered-containers == 0.2.10.0 - vector == 0.12.1.2 - xml-conduit == 1.9.0.0 - - flow== 1.0.21 - parsec == 3.1.14.0 - containers == 0.6.2.1 - transformers == 0.5.6.2 - - mtl == 2.2.2 - bytestring == 0.10.10.1 - filepath == 1.4.2.1 - http-client-tls == 0.3.5.3 From 4653a9d69e1d905262d9f14fe4a224a3e205f6b0 Mon Sep 17 00:00:00 2001 From: kogai Date: Sun, 13 Sep 2026 07:33:33 +0000 Subject: [PATCH 6/6] Narrow the Control.Monad.Trans import so mtl can actually go MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review caught that mtl was not in fact unused. src/Xsd/Parser.hs:14 was `import Control.Monad.Trans` — the bare module, which transformers does not expose. It comes from mtl, which re-exports Control.Monad.Trans.Class and Control.Monad.IO.Class through it. The check behind the previous commit only looked for Control.Monad.{State,Reader,Writer,Except}, so this line went unnoticed, and with -hide-all-packages the build would have failed on a missing module rather than anything subtle. Import Control.Monad.Trans.Class (lift) instead. lift is the only thing Parser.hs used from it (one use, line 598); liftIO in Xsd.hs comes from base's Control.Monad.IO.Class, which that module already imports directly. With this, mtl really is unused. Also refresh onix.cabal's hpack hash, which the previous commit left pointing at the pre-edit content. A stale hash makes hpack treat the file as hand-modified and stop regenerating it, so later package.yaml changes would silently fail to propagate. The algorithm was confirmed by reproducing origin/main's recorded hash from its own file before computing this one. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01P8rZakwAiz1jpViUX34x1Z --- onix.cabal | 2 +- src/Xsd/Parser.hs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/onix.cabal b/onix.cabal index c1ce21e..373a58a 100644 --- a/onix.cabal +++ b/onix.cabal @@ -4,7 +4,7 @@ cabal-version: 1.12 -- -- see: https://github.com/sol/hpack -- --- hash: d894bbda696a3e4398796a16a928bd9923bbeaae2b4a61ad371f193c8322fa0d +-- hash: ccd13791926f8c74575d5f17648a17adbbe0740ce44707823a93b20ae5f7605c name: onix version: 0.1.0.0 diff --git a/src/Xsd/Parser.hs b/src/Xsd/Parser.hs index df7c154..884930b 100644 --- a/src/Xsd/Parser.hs +++ b/src/Xsd/Parser.hs @@ -11,7 +11,7 @@ module Xsd.Parser where import Control.Monad -import Control.Monad.Trans +import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.Except import Control.Monad.Trans.Reader import qualified Data.ByteString.Lazy as Lazy (ByteString)