Skip to content

container.py: cmd_scale の長いメソッドと compose config 読み取りの重複を整理する #192

Description

@takemi-ohama

何を見つけたか

lib/devbase/commands/container.py に、構造改善の候補が 2 つある。

対象 兆候 内容
cmd_scale(1596-1690、本体 86 行) 長いメソッド 前提の検査・context の解決・[1/5] project.ymlscale 書き換え・[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.pydocker_compose())を通さずに直接呼ぶため、compose_env() が適用されない。

result = subprocess.run(
    ['docker', 'compose', '-f', str(override_file), 'up', '-d', '--no-recreate'],
    check=False
)

compose_env() を通る場所は utils/docker.pydocker_compose()container.py_compose_run / _resolve_dev_service / _read_compose_serviceseditor/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 では成り立たない。端末または .envCOMPOSE_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 #199devbase 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.pycmd_scale の 86 行と、_resolve_dev_service / _read_compose_services の重複)。

修正レイヤー: devbase が docker compose を呼ぶ共通経路(lib/devbase/utils/docker.pydocker_compose()compose_env())と、その適用範囲を定める docs/specifications/compose-profiles.md の仕様。

cmd_scale が長いことと 2 関数が重複していることは、どちらも共通経路を通さずに自前で subprocess.rundocker compose config を書いていることの現れである。関数を分割しても共通経路を通さなければ、同じ食い違いが残る。

採る手: 統合(consolidate_duplication)。Compose の呼び出しを共通経路へ寄せてから、段階を抽出する。

順序: 仕様(scale を共通経路の対象にするか決める)→ 共通経路へ寄せる → 現状固定テストを足す → 関数を分ける。

直さないと何が起きるか

scale の手順を変えるとき(別の起動オプションや profiles への対応を足すとき)に、cmd_upcmd_scale の片方だけを直す食い違いが起きやすい。config の読み取りの契約(環境・失敗の扱い)を変えるときも 2 か所を揃える必要がある。加えて、確定仕様が約束している COMPOSE_PROFILES の無効化が scale では成り立たないまま残る。

決めること

  • devbase scale の Compose 呼び出しを共通経路へ寄せるか、それとも仕様の「devbase 経由の操作には効かない」を scale 除外込みへ書き直すか。決め方によって、抽出した後の関数の境界が変わる

由来

PR #191(issue #189)。cmd_scale は kiro の提案 R2-001(major)、config 読み取りの重複は codex の提案(minor、しきい値未満で見送り)。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions