Skip to content

refactor(PLAN65): devbase scale と login の Compose 呼び出しを共通経路へ寄せる (#192) - #231

Merged
takemi-ohama merged 8 commits into
release/v3.7.0from
feature/v3.7.0-scale-compose-path
Sep 22, 2026
Merged

takemi-ohama merged 8 commits into
release/v3.7.0from
feature/v3.7.0-scale-compose-path

Conversation

@takemi-ohama

@takemi-ohama takemi-ohama commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Pull Request

概要

devbase scale の Compose 呼び出しを共通経路(docker_compose() / compose_env())へ寄せ、
確定仕様の「COMPOSE_PROFILES を端末や .env に置いても devbase 経由の操作には効かない」を
例外なしの約束にする(設計の案 A・決定 1)。cmd_login の exec も同じ Pull Request で compose_env() を通す(決定 2)。

設計文書 issues/PLAN65_scale-compose-path-design.md の「実装の分け方」の 1 本目
(Compose の呼び出しを共通経路へ寄せる)である。2 本目(cmd_scale の段階を分ける。受け入れ条件 D-3・D-4)は
この Pull Request のマージ後に別に出す。計画は issues/PLAN65_scale-compose-path-impl1.md。

振る舞いの変更(承認済み): 端末や .env に COMPOSE_PROFILES を置いている人の devbase scale は、
プロファイルのサービスを起動しなくなる。プロファイルを持たないプロジェクトでは起動の対象の集合は変わらない。

関連 Issue

変更点

コミットは設計の順序表(仕様 → 共通経路へ寄せる → 現状固定テスト)のとおりに並べた。

  1. docs(PLAN65): 確定仕様 docs/specifications/compose-profiles.md を書き換えた。経路の表を 5 行
    (docker_compose / _compose_lines / _compose_run / cmd_login / _query_container_name)に畳み、
    cmd_scale の除外を「経路はこの表の 5 つだけ」へ置き換えた。コマンド列の表に scale / login / config --format json の行、
    up と down の節に scale の段落、運用とテスト観点に scale を足した
  2. fix(PLAN65): cmd_scale の [4/5] を docker_compose(['up', '-d', '--no-recreate', *services], compose_file=override_file, check=False) にした。
    services は生成の直後に default_services(override_file) で求める。docker_compose_up() は check=True 固定で
    CalledProcessError が except DevbaseError を素通りするため使わない(決定 3)。
    config --format json の読み取りを _compose_config_services() の 1 つにして docker_compose を通し、
    _read_compose_services を削除、_resolve_dev_service は名前と契約を保って載せ替えた(決定 9)
  3. fix(PLAN65): cmd_login に env=compose_env() を渡した(1 行。独立したコミット)。
    tests/utils/test_docker_profiles.py の棚卸しのコメントを変更後の 4 経路へ書き直し、_compose_lines と cmd_login のテストを並べた。
    tests/cli/test_login_command.py の差し替えの run(cmd) が env を受けられないため、**kwargs を受ける形にした(コマンド列の固定は変えていない)
  4. test(PLAN65): tests/commands/test_container_scale_order.py に正常系の手順(順序・範囲・停止しないこと)を固定するテストを足した。
    2 本目の構造変更の前の安全網である

テスト駆動の証跡: 2 と 3 は新しい振る舞いのテストを先に書き、変更前の実装で期待どおりの理由で落ちることを確かめてから寄せた
(cmd_scale の子プロセスの env が None・コマンド列にサービス名が無い・_compose_config_services が無い AttributeError・cmd_login の env が無い KeyError)。
4 は現状固定テストのため、書いた時点で緑であることを確かめた。

検査で足したもの(構造改善・実装レビュー)

  1. /ndf:cross-refactoring のテスト整備ラウンドで現状固定テストを 3 件足した(8cb23d1 / 5376d83。lib/ の本体は変えていない)
    • cmd_scale: 一部の ./deploy が失敗しても残りを実行して 0 を返す経路 / project_name を明示したときの経路
    • cmd_login: 引数を省いた既定の呼び出し(index='1'、context=None)
  2. 構造改善の提案ラウンドで 3 者が一致して挙げた cmd_scale の extract_method(major)は、設計が 2 本目へ割り当てた範囲のため適用していない(理由: refactor(PLAN65): devbase scale と login の Compose 呼び出しを共通経路へ寄せる (#192) #231 (comment) 、改修計画: refactor(PLAN65): devbase scale と login の Compose 呼び出しを共通経路へ寄せる (#192) #231 (comment) )
  3. /ndf:cross-review は 2 ラウンド(agy + kiro → codex + kiro)で 3 者とも APPROVE・指摘 0 件で収束した。未解決のスレッドは 0 件

Test plan

release/v3.7.0 を base にした Pull Request では CI が動かない(#216)。以下はすべて手元(作業ツリー、macOS)で実行した。
実環境のプロジェクトでの devbase up / scale / login は実行していない(コマンド列と subprocess.run を差し替えた水準で確かめた)。

  • 変更前の全件: uv run pytest -q(b112584 + 空コミット)→ 2863 passed、exit=0
  • 実装の直後の全件: uv run pytest -q(2be41c0)→ 2885 passed、exit=0(新設 22 件。失敗 0)— C-3 / C-4 / E-1
  • 検査の後の全件: uv run --locked pytest tests/ -q(5376d83、2026-09-22 22:33)→ 2889 passed in 132.99s、exit=0(現状固定テスト 4 件を追加。失敗 0)— C-3 / C-4 / E-1
  • 変更箇所のテスト: uv run pytest -q tests/commands/test_container_scale_order.py tests/utils/test_docker_profiles.py tests/cli/test_login_command.py tests/commands/test_container_up_order.py(5376d83)→ 56 passed、exit=0
  • CI と同じ静的検査: python3 -m compileall -q lib bin(5376d83)→ exit=0。shellcheck --severity=error install.sh は手元に shellcheck が無く未実行(install.sh はこの Pull Request で変えていない)
  • 新設のテスト: uv run pytest -q tests/commands/test_container_scale_order.py tests/utils/test_docker_profiles.py → exit=0 — B-1〜B-5 / C-1 / C-2 / D-2 / E-2 / E-3 / A-5
  • A-1: grep -rn "'docker', 'compose'\|\"docker\", \"compose\"" lib/ → 3 件(utils/docker.py:56 / container.py:266 の _compose_base_args / editor/opener.py:396)。
    _compose_base_args の呼び出し元 3 つ(_compose_run / _compose_lines / cmd_login)はすべて env=compose_env() を渡す
  • D-1: grep -rn "'config', '--format', 'json'" lib/ → 1 件(container.py の _compose_config_services)
  • A-2: grep -n "cmd_scale" docs/specifications/compose-profiles.md → 除外の記述は無く、構成要素の表と scale の段落だけに出る
  • A-4: git diff --name-only origin/release/v3.7.0..HEAD に docs/plugin-dev/compose-profiles.md が出ない
  • C-1: grep -rn "no-recreate" tests/ → 3 件(変更前 0 件)
  • D-3 / D-4 は 2 本目の Pull Request で満たす

範囲外と判断したもの(起票しない。いずれも変更前と同じ挙動で不具合ではない):

  • container.py の _SCALE_COMPOSE_FILE の有無で -f を選ぶ 1 行が _compose_run / cmd_down / cmd_login にある(構造改善の提案、minor)。しきい値 major 未満で、この Pull Request の差分の外
  • cmd_logs の follow / tail の引数生成を公開入口で固定するテストが無い(テスト整備の提案)。cmd_logs はこの Pull Request で変えていない

🤖 Generated with Claude Code

takemi-ohama and others added 7 commits September 22, 2026 21:22
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
確定仕様の「COMPOSE_PROFILES は devbase 経由の操作には効かない」を例外なしの約束にする
(設計の決定 1)。経路の表から cmd_scale の除外を削り、経路を 5 つに畳む。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- cmd_scale の [4/5] を docker_compose(['up', '-d', '--no-recreate', *services], check=False) にし、
  起動の対象を default_services(<生成物>) で明示する(設計の決定 1・3・4)
- config --format json を読む関数を _compose_config_services の 1 つにし、docker_compose を通す。
  _read_compose_services を削除し、_resolve_dev_service は名前と契約を保って載せ替える(決定 9)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
経路の表が devbase の Compose の起動を網羅するよう、cmd_login の 1 行を塞ぐ(設計の決定 2)。
棚卸しのコメントを変更後の 4 経路(_compose_run / _compose_lines / cmd_login /
_query_container_name)へ書き直し、_compose_lines と cmd_login のテストを並べる。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
cmd_scale の段階を分ける前の安全網。順序(グループの検査 → write_scale → ボリューム →
network → 生成 → default_services → 起動 → ready 待ち → bao → ./deploy)、bao と ./deploy の
範囲(current + 1 から new まで)、停止を呼ばないこと、受け付けない scale の扱いを固定する。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Add current-behavior tests for continuing deployment after an instance failure and logging into instance 1 when arguments are omitted. Production code is unchanged.

Item-Id: R1-001
Round: 1
Impl-Runtime: codex
Impl-Model: default
@takemi-ohama

takemi-ohama commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor Author

改修計画 — devbasex/devbase #231

/ndf:cross-refactoring が提案し、適用した改善項目の記録である。
理由と手順は提案の時点でしか残らないため、公開の直前に書き出している。

  • 対象範囲: lib/devbase/commands/container.py, tests/commands/test_container_scale_order.py, tests/utils/test_docker_profiles.py, tests/cli/test_login_command.py
  • 着手前のテスト: uv run pytest -q tests/commands tests/utils tests/cli

ラウンド 1(実装 codex / レビュー agy / kiro)

R1-001 — lib/devbase/commands/container.py#cmd_scale

兆候・経路 手法・階層 重要度 提案元 状態 コミット
error unit — codex / agy / kiro 採用 1

なぜ: cmd_scale の接続先確定 (_resolve_docker_target) が DevbaseError を投げると 'Scale failed' で 1 を返す早期 return 分岐がある。scale_harness は _resolve_docker_target を常に成功する DockerTarget へ差し替えており、この分岐に入る入力が無い。既存で固定された 'Scale failed' は try 内の default_services 失敗 (末尾の except DevbaseError) だけで、接続先確定の失敗はこれと別経路。

手順: 1. 一時プロジェクトを scale=1 とし、deploy ファイルを用意する。Docker・認証等の外部依存を代替し、deploy 処理は実実装を通す。
2. subprocess.run の代替で Compose の起動を成功させ、deploy の DEVBASE_INSTANCE_INDEX=2 だけ CalledProcessError、3 は成功にする。
3. 公開入口 cmd_scale(3) を実行し、戻り値と deploy 子プロセスに渡されたインスタンス番号を採取する。
4. 現状の終了コード 0 と、失敗した 2 に続いて 3 も実行される外部作用を固定する。内部メソッドの呼び出し回数やログ全文は比較しない。

R1-002 — lib/devbase/commands/container.py#cmd_login

兆候・経路 手法・階層 重要度 提案元 状態 コミット
normal unit — agy 採用 1

なぜ: 引数を省略したデフォルト呼び出し(index='1', context=None)の経路が固定されていない。既存の test_login_command は index='2', context='remote' の組み合わせのみを検証している。

手順: 1. 引数を省略して cmd_login() を呼び出す
2. _apply_context に context=None が渡ることを確認する
3. 実行される exec コマンドがインデックス 1(scaled の有無に応じて dev-1 または --index=1)を対象とすることを検証する

R1-003 — lib/devbase/commands/container.py#cmd_scale

兆候・経路 手法・階層 重要度 提案元 状態 コミット
branch unit — agy 検証中 1

なぜ: cmd_scale は project_name が None の場合に get_project_name() から取得する分岐と、明示的に渡された project_name を採用する分岐があるが、既存のテストは全て省略(None)された分岐のみを通り、明示的に指定された場合の分岐が固定されていない。

手順: 1. cmd_scale(2, project_name='custom-proj') を実行する
2. ensure_volumes、_build_scaled_override、_push_bao_token の呼び出し引数に指定したプロジェクト名が渡っていることを検証する

見送った項目

(なし)

…ds/container.py#cmd_scale

cmd_scale に明示的な project_name が渡された場合の分岐を固定する現状固定テストを追加。

Item-Id: R1-003
Round: 1
Impl-Runtime: agy
Impl-Model: default
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

構造改善(cross-refactoring): 提案ラウンド 1 を適用せずに止めた

  • 提案の担当 3 者(codex / agy / kiro)が一致して挙げた lib/devbase/commands/container.py#cmd_scale(long_method → extract_method、major)は適用していない。cmd_scale の段階を関数へ抽出するのは、設計(issues/PLAN65_scale-compose-path-design.md、承認済み)が決めたこの束の 2 本目の Pull Request の範囲であり、この Pull Request(1 本目)には入れない
  • kiro が挙げた lib/devbase/commands/container.py#cmd_down(duplication、minor)は、しきい値 major 未満で、この Pull Request の差分の外でもあるため採らない
  • テスト整備ラウンドの提案のうち lib/devbase/commands/container.py#cmd_logs(codex)は、この Pull Request の差分の外の入口なので採否の前に外した
  • 適用したのはテスト整備ラウンドの 3 件(現状固定テスト)だけで、lib/ の本体は変えていない。改修計画: refactor(PLAN65): devbase scale と login の Compose 呼び出しを共通経路へ寄せる (#192) #231 (comment)

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 cross-review | round 1 | kiro | APPROVE

設計 (PLAN65 案 A) が 1 本目へ割り当てた範囲 — Compose 起動の共通経路化 (cmd_scale の [4/5] / cmd_login の env / config --format json の _compose_config_services への集約) と現状固定テスト — に一致しており、compose_env() を通さない起動が lib/ から消えていること (grep 3 件・すべて _compose_base_args / docker_compose / opener 経由で env 付き)、up と同じく default_services(<生成物>) で起動対象を明示していること、失敗経路が check=False で except DevbaseError を素通りしないことを確認した。cmd_scale の段階抽出は設計が 2 本目へ割り当てた範囲のため指摘しない。追加の修正アクションは無い。

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 cross-review | round 1 | agy | APPROVE

承認済みの設計(issues/PLAN65_scale-compose-path-design.md)および実装計画(issues/PLAN65_scale-compose-path-impl1.md)のスコープに準拠しており、受け入れ条件を満たしていることを確認しました。修正を要する指摘事項はありません。

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 cross-review | round 2 | codex | APPROVE

設計の1本目の範囲で新たな修正指摘はありません。関連テスト123件が成功(実Dockerでの検証は対象外)。

@takemi-ohama takemi-ohama left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 cross-review | round 2 | kiro | APPROVE

設計 (issues/PLAN65_scale-compose-path-design.md) と計画 (impl1) の 1 本目の範囲に収まっており、修正を要する指摘はない。差分(cmd_scale [4/5] の docker_compose(..., check=False) 化・cmd_login の env=compose_env()・_read_compose_services → _compose_config_services への集約)は設計の決定 1/2/3/4/9 と一致し、_resolve_dev_service の名前と契約も保たれている。手元で uv run pytest tests/commands tests/utils tests/cli を実行し 1472 passed(新設テスト含む・失敗 0)を確認した。既存の scale/login テストは書き換えられておらず C-3/E-1 も満たす。extract_method(2 本目の範囲)に踏み込む指摘は出さない。

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