何を見つけたか
lib/devbase/commands/container.py に、構造改善の候補が 2 つある。
| 対象 |
兆候 |
内容 |
cmd_scale(1596-1690、本体 86 行) |
長いメソッド |
前提の検査・context の解決・[1/5] project.yml の scale 書き換え・[2/5] ボリューム・[2.5/5] network・[3/5] 構成生成・[4/5] --no-recreate の起動・[5/5] ready 待ち・bao token・deploy フック・完了ログを 1 関数で通しで持つ。cmd_up は同種の本体を _run_deploy_pipeline(1254-、[1/6]〜[5/6] と [1.5/6])へ抽出済みで、scale だけ段階に名前が無い |
_resolve_dev_service(1789) / _read_compose_services(1967) |
重複 |
どちらも docker compose config --format json の実行・compose_env() の適用・終了コードの判定・services の取り出しを持つ。不正 JSON のときだけ前者は None を返し、後者は例外を伝播する |
振る舞いの側にも食い違いがある
cmd_scale は Compose を共通経路(lib/devbase/utils/docker.py の docker_compose())を通さずに直接呼ぶため、compose_env() が適用されない。
result = subprocess.run(
['docker', 'compose', '-f', str(override_file), 'up', '-d', '--no-recreate'],
check=False
)
compose_env() を通る場所は utils/docker.py の docker_compose()、container.py の _compose_run / _resolve_dev_service / _read_compose_services、editor/opener.py である。cmd_scale はこの一覧に無い。
確定仕様 docs/specifications/compose-profiles.md は、同じ文書の中で相反することを書いている。
- 「
cmd_scale が直接呼ぶ docker compose -f <生成物> up -d --no-recreate はこの対象に含めない。プロファイルの入口ではないためである」
- 「
COMPOSE_PROFILES を端末や .env に置いても devbase 経由の操作には効かない。素の docker compose には従来どおり効く」
devbase scale は devbase 経由の操作であり、2 つ目の約束は cmd_scale では成り立たない。端末または .env に COMPOSE_PROFILES を置いた状態で devbase scale を打つと、その環境が子プロセスへそのまま渡る。サービスの指定も無いため、プロファイルのサービスが起動の対象に入りうる。
実害の観測はまだ無い。 確定仕様の約束と実装が食い違っていることまでが分かっている。
なぜこの変更の範囲外だったのか
PR #191 は #189(Compose の profiles)の実装で、cmd_scale には手を入れていない。境界は「依頼範囲外のリファクタリングを行わない」と定め、devbase scale の直接の Compose 呼び出しも「含まない」に挙げていた(現在の所在は docs/specifications/compose-profiles.md)。config 読み取りの 2 関数は、PR #191 では env=compose_env() を足しただけである。
v3.6.0 の container.py への変更(PR #207 の _build_single_image への名前検証の追加、PR #199 の devbase open の追加)は、どちらも cmd_scale と 2 つの config 読み取りに触れていない。
現状固定テストが薄い
cmd_scale を呼ぶテストは 4 か所しかない。
| 場所 |
何を固定しているか |
tests/commands/test_container_up_order.py:257 |
グループ不一致で 1 を返す |
tests/commands/test_container_up_order.py:290 |
_build_scaled_override の例外で 1 を返す |
tests/commands/test_container_context.py:254 |
context の伝播 |
tests/cli/test_project_dispatch.py:362,366 |
dispatch の伝播(cmd_scale は差し替え) |
正常系の手順(up -d --no-recreate のコマンド列・bao token・./deploy の順序)を固定するテストは無い(grep -rn "no-recreate" tests/ は 0 件)。cmd_up には順序を固定する tests/commands/test_container_up_order.py がある。
修正レイヤー
現象レイヤー: lib/devbase/commands/container.py(cmd_scale の 86 行と、_resolve_dev_service / _read_compose_services の重複)。
修正レイヤー: devbase が docker compose を呼ぶ共通経路(lib/devbase/utils/docker.py の docker_compose() と compose_env())と、その適用範囲を定める docs/specifications/compose-profiles.md の仕様。
cmd_scale が長いことと 2 関数が重複していることは、どちらも共通経路を通さずに自前で subprocess.run と docker compose config を書いていることの現れである。関数を分割しても共通経路を通さなければ、同じ食い違いが残る。
採る手: 統合(consolidate_duplication)。Compose の呼び出しを共通経路へ寄せてから、段階を抽出する。
順序: 仕様(scale を共通経路の対象にするか決める)→ 共通経路へ寄せる → 現状固定テストを足す → 関数を分ける。
直さないと何が起きるか
scale の手順を変えるとき(別の起動オプションや profiles への対応を足すとき)に、cmd_up と cmd_scale の片方だけを直す食い違いが起きやすい。config の読み取りの契約(環境・失敗の扱い)を変えるときも 2 か所を揃える必要がある。加えて、確定仕様が約束している COMPOSE_PROFILES の無効化が scale では成り立たないまま残る。
決めること
devbase scale の Compose 呼び出しを共通経路へ寄せるか、それとも仕様の「devbase 経由の操作には効かない」を scale 除外込みへ書き直すか。決め方によって、抽出した後の関数の境界が変わる
由来
PR #191(issue #189)。cmd_scale は kiro の提案 R2-001(major)、config 読み取りの重複は codex の提案(minor、しきい値未満で見送り)。
何を見つけたか
lib/devbase/commands/container.pyに、構造改善の候補が 2 つある。cmd_scale(1596-1690、本体 86 行)[1/5]project.ymlのscale書き換え・[2/5]ボリューム・[2.5/5]network・[3/5]構成生成・[4/5]--no-recreateの起動・[5/5]ready 待ち・bao token・deployフック・完了ログを 1 関数で通しで持つ。cmd_upは同種の本体を_run_deploy_pipeline(1254-、[1/6]〜[5/6]と[1.5/6])へ抽出済みで、scaleだけ段階に名前が無い_resolve_dev_service(1789) /_read_compose_services(1967)docker compose config --format jsonの実行・compose_env()の適用・終了コードの判定・servicesの取り出しを持つ。不正 JSON のときだけ前者はNoneを返し、後者は例外を伝播する振る舞いの側にも食い違いがある
cmd_scaleは Compose を共通経路(lib/devbase/utils/docker.pyのdocker_compose())を通さずに直接呼ぶため、compose_env()が適用されない。compose_env()を通る場所はutils/docker.pyのdocker_compose()、container.pyの_compose_run/_resolve_dev_service/_read_compose_services、editor/opener.pyである。cmd_scaleはこの一覧に無い。確定仕様
docs/specifications/compose-profiles.mdは、同じ文書の中で相反することを書いている。cmd_scaleが直接呼ぶdocker compose -f <生成物> up -d --no-recreateはこの対象に含めない。プロファイルの入口ではないためである」COMPOSE_PROFILESを端末や.envに置いても devbase 経由の操作には効かない。素のdocker composeには従来どおり効く」devbase scaleは devbase 経由の操作であり、2 つ目の約束はcmd_scaleでは成り立たない。端末または.envにCOMPOSE_PROFILESを置いた状態でdevbase scaleを打つと、その環境が子プロセスへそのまま渡る。サービスの指定も無いため、プロファイルのサービスが起動の対象に入りうる。実害の観測はまだ無い。 確定仕様の約束と実装が食い違っていることまでが分かっている。
なぜこの変更の範囲外だったのか
PR #191 は #189(Compose の profiles)の実装で、
cmd_scaleには手を入れていない。境界は「依頼範囲外のリファクタリングを行わない」と定め、devbase scaleの直接の Compose 呼び出しも「含まない」に挙げていた(現在の所在はdocs/specifications/compose-profiles.md)。config 読み取りの 2 関数は、PR #191 ではenv=compose_env()を足しただけである。v3.6.0 の
container.pyへの変更(PR #207 の_build_single_imageへの名前検証の追加、PR #199 のdevbase openの追加)は、どちらもcmd_scaleと 2 つの config 読み取りに触れていない。現状固定テストが薄い
cmd_scaleを呼ぶテストは 4 か所しかない。tests/commands/test_container_up_order.py:257tests/commands/test_container_up_order.py:290_build_scaled_overrideの例外で 1 を返すtests/commands/test_container_context.py:254tests/cli/test_project_dispatch.py:362,366cmd_scaleは差し替え)正常系の手順(
up -d --no-recreateのコマンド列・bao token・./deployの順序)を固定するテストは無い(grep -rn "no-recreate" tests/は 0 件)。cmd_upには順序を固定するtests/commands/test_container_up_order.pyがある。修正レイヤー
現象レイヤー:
lib/devbase/commands/container.py(cmd_scaleの 86 行と、_resolve_dev_service/_read_compose_servicesの重複)。修正レイヤー: devbase が
docker composeを呼ぶ共通経路(lib/devbase/utils/docker.pyのdocker_compose()とcompose_env())と、その適用範囲を定めるdocs/specifications/compose-profiles.mdの仕様。cmd_scaleが長いことと 2 関数が重複していることは、どちらも共通経路を通さずに自前でsubprocess.runとdocker compose configを書いていることの現れである。関数を分割しても共通経路を通さなければ、同じ食い違いが残る。採る手: 統合(
consolidate_duplication)。Compose の呼び出しを共通経路へ寄せてから、段階を抽出する。順序: 仕様(
scaleを共通経路の対象にするか決める)→ 共通経路へ寄せる → 現状固定テストを足す → 関数を分ける。直さないと何が起きるか
scaleの手順を変えるとき(別の起動オプションや profiles への対応を足すとき)に、cmd_upとcmd_scaleの片方だけを直す食い違いが起きやすい。config の読み取りの契約(環境・失敗の扱い)を変えるときも 2 か所を揃える必要がある。加えて、確定仕様が約束しているCOMPOSE_PROFILESの無効化がscaleでは成り立たないまま残る。決めること
devbase scaleの Compose 呼び出しを共通経路へ寄せるか、それとも仕様の「devbase 経由の操作には効かない」をscale除外込みへ書き直すか。決め方によって、抽出した後の関数の境界が変わる由来
PR #191(issue #189)。
cmd_scaleは kiro の提案 R2-001(major)、config 読み取りの重複は codex の提案(minor、しきい値未満で見送り)。