Skip to content

feat: 別ホストの Docker に dev コンテナを立ち上げ、VS Code もそこへ接続する (PLAN52) - #164

Merged
takemi-ohama merged 23 commits into
mainfrom
feature/remote-docker-context
Sep 13, 2026
Merged

takemi-ohama merged 23 commits into
mainfrom
feature/remote-docker-context

Conversation

@takemi-ohama

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

Copy link
Copy Markdown
Contributor

Pull Request

概要

projects/<name>/project.local.yml(gitignore 対象の個人・機材ごとの設定)に docker.context / docker.home / docker.gid を書くと、devbase up/down/ps/logs/login/scale/build/rebuild がその docker context の daemon を相手に動き、devbase up が開く VS Code がそのホストのコンテナへ attach します。設計は #163(マージ済み)、確定仕様は docs/specifications/remote-docker-context.md にあります。

関連 Issue

変更点

  • project/local_config.py(新設): project.local.yml の読み込みと検証。project.yml の docker: は移す案内付きで拒む
  • utils/docker_context.py(新設): context の解決(CLI > env > ファイル > 未指定)、docker context show との比較によるリモート判定(DOCKER_CONTEXT / DOCKER_HOST を外した環境で問い合わせ)、DOCKER_CONTEXT / DOCKER_GID の反映(冪等・機密注入後に再適用・操作前後で reset)、DOCKER_HOST の除去、gid の自動取得と .cache/docker-gid/<context> への控え
  • commands/container.py: --context を全 lifecycle コマンドへ。up / scale は接続先を確定し、リモート扱いでは自動スナップショットを飛ばす。プロジェクト切替時は切替元の機密を落としてから切替先の env を読む。_run_build は --context を引数で渡す
  • volume/bind_mounts.py(新設)+ compose.py: リモート扱いの生成で bind mount の ~ を docker.home で展開し、書き換えられない mount(~user・相対パス・長い書式の素の相対 source)を警告
  • bin/devbase: build --context NAME を先頭で抜き取り(空値は exit 2)、env exec --context NAME へ引数で渡す。docker buildx build / docker image inspect も env exec 経由に
  • commands/env.py + cli.py: env exec --context(プロジェクト直下の project.local.yml を読む)
  • editor/opener.py: 解決した context を settings.context に載せ、Remote-SSH ではフラット URI も提示。推測は docker が実際に使う context に合わせる
  • cross-refactoring による構造改善 8 件(cmd_up / open_editor / generate_scaled_compose / ensure_remote_gid の抽出、環境変数の形の判定の共通化)と現状固定テスト 5 件。改修計画: feat: 別ホストの Docker に dev コンテナを立ち上げ、VS Code もそこへ接続する (PLAN52) #164 (comment)
  • docs: project-yml.md(project.local.yml の節)、environment-variables.md(「リモート Docker」)、CLI リファレンス、CHANGELOG、確定仕様 docs/specifications/remote-docker-context.md。PLAN52 は issues/old/ へ

動作確認

検証結果

段階 コマンド 対象範囲 実行時刻 結果
限定的な検証 uv run pytest -q <PLAN52 の新規・変更テスト 8 ファイル> 変更箇所 2026-09-13 15:10 215 passed / exit=0
全体テスト uv run pytest -q 全体 2026-09-13 15:10 1921 passed / exit=0(着手時 1793)
静的解析 uvx ruff check --select=E9,F63,F7,F82 lib lib 2026-09-13 15:11 All checks passed! / exit=0
静的解析 uvx --from shellcheck-py shellcheck --severity=error bin/devbase bin/devbase 2026-09-13 15:11 exit=0
ビルド python3 -m compileall -q lib bin lib bin 2026-09-13 15:11 exit=0
結合 実 CLI: devbase ps --context desktop-linux / --context nope / env exec --context desktop-linux -- sh -c 'echo $DOCKER_CONTEXT' 手元の daemon 2026-09-13 従来どおり ps / docker のエラーで exit=1 / CTX=desktop-linux
結合 CI(syntax 3.10-3.12 / Ruff / ShellCheck) 全体 — GitHub Actions のキューで待機中(手元で同じ 3 検査は exit=0)

カバレッジツールの設定は無いため測定していない。

受け入れ条件: 49 件のうち 46 件をテストで確認(対応は docs/specifications/remote-docker-context.md の「テスト観点」)。
未検証の項目(リリース後テストで行う): 実 daemon での buildx リモートビルド、ローカル VS Code の settings.context での attach、Remote-SSH + リモート context のネスト URI。
既存の失敗: なし。
範囲外と判断したもの: devbase-samples の .gitignore に project.local.yml を足す → devbasex/devbase-samples#7 に起票。

  • ./bin/devbase --help が正常に動作する
  • 影響を受けるコマンドの主要シナリオを手動で確認した(上記「結合」)
  • ドキュメント (docs/, CHANGELOG.md) を更新した
  • CI が green である(キュー待ち)

補足

  • クロスレビュー: 5 ラウンド(codex / agy / kiro)、指摘 8 件をすべて反映、未解決 0
  • docker.home / docker.gid は CLI / env でファイルと別の context へ向けたときは使いません
  • リモートのボリュームのスナップショット、devbase status の複数 daemon 集約、DOCKER_HOST 直接指定は対象外

🤖 Generated with Claude Code

https://claude.ai/code/session_01MpE7aJufCtCacsm1Z3o83X

takemi-ohama and others added 10 commits September 13, 2026 12:36
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpE7aJufCtCacsm1Z3o83X
- --context を lifecycle サブコマンドと env exec に追加
- _dispatch_lifecycle の前後で接続先を reset、切替後に機密を読み直してから解決
- up / scale は接続先を確定して DOCKER_CONTEXT / DOCKER_GID を反映、リモート扱いでは自動スナップショットを飛ばす
- _inject_secrets の後に再適用、_run_build は --context を引数で渡す

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpE7aJufCtCacsm1Z3o83X
… env exec 経由にする (PLAN52 Task 5)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpE7aJufCtCacsm1Z3o83X
…る (PLAN52 Task 6)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MpE7aJufCtCacsm1Z3o83X
Add characterization tests for untracked child environments, explicit open-index boundaries, and remote settings propagation in cmd_scale.

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

takemi-ohama commented Sep 13, 2026 •

Copy link
Copy Markdown
Contributor Author

改修計画 — devbasex/devbase #164

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

  • 対象範囲: lib/devbase/utils/docker_context.py, lib/devbase/project/local_config.py, lib/devbase/volume/bind_mounts.py, lib/devbase/commands/container.py, lib/devbase/commands/env.py, lib/devbase/editor/opener.py, lib/devbase/volume/compose.py, bin/devbase, tests/utils, tests/project, tests/volume, tests/commands, tests/cli, tests/editor
  • 着手前のテスト: uv run pytest -q

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

R1-001 — lib/devbase/utils/docker_context.py#apply

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

なぜ: 既存テストは通常の apply/reapply/reset と、追跡中の対象がない状態での env exec を固定している。追跡中の対象がある状態で別の辞書へ track=False を適用し、その後 reapply/reset する経路は未固定。実行では子辞書だけに別 context/GID が適用され、親の追跡対象と最初の復元値が保持された。

手順: 1. DOCKER_CONTEXT・DOCKER_HOST・DOCKER_GID に初期値を持つ親辞書と、異なる値を持つ子辞書を用意する。
2. 親辞書へリモート DockerTarget A を通常適用し、子辞書へ別のリモート DockerTarget B を track=False で適用する。
3. 子辞書の context/GID が B の値となり DOCKER_HOST が除去され、無関係なキーが保持されることを固定する。
4. 親辞書の保護対象キーを別値で上書きして reapply し、A の context/GID と DOCKER_HOST 除去が復元されることを固定する。
5. reset 後の親辞書が最初の値に戻り、子辞書は手順3の状態を保つことを固定する。状態の後始末にも公開 reset を使い、private な状態や呼び出し回数は検証しない。

R1-002 — lib/devbase/utils/docker_context.py#ensure_remote_gid

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

なぜ: 既存の test_gid_probe_failure_raises_with_stderr_and_hint と test_gid_probe_non_integer_raises は非ゼロ終了と整数でない出力を固定しているが、runner 自体が FileNotFoundError / TimeoutExpired を送出する経路は固定していない。公開入口の実行ではどちらも DevbaseError となり、context 名と docker.gid の案内を含み、キャッシュを作成しなかった。

手順: 1. gid 未指定の DockerTarget と空の一時キャッシュディレクトリを用意する。
2. FileNotFoundError または subprocess.TimeoutExpired を送出する runner をパラメータ化して ensure_remote_gid へ渡す。
3. 実測した DevbaseError 型と、メッセージに対象 context 名・docker.gid が含まれることを固定する。文言全体は比較しない。
4. 対象 context のキャッシュファイルが作成されていないことを確認する。内部関数は直接呼ばない。

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

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

なぜ: 1<=open_index<=scale の範囲外 (0・scale 超過) を 1 へ倒す条件式は、範囲チェックの書き換えで壊れやすいが、この経路を固定したテストが無い (dispatch テストは引数伝播だけを見ており clamp を通っていない)。

手順: 1. open_index を明示指定して呼ぶ (env フォールバックを経由させない)
2. 0・scale (境界)・scale+1 (上限超過) を渡し、戻り値がそれぞれ 1・scale・1 になることを比較する
3. 検証は戻り値のみ (警告文言には結合しない)

R1-004 — lib/devbase/commands/container.py#_resolve_open_index

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

なぜ: open_index=None のとき env DEVBASE_OPEN_INDEX を int 変換し、非整数値を ValueError で握って 1 へ倒す分岐が固定されていない。env パースの書き換えで既定値の決まり方が変わっても検出できない。

手順: 1. monkeypatch で DEVBASE_OPEN_INDEX を未設定・整数文字列・非整数文字列に設定する
2. open_index=None・scale を十分大きくして呼ぶ
3. 未設定→1、'2'→2、'abc'→1 と戻り値を比較する (戻り値のみ検証)

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

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

なぜ: cmd_up や cmd_down などの各 lifecycle コマンドで context 伝播がテストされている一方、cmd_scale に追加された context 引数の解決・反映および構成生成へのリモート設定(docker_home, remote)伝播がテストされていない

手順: 1. project.local.yml にリモートの docker 設定(context, home, gid)を用意する
2. 外部呼び出しをモックした環境で cmd_scale を実行する
3. DOCKER_CONTEXT と DOCKER_GID が環境に反映され、構成生成処理に docker_home と remote=True が渡ることを検証する

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

R2-001 — lib/devbase/volume/compose.py#generate_scaled_compose

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

なぜ: 構成の読込、機密・認証環境の整備、サービス生成、bind mount の変換・警告、YAML 保存を1関数が担っている。特に末尾のリモート mount 処理は scaled_services・docker_home・remote だけに依存する独立した段階であり、構成生成の進行と詳細な警告方針が混在している。tests/volume/test_compose_remote_home.py が公開入口からローカルの保持、HOME 指定時の変換と相対パス警告、HOME 未指定時の保持と警告を検証している。

手順: 1. generate_scaled_compose 内の if docker_home / elif remote と両方の警告処理を、同じ compose.py の _prepare_remote_mounts(services, docker_home, remote) -> None にそのまま抽出する。
2. dev_excluded の除去後、scaled_config の組立て前という現在の位置を維持し、抽出関数への1回の呼び出しに置き換える。bind_mounts.expand_home 自体は変更しない。
3. docker_home の真偽判定が remote より優先すること、サービスの破壊的更新、警告対象の順序、文言とログレベルを維持する。新たな検証や条件変更は加えない。
4. tests/volume/test_compose_remote_home.py と tests/volume/test_bind_mounts.py、および tests/volume の既存生成テストを実行し、その後 uv run pytest -q を実行する。見積り65行はコメントを含む本体の移動、関数定義、説明、呼び出しと引数受け渡しを含む。

R2-002 — lib/devbase/utils/docker_context.py#ensure_remote_gid

兆候・経路 手法・階層 重要度 提案元 状態 コミット
long_method extract_method major codex / agy 採用 1

なぜ: 明示 GID・キャッシュの優先順位と永続化を管理する処理に、Docker 用環境の構築、subprocess 実行、失敗の例外変換、標準出力の整数化、GID 0 の警告が同居している。キャッシュ方針を追う際にもプローブの実装詳細を読む必要がある。tests/utils/test_docker_context.py には明示値、キャッシュ再利用・破損、非ゼロ終了、不正出力、実行例外、GID 0 の各経路を ensure_remote_gid 経由で確認するテストがある。

手順: 1. Docker 用環境のコピーから整数化と GID 0 の警告までを、同じモジュールの _probe_remote_gid(target, environ, runner) -> int に抽出する。
2. ensure_remote_gid には明示値とキャッシュによる早期 return、プローブ呼び出し、キャッシュの保存、保存後のログだけを残す。既存の _read_cached_gid と _gid_failure_message を再利用する。
3. コマンド引数、タイムアウト、DOCKER_HOST の除去、例外の型・文言・cause、警告とキャッシュ保存の順序をそのまま保つ。公開シグネチャと runner の注入口は変えない。
4. tests/utils/test_docker_context.py と tests/commands/test_container_context.py を実行し、その後 uv run pytest -q を実行する。見積り85行は本体の移動による追加・削除、抽出関数の定義・説明、呼び出しと引数受け渡しを含む。

R2-003 — lib/devbase/editor/opener.py#open_editor

兆候・経路 手法・階層 重要度 提案元 状態 コミット
long_method extract_method major kiro 採用 1

なぜ: IPC ソケットの拾い直しとログ・stale 警告・editor/display 解決・decide_action・skip 早期 return・container 名解決・ssh_host と docker_context の解決・workspace/uri_flag/uri 組み立て・直接 attach 案内・print_command/launch 分岐を 1 関数で行う。URI 構築と起動判定という別関心が混在する。

手順: 1. ssh_host + docker_context + workspace + uri_flag + uri の組み立てを _build_open_uri(ctx, env, container, workdir, workspace, docker_context) -> (uri, uri_flag, display, ...) へ抽出
2. IPC ソケット拾い直しと 2 種の警告ログを _prepare_ipc_env(env) -> (env, ctx) へ抽出
3. open_editor は「ctx 準備 → plan 判定 → skip 早期 return → uri 構築 → print/launch 分岐」に縮める
4. tests/editor/test_opener.py で launch/print_command/skip とネスト URI を退行確認

R2-004 — lib/devbase/commands/container.py#cmd_up

兆候・経路 手法・階層 重要度 提案元 状態 コミット
long_method extract_method major kiro 採用 1

なぜ: 1 関数が context 確定・env/hook/image の事前確認・snapshot・volume/network 準備・compose 生成と既存停止・起動・ready 待ち・不足 repo 報告・deploy スクリプト・window title・editor 起動と、6 段以上の異なる関心を通しで持つ。段ごとにテストできず、失敗経路 (DevbaseError / CalledProcessError) が末尾に集約されている。

手順: 1. [1/6]〜[5/6] の try 本体 (volume/network/compose 生成/down/up/wait) を _run_deploy_pipeline(project_name, scale, config, target, dev_service_name) として抽出
2. 事前確認 3 つ (_ensure_env_files/_run_pre_up_hook/_ensure_images) の並びを _run_pre_up_checks(config) -> bool へ抽出
3. cmd_up は「context 確定 → 事前確認 → snapshot → pipeline → 後処理 (report/deploy/title/editor)」の呼び出し列に縮める
4. 既存 tests/commands/test_container_up_order.py で段の順序と早期 return を確認

R2-005 — lib/devbase/commands/container.py#_choose_context

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

なぜ: cmd_down, cmd_login, cmd_build, cmd_rebuild, _compose_run の各所で docker_context.apply(_choose_context(context)) という同一の呼び出しが重複している。また _resolve_docker_target 内でも _choose_context を使わずに同等の設定取得処理が重複記述されている。

手順: 1. _resolve_docker_target 内の choice 取得を _choose_context(cli_context) の呼び出しに統一する。
2. docker_context.apply(_choose_context(context)) を集約する _apply_context(context=None) ヘルパーを定義する。
3. cmd_down, cmd_login, cmd_build, cmd_rebuild, _compose_run 内の重複呼び出しを _apply_context(context) に置き換える。
4. tests/commands/test_container_context.py を実行して確認する。

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

R3-001 — lib/devbase/volume/compose.py#generate_scaled_compose

兆候・経路 手法・階層 重要度 提案元 状態 コミット
long_method extract_method major agy / kiro 取り消し 1

なぜ: ラウンド2でリモートマウント処理 (_prepare_remote_mounts) が抽出されたものの、generate_scaled_compose は依然として150行超あり、複数の責務・フェーズが1つの関数に同居している。具体的には、(1) GCP認証関連の除外変数名の算出と _SecretNames の構築、(2) VS Code Server用ボリュームの決定 (_declares_target 判定とボリューム名解決)、(3) dev インスタンスごとの _drop_env_names 適用ループ、(4) サービス構築と設定ファイル出力、が直列に記述されている。各フェーズはインラインコメントで明確に区切られており、それぞれ小さなプライベート関数に抽出可能である。既存テスト (tests/volume/test_compose_secret_env.py, tests/volume/test_compose_gcp_auth.py, tests/volume/test_compose_vscode.py) により公開挙動が十分に保護されている。

手順: 1. GCP 除外集合と _SecretNames の構築 (auth_mode の取り出し・enumerated の収集・gcp_auth.dev_excluded_env_names・_SecretNames 生成) を _build_secret_names(dev_service, dev_environment, secret_env_names, global_env_names, project_env_names) -> tuple[_SecretNames, set] へ抽出
2. vscode volume の決定 (_declares_target 判定と get_vscode_volume_for 内包) を _resolve_vscode_volumes(dev_service, scale) -> list へ抽出
3. dev インスタンスの _drop_env_names ループを _drop_dev_excluded(scaled_services, dev_service_name, scale, dev_excluded) へ抽出
4. generate_scaled_compose を「読込 → dev/受信者/グループ解決 → _build_secret_names → _resolve_vscode_volumes → _build_scaled_services → _drop_dev_excluded → prepare_remote_mounts → assemble/write」の呼び出し列へ縮める
5. tests/volume/test_compose
*.py 群で退行確認

R3-002 — bin/devbase#cmd_build

兆候・経路 手法・階層 重要度 提案元 状態 コミット
duplication consolidate_duplication major codex / agy 取り消し 1

なぜ: bin/devbase の cmd_build 関数内において、通常ビルド (236-245行)、--no-cache 指定時 (203-212行)、--project-no-cache 指定時 (181-190行) の3つの実行経路で、compose_with_secrets docker compose build "${DEV_SERVICE_NAME:-dev}" の実行、成功・失敗メッセージの出力、および失敗時の exit 1 処理がほぼ完全に重複している。プロジェクトビルドの実行ロジックや成否判定の変更時に3箇所を同期して修正する必要があり、修正漏れのリスクがある。なお、既存の tests/cli/test_wrapper_secrets.py はスクリプト内の特定コマンド記述箇所数を固定しており、ハーネス側で cmd_build を差し替えるテストもあるため、重複集約にあたってはテスト側での呼び出し契約の確認と追従が必要となる。

手順: 1. tests/cli に実物の bin/devbase を一時ルートへ複製して実行する現状固定テストを先に追加する。PATH 上の uv を記録用スタブにして外部実行境界で引数を観測し、cmd_build と compose_with_secrets は実物を通す。通常・--no-cache・--project-no-cache(両フラグ併用を含む)について、base→project の順序、--context の伝達、引数の順序と重複、成功表示、base 失敗時の打ち切り、project 失敗時の表示と終了値1を固定する。
2. 同じ bin/devbase 内に build_project_image を抽出する。既存の compose_with_secrets docker compose build と結果表示、失敗時 exit 1 をそのまま移し、追加のビルド引数は "$@" で受け取る。モード別の進捗表示とbase側の判断・引数加工は各呼び出し元に残す。
3. 3箇所を共通関数呼び出しへ置き換える。project-no-cache 経路は現状どおり --no-cache を先頭へ追加し、それ以外の引数と既存の return/exit の位置・意味を保つ。
4. test_wrapper_secrets.py の3箇所固定と test_base_image_staleness.py の具体的コマンド文字列固定を、手順1の実行結果検査へ置き換える。機密注入経由という契約とモードごとの挙動は維持する。
5. 対象CLIテスト、bash -n bin/devbase、uv run pytest -q を実行する。事前実行の snapshot 復元テスト1件の失敗は別記し、構造変更の退行と区別する。見積220行は、本体の削除・抽出・3呼び出し元の書換え約60行、現状固定ハーネス/テスト追加と既存テスト変更約160行の合計。

R3-003 — lib/devbase/volume/compose.py#_mask_secret_environment

兆候・経路 手法・階層 重要度 提案元 状態 コミット
duplication consolidate_duplication minor agy / kiro 検証中 1

なぜ: lib/devbase/volume/compose.py 内の _mask_secret_environment (194-250行), _service_env_names (253-267行), _drop_env_names (269-305行), _apply_dev_environment (370-398行) の4関数において、Compose の service['environment'] の表現形式 (辞書形式 / KEY=VALUE のリスト形式 / その他) を判定し走査するロジックが重複している。特にリスト形式の各要素からキー名を取り出す処理 (item.split('=', 1)[0].strip()) は複数箇所に散在しており、_apply_dev_environment では .strip() が適用されていないなど微小な実装の乖離も発生している。環境変数定義の走査・キー抽出ロジックを一元化することで、Compose 仕様変更時の保守性を高め、解釈のブレを解消できる。既存の tests/volume/test_compose_dev_environment.py や tests/volume/test_compose_secret_env.py で各形式の挙動が網羅されている。

手順: 1. environment のキー名を列挙する走査を _iter_env_names(existing) へ 1 本化し、_service_env_names をその薄いラッパにする (item.split('=', 1)[0].strip() に統一)
2. dict / list / その他を判定して形態を返す小さな分類ヘルパ (_env_shape など) を導入し、_mask_secret_environment・_drop_env_names・apply_dev_environment の分岐頭をそれで揃える (各関数の書き込み方針・警告文言・戻り値は現状のまま)
3. 各関数を 1 手ずつ置き換え、その都度 tests/volume/test_compose
*.py を実行して退行が無いことを確認
4. list 形態のキー抽出の .strip() 有無の差は現状の _drop_env_names 側 (.strip() あり) に寄せ、変化を固定テストで確認

見送った項目

ラウンド 対象 兆候・経路 理由
1 lib/devbase/editor/opener.py#resolve_docker_context branch 1 ラウンドの採用上限 5 件を超えた
1 lib/devbase/project/local_config.py#load_project_local_config error 1 ラウンドの採用上限 5 件を超えた
1 lib/devbase/volume/bind_mounts.py#expand_home branch 1 ラウンドの採用上限 5 件を超えた
2 lib/devbase/volume/bind_mounts.py#collect_remote_warnings duplication 1 ラウンドの採用上限 5 件を超えた
2 lib/devbase/commands/container.py#_ensure_images long_method 1 ラウンドの採用上限 5 件を超えた
2 lib/devbase/commands/env.py#_update_source_metadata long_method 1 ラウンドの採用上限 5 件を超えた
3 lib/devbase/volume/compose.py#generate_scaled_compose long_method テストの期待する振る舞いが変わっています(tests/cli/test_base_image_staleness.py, tests/cli/test_wrapper_secrets.py)。構造改善では期待出力を変えません。振る舞いの変更は別の変更に分けてください
3 bin/devbase#cmd_build duplication テストの期待する振る舞いが変わっています(tests/cli/test_base_image_staleness.py, tests/cli/test_wrapper_secrets.py)。構造改善では期待出力を変えません。振る舞いの変更は別の変更に分けてください

takemi-ohama and others added 7 commits September 13, 2026 13:19
…ndex fallback

Add characterization tests for ensure_remote_gid runner exceptions and _resolve_open_index DEVBASE_OPEN_INDEX fallback.

Item-Id: R1-002
Round: 1
Impl-Runtime: agy
Impl-Model: default
振る舞いを変えずに 4 つの long_method から段階を抽出した。

- lib/devbase/volume/compose.py#generate_scaled_compose:
  リモート mount の展開・警告を _prepare_remote_mounts へ抽出
- lib/devbase/utils/docker_context.py#ensure_remote_gid:
  Docker 実行・例外変換・整数化・GID 0 警告を _probe_remote_gid へ抽出
- lib/devbase/editor/opener.py#open_editor:
  IPC ソケット準備を _prepare_ipc_env、URI 組立てを _build_open_uri へ抽出
- lib/devbase/commands/container.py#cmd_up:
  起動前チェックを _run_pre_up_checks、[1/6]〜[5/6] を _run_deploy_pipeline へ抽出

Item-Id: R2-001
Round: 2
Impl-Runtime: kiro
Impl-Model: default
…#_choose_context

docker_context.apply(_choose_context(context)) が cmd_down / cmd_login /
cmd_build / cmd_rebuild / _compose_run に同じ形で 5 回並んでいたのを
_apply_context(context) ヘルパーへ集約する。_resolve_docker_target で
_choose_context を使わず同じ設定取得 + choose_context を書き直していた箇所も
_choose_context(cli_context) の呼び出しへ統一する (resolve_target が settings
を要るため、ローカル設定の読み込みはそこに残る)。振る舞いは変えない。

Item-Id: R2-005
Round: 2
Impl-Runtime: claude
Impl-Model: default
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Extract secret-name preparation, VS Code volume resolution, and dev environment exclusions from generate_scaled_compose (R3-001). Consolidate project build execution and result handling, protected by real-wrapper characterization tests for build modes, context forwarding, argument order, and failures (R3-002).

Item-Id: R3-001
Round: 3
Impl-Runtime: codex
Impl-Model: default
…sk_secret_environment

Compose の service['environment'] の走査およびキー抽出処理を一元化。

- _env_shape による environment 形式判定の統一
- _env_item_name による list 項目からのキー抽出 (.strip() 適用) の一元化
- _iter_env_names による環境変数名列挙の一元化と _service_env_names の薄いラッパ化
- _mask_secret_environment, _drop_env_names, _apply_dev_environment の分岐統一

Item-Id: R3-003
Round: 3
Impl-Runtime: agy
Impl-Model: default

@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

リモート docker context の解決・反映(DOCKER_CONTEXT 経由)・gid 取得・bind mount の ~ 展開・エディタ attach への伝播まで、責務分割と特性化テストが揃っている。env exec --context の引数展開(空文脈で -- のみ、文脈名の空白は _parse_context で拒否)、リモート扱いでの自動スナップショット抑止、機密注入後の reapply による接続先の再適用(決定 13)も検証できた。設計・正確性・セキュリティ(外部コマンドへの文脈伝播、秘密のログ非出力)の観点で新たに修正を要する actionable な指摘は見当たらない。長メソッド/重複の構造的項目は既存の改修計画コメント(rf164)で追跡済みのため重複指摘しない。

@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 | REQUEST_CHANGES

PLAN52(リモート Docker context 対応)の全体的な実装およびテストともに非常に高い完成度ですが、opener.py におけるコンテキスト解決の重複実装・環境変数漏れ、および bin/devbase の空文字 context バリデーションについて改善を提案します。

Comment thread lib/devbase/editor/opener.py
Comment thread bin/devbase

@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

context 解決 (choose→resolve→apply/reapply/reset) の状態管理、DOCKER_HOST 除去とリモート判定、bind mount の ~ 展開、gid の取得・キャッシュ・失敗変換、env exec --context の子プロセス反映まで一貫しており、TUI での操作間リセットや機密注入後の再適用も含めて経路ごとにテストで固定されている。関連テスト (docker_context / bind_mounts / container_context / env_exec_context / opener) はローカルで 175 passed。構造面 (generate_scaled_compose / cmd_up などの長関数・重複) は既存の改修計画コメントで追跡済みのため重複指摘はしない。修正を要する正確性・セキュリティ・設計上の問題は見つからなかった。

@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 | REQUEST_CHANGES

修正が必要な指摘は 2 件です。

Comment thread lib/devbase/editor/opener.py Outdated
Comment thread lib/devbase/volume/bind_mounts.py Outdated

@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 3 | codex | REQUEST_CHANGES

仕様適合: 接続先の伝達に関する修正が 2 件あります。

Comment thread lib/devbase/commands/container.py
Comment thread lib/devbase/commands/env.py Outdated

@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 3 | agy | APPROVE

前ラウンドまでの指摘(エディタ推測の context 一致、長い書式 bind の相対パス警告、空 context の拒否、接続先確定の最適化)が適切に反映され、全テストの通過を確認しました。修正アクションを要する指摘事項はありません。

takemi-ohama and others added 2 commits September 13, 2026 14:48

@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 4 | kiro | REQUEST_CHANGES

uv run pytest -q を worktree で実行すると 3 failed / 1917 passed(PR 記載の「1900 passed」と不一致 = 現状 CI は red)。原因はコード側ではなく、新規テストの状態リーク(順序依存)です。個別実行では全 pass するため見落としやすい。

修正提案(インライン参照):

  • tests/commands/test_container_context.py: test_dispatch_clears_source_secrets_before_loading_target_env が DEVBASE_DOCKER_CONTEXT を実 os.environ へ残したまま終了し、tests/commands/test_container_up_order.py の 2 件と tests/commands/test_env_exec_context.py::test_env_exec_does_not_keep_module_state を巻き込みます。monkeypatch.setenv 化 + autouse _clean_env の teardown で当該 env を掃除してください。
  • tests/commands/test_container_up_order.py: up_harness に DOCKER_CONTEXT/DEVBASE_DOCKER_CONTEXT の delenv と docker_context.reset() を足すと順序非依存になり、漏れの二重防御になります。

再現: uv run pytest -q -p no:randomly tests/commands/test_container_context.py tests/commands/test_container_up_order.py → 2 failed。

Comment thread tests/commands/test_container_context.py
Comment thread tests/commands/test_container_up_order.py

@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 5 | codex | APPROVE

新規の修正指摘はありません。関連テスト 343 件と bash -n が成功しました(実機接続は未検証)。

@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 5 | kiro | APPROVE

ラウンド 1〜2 と R3-003 のリファクタリングは適用済みで、対象テスト 348 件が通過。R3-001 / R3-002 は「振る舞い変更を含む」として意図的に取り消し済み(別変更へ分離する判断で妥当)。新設モジュール(local_config.py / docker_context.py / bind_mounts.py)は責務が単一で検証・文書化も十分。bin/devbase の --context 抜き取りは空白・空値・スペース入り context 名を含めて期待どおり展開されることを確認。env exec の context 解決経路も設計コメントどおりで、bind mount の ~ 展開(短/長形式・:ro・named volume・~user・相対パス)と apply/reset の二重適用順序に不整合なし。修正を要する正確性・セキュリティ・保守性の問題は検出せず。

@takemi-ohama
takemi-ohama marked this pull request as ready for review September 13, 2026 06:29
@takemi-ohama
takemi-ohama merged commit b9e8fc0 into main Sep 13, 2026
5 checks passed
@takemi-ohama
takemi-ohama deleted the feature/remote-docker-context branch September 13, 2026 07:51
@takemi-ohama takemi-ohama mentioned this pull request Sep 13, 2026
3 tasks
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

リリース後テスト

対象の版: v3.3.0(2026-09-13 16:50 タグ、GitHub Release あり)
導入経路: git pull --ff-only origin main(install.sh の更新経路と同じ)→ devbase --version = 3.3.0
環境: 手元の Mac。手元の daemon と同じ socket を指す別名 context plan52-verify を作り「リモート扱い」の経路を通した

受け入れ条件 実行したこと 実行時刻 結果
project.local.yml の docker.context で全 docker 呼び出しが向く projects/adminer/project.local.yml に context: plan52-verify を置いて devbase up adminer --no-open 16:57 合格 / exit=0(docker context: plan52-verify (project.local.yml, リモート扱い)、コンテナ起動)
gid の自動取得と控え 同上 16:57 合格(docker run alpine:3 で取得、.cache/docker-gid/plan52-verify に控え、Docker Desktop の VM は 0 なので警告が出た。コンテナの GroupAdd=[0])
リモート扱いでは自動スナップショットを飛ばす 同上 16:57 合格(警告 1 行、スナップショット未作成)
ps / down が同じ context を通る devbase ps adminer / devbase down adminer 16:58 合格 / exit=0
DOCKER_HOST があると警告して外す DOCKER_HOST=tcp://127.0.0.1:1 devbase ps adminer 16:58 合格(警告 1 件、ps は context 経由で成功)
CLI --context がファイルより優先し、現在の context と同じならローカル扱い devbase up adminer --no-open --context desktop-linux(ファイルは plan52-verify のまま) 16:58 合格((--context, 現在の context と同じ)、自動スナップショット実行)
存在しない context は docker のエラーで非ゼロ devbase ps adminer --context nope 16:59 合格 / exit=1(context "nope": context not found)
実 daemon での buildx リモートビルド — — 保留(理由: 手元に別ホストの dockerd が無い。Mac → WSL2 の構成を組んだときに devbase build --context <ctx> で確かめる)
ローカル VS Code の settings.context での attach — — 保留(理由: 同上。devbase up --open でフラット URI に settings.context が付くことは単体テストで確認済み)
Remote-SSH + リモート context のネスト URI — — 保留(理由: 同上)

合否: 合格(10 件中 7 件を実施、3 件は保留。保留 3 件は実機の別ホスト構成が要る)
起票したもの: なし(devbase-samples の .gitignore は devbasex/devbase-samples#7 に起票済み)
後片付け: project.local.yml・context plan52-verify・gid の控えを削除、コンテナは down 済み

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.

feat: 別ホスト (Windows/WSL・別 PC・EC2) の Docker に dev コンテナを立ち上げ、VS Code もそこへ接続する

1 participant