ドキュメントビルド環境の現代化(Sphinx 1.3.6 → 9.1.0 / Python 3.12 / docutils 0.22) - #729
Open
kumagoro1202 wants to merge 5 commits into
Open
ドキュメントビルド環境の現代化(Sphinx 1.3.6 → 9.1.0 / Python 3.12 / docutils 0.22)#729kumagoro1202 wants to merge 5 commits into
kumagoro1202 wants to merge 5 commits into
Conversation
ビルド成果物を一切変えずにビルド環境を最新化する。
- ベースイメージ: python:3.8.18-slim (EOL) -> python:3.10.20-slim
- Sphinx 1.3.6 は Python 3.11 の正規表現仕様変更で起動不能のため、
現行ツールチェーンでの上限は 3.10 系
- docutils-ast-writer の use_2to3 対応のため setuptools==57.5.0 に
固定し --no-build-isolation でインストール
- Python 3.10 で削除された stdlib parser モジュールの互換シムを追加
(無指定コードブロックのハイライト判定を 3.8 時代と同一に保つため)
- Node.js: 実体は Debian 標準の 18 系だったものを NodeSource 22 系 LTS へ
- 従来はベースイメージに curl が無く NodeSource セットアップが無言で
失敗し、Debian 標準の nodejs 18.20.4 が入っていた
- curl を明示導入し、スクリプトをファイル保存してから実行することで
ダウンロード失敗をビルド失敗として検知するよう修正
- textlint: 12.2.1 -> 15.7.1 / patch-package: 6.4.7 -> 8.0.1
- npm audit の high 深刻度 5 件を解消 (残りは moderate 3 件のみ:
textlint 15 の MCP サーバ機能由来で lint 用途では影響なし)
- textlint-plugin-rst 0.1.1 と既存パッチはそのまま動作
- Python 支援ライブラリ (requests / urllib3 / certifi / lxml ほか) を更新
- HTML 生成に関与する Sphinx / docutils / Pygments / テーマ等は据え置き
検証: 更新前後の環境で日英ドキュメントをフルビルドし、全 2378 ファイルの
SHA-256 が完全一致することを確認 (更新前環境の 2 回ビルドで決定性も確認)。
textlint は同一入力に対し新旧で同一の検出結果を返すことを確認。
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
HTML生成中核を保守が継続している最新ツールチェーンへ更新し、
継続開発可能な状態にする。
- Sphinx 1.3.6 -> 9.1.0 / docutils 0.15.2 -> 0.22.4 /
sphinx-rtd-theme 0.2.4 -> 3.1.0 / Pygments 2.4.2 -> 2.20.0
- Python: 3.10 -> 3.12 (Sphinx 9.1 の下限要件)
- javasphinx 0.9.15 (2019年アーカイブ済み・現行Sphinxで起動不能) の
必要部分 (Javaドメイン + :java:extdoc: ロール) を _extensions/ へ
同梱し、外部の放棄パッケージへの依存を解消 (Apache-2.0、原本の
ライセンス表記を保持)
- sphinx.locale.l_ の削除対応 (l_ -> _)
- コンストラクタ参照 Class.<init>(...) の明示タイトル解釈を
ロール内に実装 (Sphinx 4 以降の正規表現変更への対応。
rst本文は変更しない)
- conf.py: add_javascript -> add_js_file、extlinks キャプション '%s' 化
- requirements を直接依存 (requirements.in) + lock (requirements.txt) 構成へ変更
- Dockerfile をマルチステージ化し、HTML生成環境 (Python 3.12) と
textlint環境 (Python 3.10 + docutils-ast-writer) を分離
- README を新環境の構築・ビルド手順へ更新
Sphinx更新前後のビルド済みHTMLツリーを意味レベルで比較する検証器 (semdiff.py)・その自己テスト (canary_suite.py) と実行結果・READMEを 同梱する。ビルド時にはロードされない独立ツールのため _extensions/ とは分離して配置。将来のツールチェーン更新時の回帰検証にも再利用可能。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
# Conflicts: # Dockerfile # README.md # requirements.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概要
#727(成果物バイト完全一致を条件とした周辺ツールチェーン更新)の次段階として、HTML生成の中核(Sphinx / docutils / テーマ / Javaドメイン拡張)を含むビルド環境全体を現代化します。
Sphinx本体のメジャー更新(1.3.6 → 9.1.0)を伴うため、今回は成果物HTMLに差異が生じます。そこで合否条件を「見た目(テーマ・配色等)の変化は許容。ただし (a) 本文テキストの欠損・欠落・文字化けが1件もないこと、(b) 内部リンク・アンカー・画像・ダウンロード資材の破損が1件もないこと」と定め、専用の意味的差分検証器を作成して新旧の全ビルド成果物を機械検証しました。
結果は 988ページ完全1:1対応(欠損0・追加0)・本文情報の欠損0件・リンク等の破損0件 です。残る差異は活字表現上の表示差598件のみで、全件を機械分類し原因を特定済みです(後述。旧環境が設定意図に反して行っていた引用符自動変換の消失559件+脚注後方参照の表記差39件)。
変更内容(before → after)
_extensions/javasphinx/へ同梱化(vendoring)(詳細後述)requirements.in(直接依存)+requirements.txt(pip-compile生成lock)の2層構成(lockはpython:3.12-slimコンテナ内で生成)requirements-lint.txt新設(docutils 0.15.2+docutils-ast-writer 0.1.2+six。Python 3.10前提)--target lint: Python 3.10+Node 22。旧parserシム・setuptoolsピンはlintステージにのみ維持)add_javascript→add_js_file(Sphinx 4.0で削除されたAPIの置換)、extlinksキャプションの'%s'化、無害な迷い込み行[extensions]の清掃、_extensions/のsys.path追加javasphinxの同梱化(vendoring)について
sphinx.locale.l_のImportError)。保守されたフォーク・後継は存在しません。:java:extdoc:ロール(日英計3,948箇所)と.. java:method::ディレクティブ(日英各1箇所)のみのため、必要部分(__init__.py/domain.py/extdoc.py/formatter.py/util.py)を_extensions/javasphinx/に同梱しました。ビルド未使用のapidoc系(apidoc.py / compiler.py / htmlrst.py)は同梱せず、lxml / beautifulsoup4 / future への依存を解消しています。LICENSEとして同梱し、各ソースの著作権ヘッダも原本のまま保持。README.mdに出所(bronto/javasphinx 0.9.15)・経緯・変更点を明記しています。domain.py:from sphinx.locale import l_→_(Sphinx 4以降対応の最小パッチ)extdoc.py: 現行Sphinxは明示タイトルの正規表現が変更され、ターゲットに<を含むClass.<init>(...)記法(日英4ファイル・計6箇所)が解釈エラーになるため、extdocロール内に限定して旧来の解釈を実装(rst本文は一切変更せず、:ref:等の他ロールへの副作用もありません).. java:method::のシグネチャ解析に必要なjavalang==0.13.0は維持しています。lint環境を分離した理由
textlint-plugin-rst が依存する docutils-ast-writer 0.1.2 は
use_2to3を用いる旧世代パッケージで、Python 3.12では導入経路が存在しません(distutils削除によりsetuptools 57.5.0自体が動作しない)。textlintはHTML出力に関与しないため、lint環境をPython 3.10のDockerステージとして分離しました。成果物への影響はありません。検証の観点と方法
新旧2つのビルド済みHTMLツリーを意味レベルで比較する検証器(
semdiff.py。本PRのtools/doc-build-verifier/に同梱)を作成し、以下の4観点を機械検証しました。比較対象は同一コミットのrstソースを旧環境・新環境それぞれでフルビルドした2ツリーです。_static/**/*.html(yuidoc生成のJS APIドキュメント等)はSphinxが変換せず複製するため、より厳格なバイト同一で照合。*[role="main"]からブロック要素単位で可読テキストを抽出(script/style/パーマリンク¶は除去。正規化は連続空白の畳み込みのみで、Unicode正規化は情報改変になり得るため不採用=バイト等価比較)。旧ページの全テキスト片が新ページに含まれるかを多重集合で照合し、見つからない片はtext-missingとしてNG。文字化けもバイト等価比較によりtext-missingとして検出されます。新テーマ由来の追加文言(UI文字列等)は許容(包含照合)。a[href]/img[src]等を全数列挙し、内部リンク・アンカーは新ビルド内で解決するか(サイト内自己整合)を検査。画像・DL資材は参照経路をキーに内容SHA-256の多重集合で照合(版間のファイル名ハッシュ規則変化に頑健。内容が失われればNG)。旧ビルドに元から存在する破損は除外し、新規リグレッションのみNG。旧アンカーIDが新に存在しない差分(外部からの深リンク切れの可能性)は合否と別にreport-onlyで全件記録。さらに、検証方式自体の穴を塞ぐ検査を併用しています。
実行コマンド:
(依存: Python 3.12+lxml)
実測結果
c241906を従来環境(Sphinx 1.3.6 / Python 3.10)でja+enフルビルドした988ページ19a641b。それ以降の本ブランチの差分は検証器tools/doc-build-verifier/の追加のみで、ビルド成果物には影響しません)検証器の実出力:
新環境ビルドの完全性: ja 334rst→495HTML(実測4分00秒・警告3件)/ en 332rst→493HTML(4分14秒・警告1件)、総2426ファイル・全17トップレベルセクション。警告は全てJSPコードブロック内の日本語句読点によるハイライト失敗→relaxedモード自動回復(
misc.highlighting_failure)で、可読テキストへの影響はありません。rst参照系警告(unknown target等)は0件です。表示差598件の内訳と根本原因
検証器は意図的に「バイト等価・正規化なし」で設計しているため、意味を変えない活字差もNGとして検出します(検出自体は正当な動作です)。NG 598件(184ページ: ja 54 / en 130)を、検証器と同一の抽出・正規化ロジックを用いた照合スクリプトで全件機械分類しました(残余0件)。
“ ” ‘ ’ – — …(自動変換後) / 新:" ' -- --- ...(ソース原文のまま)。逆写像を適用すると旧本文の全文が新側に存在することを機械照合で確認(1, 2)(カンマ後スペース) / 新:(1,2)。脚注本文は全量新側に存在(a)の根本原因: 本リポジトリのja/en
docutils.confには以前からsmart_quotes: falseが明示されています(かぎ括弧の自動変換を無効化する意図のコメント付き)。ところが旧Sphinx 1.3.6は、この設定が及ばないHTMLライタ層のSmartyPants変換(html_use_smartypantsデフォルト有効)で引用符類を自動変換していました。つまり旧ビルドの曲引用符は、リポジトリ自身の設定意図に反して出力されていたものです。新Sphinx 9はsmart_quotes: falseを正しく尊重し、ソース原文の記号をそのまま出力します。例(
ja/about_nablarch/versionup_policy.rst、ソースは"architect"):@Published(tag = “architect”)(自動変換)@Published(tag = "architect")(ソースどおり)(b)の根本原因: docutils 0.22で脚注のHTML構造が
<table>から<aside>へ変更された副作用で、脚注の後方参照リストの区切り表記が変わったものです。この文字列はビルダーが生成するナビゲーションUI文言であり、著者が書いた本文ではありません。以上より、598件はいずれも意味的な情報欠損ではなく、ソースおよびリポジトリの設定意図に忠実な新挙動として受容する方針です。
脆弱性の状況
requirements.txt(docs)・requirements-lint.txtとも既知脆弱性0件。@hono/node-server<2.0.5のWindows限定path traversalが@modelcontextprotocol/sdk経由でtextlint≥15.5.1に連鎖するもの)。修正にはtextlint 15.5.0への後退(breaking)が必要なため、#727と同方針(npm auditは情報表示・合否判定外)で据え置き。lint環境限定でありHTML成果物には無関係です。再現手順(第三者による追試)
1. 旧環境(基準)のビルド
生成された
_build/html(ja 495+en 493=988 HTMLページ)をOLD_TREEとして退避します。2. 新環境のビルド
期待結果: ja「build succeeded, 3 warnings.」/en「build succeeded, 1 warning.」(いずれもJSPハイライト警告のみ)。
_build/htmlをNEW_TREEとします。3. 検証器の実行(Python 3.12+lxml)
検証器一式(
semdiff.py/canary_suite.py/ README / 自己テスト実行結果)は本PRのブランチに同梱されています。手順2でsphinx-modernizationをcheckoutした時点で、クローン内のtools/doc-build-verifier/配下に揃っており、追加の入手作業は不要です。report.jsonのsummary期待値:{ "pages_old": 988, "pages_new": 988, "pages_compared": 666, "verbatim_pages_compared": 318, "verbatim_pages_identical": 318, "generated_pages_skipped": 4, "missing_pages": [], "added_pages": [], "ng_count": 598, "gray_count": 0, "byte_identical": 0, "display_only": 482, "text_pass_with_additions": 0, "old_build_broken_refs": 0, "new_build_broken_refs": 0, "broken_ref_regressions": 0 }ng 598件が全て前述の表示差(引用符559+脚注39)であること、
missing_pages・added_pages・broken_ref_regressionsが空/0であることが確認ポイントです。検証器の健全性はtools/doc-build-verifier/canary_suite.py(前述の15ケース)で確認できます。当方環境での実行結果は同ディレクトリのcanary_results.txtに収録しています。🤖 Generated with Claude Code