refactor(PLAN65): devbase scale と login の Compose 呼び出しを共通経路へ寄せる (#192) - #231
Conversation
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
改修計画 — devbasex/devbase #231
ラウンド 1(実装 codex / レビュー agy / kiro)R1-001 —
|
| 兆候・経路 | 手法・階層 | 重要度 | 提案元 | 状態 | コミット |
|---|---|---|---|---|---|
| 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
構造改善(cross-refactoring): 提案ラウンド 1 を適用せずに止めた
|
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 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
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 1 | agy | APPROVE
承認済みの設計(issues/PLAN65_scale-compose-path-design.md)および実装計画(issues/PLAN65_scale-compose-path-impl1.md)のスコープに準拠しており、受け入れ条件を満たしていることを確認しました。修正を要する指摘事項はありません。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 cross-review | round 2 | codex | APPROVE
設計の1本目の範囲で新たな修正指摘はありません。関連テスト123件が成功(実Dockerでの検証は対象外)。
takemi-ohama
left a comment
There was a problem hiding this comment.
🤖 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 本目の範囲)に踏み込む指摘は出さない。
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。release/v3.7.0)振る舞いの変更(承認済み): 端末や
.envにCOMPOSE_PROFILESを置いている人のdevbase scaleは、プロファイルのサービスを起動しなくなる。プロファイルを持たないプロジェクトでは起動の対象の集合は変わらない。
関連 Issue
変更点
コミットは設計の順序表(仕様 → 共通経路へ寄せる → 現状固定テスト)のとおりに並べた。
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を足した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)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を受ける形にした(コマンド列の固定は変えていない)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 は現状固定テストのため、書いた時点で緑であることを確かめた。
検査で足したもの(構造改善・実装レビュー)
/ndf:cross-refactoringのテスト整備ラウンドで現状固定テストを 3 件足した(8cb23d1/5376d83。lib/の本体は変えていない)cmd_scale: 一部の./deployが失敗しても残りを実行して 0 を返す経路 /project_nameを明示したときの経路cmd_login: 引数を省いた既定の呼び出し(index='1'、context=None)cmd_scaleの extract_method(major)は、設計が 2 本目へ割り当てた範囲のため適用していない(理由: refactor(PLAN65): devbase scale と login の Compose 呼び出しを共通経路へ寄せる (#192) #231 (comment) 、改修計画: refactor(PLAN65): devbase scale と login の Compose 呼び出しを共通経路へ寄せる (#192) #231 (comment) )/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=0uv run pytest -q(2be41c0)→2885 passed、exit=0(新設 22 件。失敗 0)— C-3 / C-4 / E-1uv 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-1uv 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=0python3 -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-5grep -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()を渡すgrep -rn "'config', '--format', 'json'" lib/→ 1 件(container.pyの_compose_config_services)grep -n "cmd_scale" docs/specifications/compose-profiles.md→ 除外の記述は無く、構成要素の表とscaleの段落だけに出るgit diff --name-only origin/release/v3.7.0..HEADにdocs/plugin-dev/compose-profiles.mdが出ないgrep -rn "no-recreate" tests/→ 3 件(変更前 0 件)範囲外と判断したもの(起票しない。いずれも変更前と同じ挙動で不具合ではない):
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