Skip to content

fix(build): devbase build <image> の単体ビルドを動くようにする - #144

Merged
takemi-ohama merged 5 commits into
mainfrom
fix/issue139-build-image-arg
Sep 2, 2026
Merged

takemi-ohama merged 5 commits into
mainfrom
fix/issue139-build-image-arg

Conversation

@takemi-ohama

Copy link
Copy Markdown
Contributor

概要

devbase build <image> が必ず失敗する不具合 (#139) を修正します。位置引数が剥がされないまま shell の cmd_build へ流れ、docker buildx build ... <context> <image> と PATH が 2 つになっていました。

設計は #143 でレビュー済みです。詳細は issues/PLAN49_build-image-argument.md を参照してください。

関連 Issue

変更点

1. wrapper が位置引数を Python へ振り分ける(bin/devbase)

build) dispatch のループで - 始まりでない引数を <image> として拾い、--expires と同じく run_python project build へ渡します。既定 / --no-cache / --project-no-cache は従来どおり shell の cmd_build(devbase-base の 2 段ビルド)のままです。

Python 側へ寄せた理由: 逆向き(Python が bash bin/devbase build <image> を呼ぶ)にすると、bin/devbase 冒頭の name 解決を通ってしまい、projects/bi-tools と containers/bi-tools が両方実在するため devbase project build bi-tools が別のものをビルドします。現在 project build の位置引数が name 解決の対象外であることで守られている挙動を壊さないためです。

2. 単体ビルドを抽出しタグとビルダを直す(lib/devbase/commands/container.py)

cmd_build の単体ビルド部分を _build_single_image() へ抽出し、次を直しました。

項目 修正前 修正後
タグ base:latest devbase-base:latest
コマンド docker build docker buildx build --load

接頭辞なしのタグは他の Dockerfile の FROM devbase-base:latest から解決できず、ビルドしても使われませんでした。containers/ 配下 10 件すべてが devbase-<name> 規約で参照されていることを確認済みです。devbase-base と接頭辞込みで渡されても二重に付けません。

これにより devbase build <image> / devbase project build <image> / devbase container build <image> が同じ実装へ届き、単体ビルドの docker 呼び出しは 1 箇所だけになります。

3. 回帰テスト(tests/cli/test_build_image_argument.py、新規 16 件)

bin/devbase は ShellCheck しか CI が見ておらず、引数解釈の回帰を防ぐテストがありませんでした。tests/cli/test_project_name_resolution.py と同じスタブ方式で bin/devbase を実プロセス起動し、振り分け先を固定しています。

4. 注記とドキュメントの追従

cli.py / container.py の「build は shell へ委譲する」という注記を実態(<image> と --expires は Python、それ以外は shell)へ更新し、docs/user/cli-reference/02-project.md に単体ビルドが作るタグと、プロジェクト名との衝突時の逃げ道を追記しました。

互換性

devbase project build <image> / devbase container build <image> が作るタグが <image>:latest から devbase-<image>:latest へ変わります。旧タグはリポジトリ内のどこからも参照されておらず(grep で確認済み)FROM devbase-* を解決できないため、移行措置は設けていません。

動作確認

段階 コマンド 結果
限定的な検証 uv run pytest tests/cli/test_build_image_argument.py -q 16 passed / exit=0
全体テスト uv run pytest tests/ -q 1740 passed / exit=0
静的解析 shellcheck --severity=error bin/devbase 指摘なし / exit=0
静的解析 ruff check --select=E9,F63,F7,F82 lib All checks passed / exit=0
構文検査 python -m compileall -q lib bin / bash -n bin/devbase exit=0
  • 影響を受けるコマンドの主要シナリオを確認した(build の 4 経路すべての振り分け先をテストで固定)
  • 必要に応じてドキュメント (docs/) を更新した
  • ローカルで ./bin/devbase --help が正常に動作する
  • CI が green である

未検証: 実 docker でのビルド。テストは subprocess.run をスタブ化しているため、実際に devbase-base:latest が作られ他 Dockerfile の FROM から解決できることは確認していません。リリース後テストで実施します。

スクリーンショット・ログ(任意)

# 修正前 (docker / compose をスタブ化)
$ devbase build base --no-cache
DOCKER:buildx build --load -t devbase-base:latest <ROOT>/containers/base base --no-cache
                                                  ^^^^^^^^^^^^^^^^^^^^^^ ^^^^  PATH が 2 つ
COMPOSE:docker compose build dev base --no-cache

# 修正後
$ devbase build base --no-cache
PYTHON:project build base --no-cache
  -> docker buildx build --load -t devbase-base:latest <ROOT>/containers/base --no-cache

補足

レビューでは特に次を見ていただきたいです。

  1. build) dispatch の振り分け条件。-* をフラグ、それ以外を <image> とする分類で漏れがないか
  2. _run_build(Python → shell)と新しい振り分け(shell → Python)で再帰しないこと。_run_build は位置引数を渡さないため shell 側へ入る、という前提が正しいか
  3. タグの二重付与を removeprefix('devbase-') で避けている点。containers/devbase-xxx のような名前が将来できたときの扱い

`devbase build <image>` は位置引数が剥がされないまま shell の cmd_build へ
流れ、`docker buildx build ... <context> <image>` と PATH が 2 つになって
必ず失敗していた (#139)。

- bin/devbase の build dispatch で位置引数を検出し、`--expires` と同じく
  Python の project build へ振り分ける。既定 / --no-cache /
  --project-no-cache は従来どおり shell の cmd_build のまま
- 単体ビルドを container._build_single_image() として抽出し、タグを
  devbase-<image>:latest に、コマンドを docker buildx build --load に揃える。
  接頭辞なしのタグは他 Dockerfile の FROM devbase-base:latest から解決できず、
  ビルドしても使われなかった
- 振り分けを Python 側へ寄せたのは、逆向きにすると wrapper 冒頭の name 解決を
  通ってしまい、containers/ と projects/ に同名がある場合 (bi-tools) に
  devbase project build が別のものをビルドするため
- bin/devbase の引数解釈に回帰テストを追加 (実プロセス起動 + スタブ)
- ルーティングの注記とドキュメントを実態へ追従

範囲外として起票: #141 (CI が pytest を実行していない)、
#142 (<image> と実在プロジェクト名の衝突)

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9tinzTAbF1LVEYvfUgzKx

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

修正を要する指摘はありません。

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

PR の設計と実装を確認しました。単体ビルドが正常に動作するようになり、引数振り分けの無限再帰も _run_build がフラグのみを渡すため発生しないことを確認しました(PR 補足 2)。また、Docker イメージ名は - から始まらないため、-* をフラグとする分類も安全です(PR 補足 1)。

1 点、PR 補足 3 で質問されていたタグの二重付与回避(removeprefix)について、ディレクトリ名とタグの対応が 1:1 にならず衝突する構造的なリスクがあるためインラインで指摘しました。修正をご検討ください。

Comment thread lib/devbase/commands/container.py Outdated
`removeprefix('devbase-')` を外し、タグを `containers/` 配下のディレクトリ名から
一意に導くようにした。接頭辞を剥がすと `containers/xxx` と `containers/devbase-xxx`
が同じ `devbase-xxx:latest` を取り合い、別ディレクトリなのに互いのイメージを
上書きする衝突リスクがあったため。

`devbase build devbase-base` のように接頭辞込みで渡した場合は、既存の存在確認で
`containers/devbase-base` を探して見つからず、探したパスを示して終了コード 1 で
終わる。黙って別のイメージを作るより明確な挙動になる。

テストは接頭辞の二重付与を禁じるものから、ディレクトリ名とタグの 1:1 対応
(`xxx` と `devbase-xxx` でタグが衝突しない)を固定するものへ書き換えた。
ドキュメントも同じ趣旨へ追従させた。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9tinzTAbF1LVEYvfUgzKx

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

実装仕様と同一 PR 内の実装計画を一致させてください。

Comment thread issues/PLAN49_build-image-argument.md 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 2 | gemini | APPROVE

PR の目的(単体ビルドの修正と Python / shell 間の適切な振り分け)が的確に実装されており、追加されたテストも AC をよく網羅しています。全体として非常にクリーンな変更です。

一点だけ、パス操作の堅牢性に関するマイナーな提案をインラインに残しました。

Comment thread lib/devbase/commands/container.py
takemi-ohama and others added 3 commits September 2, 2026 14:12
PR #144 のレビュー指摘 2 件に対応する。

- `_build_single_image` の先頭で `image` が `containers/` 配下の 1
  ディレクトリ名として妥当か検証する。`/` `\` `..` 空文字などを弾き、
  `DEVBASE_ROOT` の外を指すパスや Docker タグとして不正な名前を
  渡させない。弾いた場合は理由を logger.error に出して 1 を返し、
  docker は起動しない。
- `issues/PLAN49_build-image-argument.md` の Task 1 と決定 3 を、
  round 2 で確定した「タグはディレクトリ名から一意に導き `devbase-`
  接頭辞は剥がさない」仕様へ更新し、「受け入れ条件の変更」節へ
  旧記述の取り消し線付きで理由と日付を追記する。
- 不正な image 名の拒否と実在ディレクトリ名の受理をテストで固定する。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9tinzTAbF1LVEYvfUgzKx
レビューで方針が変わった際に、改訂前の説明 (接頭辞なしでは解決できない) と
改訂後の説明 (接頭辞を剥がさない) が並んで残っていた。1 つにまとめる。
振る舞いは変えない。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9tinzTAbF1LVEYvfUgzKx
- docs/developer/architecture.md: build の振り分けを現在の実装へ更新した。
  「build だけが Bash 側に残っている」という記述は、<image> と --expires が
  Python 経路になった今は誤り。引数ごとの層と実体、単体ビルドのタグ規約、
  期限判定の経路が再帰しない理由を表と本文で示す
- CHANGELOG.md: Unreleased の Fixed へ #139 を追加
- issues/PLAN49_build-image-argument.md を issues/old/ へ移動

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V9tinzTAbF1LVEYvfUgzKx
@takemi-ohama
takemi-ohama merged commit ea9eccd into main Sep 2, 2026
5 checks passed
@takemi-ohama
takemi-ohama deleted the fix/issue139-build-image-arg branch September 2, 2026 05:19
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.

fix: devbase build <image> が docker へ image 引数をそのまま渡して失敗する

1 participant