Skip to content

PLAN67: base イメージに shellcheck を入れる (#249) - #252

Merged
takemi-ohama merged 8 commits into
mainfrom
feature/plan67-shellcheck
Sep 24, 2026
Merged

takemi-ohama merged 8 commits into
mainfrom
feature/plan67-shellcheck

Conversation

@takemi-ohama

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

Copy link
Copy Markdown
Contributor

Summary

base イメージに shellcheck を入れ、base と、base を継ぐ派生イメージ(general / php など)のコンテナで Bash スクリプトの静的検査と、言語サーバによる Bash の診断を使えるようにします。

  • 確定仕様: docs/specifications/base-image-shellcheck.md(確定仕様化で新設)
  • 要求と受け入れ条件: issues/old/PLAN67_base-shellcheck.md(受け入れ条件 1〜9)
  • 設計: issues/old/PLAN67_base-shellcheck-design.md(決定 1〜5、設計 PR 設計(PLAN67): base イメージに shellcheck を入れる (#249) #250 でマージ済み)
  • 実装計画: issues/old/PLAN67_base-shellcheck-impl.md

Closes #249

変更点

ファイル 変更
containers/base/Dockerfile 1 つ目の RUN の 1 回目の apt-get install の一覧へ shellcheck を足した(決定 1)。版の確認の RUN へ && shellcheck --version を足し、入れ損ないをビルドで止める(決定 2)
tests/containers/test_base_dockerfile_shellcheck.py(新設) Docker を起動せずに上の 2 か所の形を固定する(決定 4。受け入れ条件 4・5)
docs/user/container-operations.md 「イメージの詳細」の表の base の行へ shellcheck、新しい小節「Bash の静的検査(base 以降)」
CHANGELOG.md [Unreleased] の ### Added
docs/specifications/base-image-shellcheck.md(新設) 確定仕様。置き場所・入れ損ないの止め方・版の扱い・派生イメージへの伝播・テスト観点(1d4c3b4)
issues/PLAN67_*.md → issues/old/ PLAN67 の 3 文書を移した(前例 PR #240 と同じ扱い。1d4c3b4)

反映には devbase build base --no-cache と、使っている派生イメージの建て直しが要ります。 CI はイメージを建てないため、イメージの中の受け入れ条件は手元(arm64)で建てたイメージから採りました。

Test plan

  • 受け入れ条件 1: 建てた base で shellcheck --version が exit=0、version: 0.11.0
  • 受け入れ条件 2: base の後に建て直した devbase-general / devbase-php で同じく exit=0
  • 受け入れ条件 3: echo $foo の 1 行に SC2154 / SC2086 を出し exit=1
  • 受け入れ条件 4・5: uv run --locked pytest tests/containers/test_base_dockerfile_shellcheck.py -q → 4 passed(Dockerfile の変更前は 2 failed / 2 passed を確認)。レビューの指摘で 1 回目の一覧の範囲を最初の ; までに絞った(5990a30)後も 4 passed / exit=0
  • 受け入れ条件 6: 変更前のイメージで新しく入るのは libnuma1 と shellcheck の 2 行。建てたイメージの Installed-Size の合計 25058 KB(≤ 30720)
  • 受け入れ条件 7: uv run --locked pytest tests/ -q → 3026 passed、exit=0
  • 受け入れ条件 8: devbase build base --no-cache(arm64)→ exit=0(3 分 4 秒)。devbase build general --no-cache / devbase build php --no-cache も exit=0
  • 受け入れ条件 9: 差分の目視(表・小節・CHANGELOG。表以外の 2 か所に devbase build base --no-cache が要ることを書いた)
  • CI が green(5990a30: Pytest 3.10 / 3.13・Python syntax 3.10〜3.12・Ruff lint・ShellCheck がすべて success、run 35935006429)
受け入れ条件 6: 変更前のイメージ(c477ec7764c1、2026-09-23 08:10:59 +0900)
$ docker run --rm --user root --entrypoint /bin/bash devbase-base:latest -c 'command -v shellcheck; echo has=$?; apt-get update -qq; apt-get install -s --no-install-recommends shellcheck | grep "^Inst"'
has=1
Inst libnuma1 (2.0.19-1build1 Ubuntu:26.04/resolute [arm64])
Inst shellcheck (0.11.0-2 Ubuntu:26.04/resolute [arm64])
受け入れ条件 1・3・6: 建てた base(a94591db20a3、2026-09-24 08:07:03 +0900)
$ docker run --rm --entrypoint /bin/bash devbase-base:latest -c 'shellcheck --version; echo exit=$?'
ShellCheck - shell script analysis tool
version: 0.11.0
license: GNU General Public License, version 3
website: https://www.shellcheck.net
exit=0

$ docker run --rm --entrypoint /bin/bash devbase-base:latest -c 'printf "#!/bin/bash\necho \$foo\n" > /tmp/t.sh; shellcheck /tmp/t.sh; echo exit=$?'

In /tmp/t.sh line 2:
echo $foo
     ^--^ SC2154 (warning): foo is referenced but not assigned.
     ^--^ SC2086 (info): Double quote to prevent globbing and word splitting.

Did you mean:
echo "$foo"

For more information:
  https://www.shellcheck.net/wiki/SC2154 -- foo is referenced but not assigned.
  https://www.shellcheck.net/wiki/SC2086 -- Double quote to prevent globbing ...
exit=1

$ docker run --rm --entrypoint /bin/bash devbase-base:latest -c 'dpkg-query -W -f="${Package} ${Installed-Size}\n" shellcheck libnuma1'
libnuma1 87
shellcheck 24971
(合計 25058)
受け入れ条件 2: 派生イメージ(general 6a8ecc270f0a / php e2f9b087fa63)
$ docker run --rm --entrypoint /bin/bash devbase-general:latest -c 'shellcheck --version; echo exit=$?'
version: 0.11.0
exit=0
$ docker run --rm --entrypoint /bin/bash devbase-php:latest -c 'shellcheck --version; echo exit=$?'
version: 0.11.0
exit=0

検査の結果

段階 コマンド 対象範囲 実行時刻 結果
限定的な検証 uv run --locked pytest tests/containers/test_base_dockerfile_shellcheck.py -q 新設のテスト 2026-09-24 08:49(5990a30) 4 passed / exit=0
全体テスト uv run --locked pytest tests/ -q 全体 2026-09-24 08:47(5990a30) 3026 passed / exit=0
静的解析 uvx ruff check tests/containers/test_base_dockerfile_shellcheck.py 変更した Python 2026-09-24 08:50 exit=0
継続的統合 CI(run 35935006429) 全ジョブ 2026-09-24(5990a30) すべて success
確定仕様化の後の全体テスト env -u DEVBASE_ROOT uv run --locked pytest tests/ -q 全体 2026-09-24(1d4c3b4) 3026 passed / exit=0
ビルド devbase build base/general/php --no-cache(arm64) イメージ 2026-09-24 08:07(b7556c8。以降 Dockerfile は不変) exit=0(上の Test plan)
  • 構造改善(cross-refactoring): テスト整備ラウンドが chore: base イメージに shellcheck を入れる(言語サーバによる Bash の診断に要る) #249 と関係しない既存の命令の現状固定テストを積んだため、ループを止めて 4 コミットを e379a6c で戻した(改修計画のコメントに記録)。本 PR の差分は実装の時点と同じ 5 ファイル
  • 実装レビュー(cross-review): 2 ラウンドで収束(round 1 agy=APPROVE / kiro=minor 1 件 → 5990a30 で修正、round 2 codex=APPROVE / kiro=APPROVE)。未解決のスレッド 0
  • カバレッジの閾値の設定はリポジトリに無い(pyproject.toml と .coveragerc に無し)
  • 既存の失敗: 手元の uvx ruff check .(ruff 0.16.8)は 995 件を出すが、main(83c2c3b)でも同数で、本 PR の差分のファイルには出ない。CI の Ruff lint は success

やらないこと

未確認のまま残ること

  • amd64 での建て直し(アーカイブに同じ版と依存があることまで確認済み)

配布の記録

段階: 承認待ち(検証のチャネルが無く、main へのマージが本番への配布にあたる。未実施)
版: 3.7.0 → 3.7.0 + main のマージコミット(版数は上げない。[Unreleased] に積み、タグは溜まった分をまとめて切る)
まとまり: PR #252

🤖 Generated with Claude Code

takemi-ohama and others added 2 commits September 24, 2026 08:08
- 1 つ目の RUN の 1 回目の apt-get install の一覧へ shellcheck を足す
- 版の確認の RUN へ shellcheck --version を足し、入れ損ないをビルドで止める
- Dockerfile の形を固定する test_base_dockerfile_shellcheck.py を新設
- 利用者向け文書(イメージの詳細の表・Bash の静的検査の小節)と CHANGELOG
- 実装計画 issues/PLAN67_base-shellcheck-impl.md

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Add characterization tests for the amd64 browser branch, offline npm global replacement by the default user, and both apt package sets. Leave the Dockerfile unchanged.

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

takemi-ohama commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor Author

2026-09-24 追記(進行側): この計画で適用した 4 コミット(a67ca10 / 38b1a52 / 8414aaa / f2f2c81)は e379a6c でまとめて戻した。 テスト整備ラウンドが --scope の Dockerfile をファイル単位で読み、#249(shellcheck の 2 か所)と関係しない既存の命令の現状固定テストを積んだため、ループをテスト整備ラウンド 2 の途中で止めた。提案ラウンドには入っていない。以下は記録として残す。

改修計画 — devbasex/devbase #252

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

  • 対象範囲: containers/base/Dockerfile, tests/containers
  • 着手前のテスト: uv run --locked pytest tests/containers -q

ラウンド 1(実装 codex)

R1-001 — containers/base/Dockerfile#BROWSER_PKG

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

なぜ: ブラウザの導入は amd64 のときだけ Google Chrome のリポジトリを足して BROWSER_PKG=google-chrome-stable にし、arm64 では chromium-browser のみになる分岐を持つ。この if [ "$arch" = "amd64" ] の分岐を固定するテストが無い。

手順: 1. 1 つ目の RUN 命令 (行継続を含む) を取り出す
2. if の中で amd64 のときだけ google-chrome のリポジトリ登録と BROWSER_PKG="google-chrome-stable" が現れることを assert する
3. apt-get install の一覧が chromium-browser と $BROWSER_PKG の両方を含み、arm64 でも chromium-browser が常に入ることを assert する

R1-002 — containers/base/Dockerfile#NPM_CONFIG_PREFIX

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

なぜ: tests/containers 全体の npm・NPM_CONFIG_PREFIX・install -g の検索と既存のイメージ検査を確認したが、一般ユーザーによるグローバルパッケージ更新の検証はない。Dockerfile が root で導入した npm パッケージを既定の非 root ユーザーが sudo なしで更新し、PATH 経由で実行できる振る舞いを固定する。OS の所有権・権限、npm、PATH のつなぎ目なので、文字列検査やスタブだけでは代替できない。

手順: 1. 現行 Dockerfile からビルドした base イメージを用意し、使い捨てコンテナを既定ユーザー、entrypoint=/bin/bash、ネットワーク無効、ホストのホームや認証情報をマウントしない条件で起動する。Docker または対象イメージが利用できない場合だけ理由付きで skip する。
2. コンテナ内に、依存と install script を持たず、bin の codex が決まった識別値を返すローカルの @openai/codex パッケージを作り、npm pack で tarball にする。既存の root 導入パッケージを置き換えるために同じ名前を使うが、ネットワークや実際の AI サービスには接続しない。
3. UID が非 0 であることを確認し、sudo や prefix・PATH・所有権の変更をせず、npm install -g --offline --ignore-scripts --no-audit --no-fund を実行する。続けて非対話シェルから codex を PATH 経由で起動する。
4. 現行イメージで得たインストールと起動の終了コード、および fixture の識別値を観測して期待値として記録する。npm の表示文言、内部の配置パス、chmod/chown の手順は固定しない。失敗を観測した場合も成功と決めつけず、現状の制約として明記する。
5. 同じ観測を assertion にして tests/containers/test_base_image_npm_globals.py に追加し、コンテナは必ず破棄する。

R1-003 — containers/base/Dockerfile#RUN apt-get install

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

なぜ: 1 つ目の RUN が apt-get install で入れるパッケージのうち固定されているのは #160 の 6 つと shellcheck だけで、locales / git / tmux / openssh-client / fonts-noto-cjk などの 1 回目の残りと、2 回目の docker-ce / terraform / gh / nodejs / chromium-browser は固定されていない。一覧を並べ替えたり分けたりすると、1 つ落ちても既存のテストは落ちない

手順: 1. コメント行を除いた Dockerfile の 1 つ目の RUN を行継続まで連結して取り出す
2. apt-get install の 1 回目と 2 回目の引数を、次の ; までの範囲でそれぞれ取り出し、オプション (- で始まる語) と行継続の \ を除いて語の集合にする
3. 1 回目の集合と 2 回目の集合を、現状の出力を実行して得た値とそれぞれ比較する ($BROWSER_PKG は語のまま集合に残す)

R1-004 — containers/base/Dockerfile#RUN aws-gcloud-uv-npm

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

なぜ: アーキテクチャの分岐は bao の RUN だけが固定されており、session-manager-plugin の case (amd64→ubuntu_64bit / arm64→ubuntu_arm64 / それ以外で exit 1) と gcloud の case (x86_64→x86_64 / aarch64→arm / それ以外で exit 1) は固定されていない。この RUN を分けたりまとめたりしたときに、片方の対応や未対応時の停止が欠けても検出できない

手順: 1. コメント行を除いた Dockerfile から session-manager-plugin を入れる RUN を行継続まで連結して取り出す
2. ssm_arch の case について、amd64) と arm64) の枝がそれぞれ現状の値を代入し、) の枝が exit 1 することを確かめる
3. gcloud_arch の case について、x86_64) と aarch64) の枝が現状の値を代入し、
) の枝が exit 1 することを確かめる
4. 取り出した値がダウンロード URL (${ssm_arch} / ${gcloud_arch}) で参照されていることを確かめる

R1-005 — containers/base/Dockerfile#RUN version-check

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

なぜ: 版の確認の RUN で固定されているのは shellcheck --version の 1 つだけで、gh / node / npm / aws / gcloud / session-manager-plugin の 6 つは固定されていない。この RUN を組み替えると、入れ損ないをビルドで止める確認が黙って欠けても既存のテストは落ちない

手順: 1. コメント行を除いた Dockerfile を RUN の命令単位に分け、gh --version を含む RUN をちょうど 1 つ取り出す
2. RUN を外した本文を && で分けて前後の空白を落とし、コマンドの集合を作る
3. その集合が現状の 7 つ (gh / node / npm / aws / gcloud / session-manager-plugin / shellcheck の --version) と等しいことを比較する。順序は仕様ではないので集合で比べる

ラウンド 2(実装 kiro)

R2-001 — containers/base/Dockerfile#agy

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

なぜ: agy のインストーラは、curl の失敗を bash の成功が覆い隠さないように、パイプに直結せずファイルへ落としてから実行し、最後にバイナリの実体を --version で確かめている(コメントに理由がある)。この失敗の検出経路はどのテストにも固定されていない。ユーザー用ツールの RUN を整理するときに、ほかの行(uv / claude)と同じ curl ... | bash の形へ揃えてしまうと検出できない

手順: 1. ユーザー用ツールを導入するRUN全体をDockerfileから取得し、専用の作業ディレクトリとHOME、PATH上の外部コマンドスタブを使って/bin/shで実行する。curlはURL別のローカルfixtureを返し、先行するuvとClaudeの導入は成功させる。
2. agyについて、取得が非0終了する場合、取得したインストーラが非0終了する場合、インストーラが0終了しても実行ファイルを生成しない場合を独立に実行する。実行失敗はfixtureスクリプト自身から発生させる。
3. 現行の終了コードと、後続のKiroダウンロードおよびPlaywright導入の成果が作られないことを観測して固定する。外部コマンドの代替は成果を専用ディレクトリへ記録し、実ネットワーク・sudo・ホストの清掃処理は実行しない。内部呼び出し順やエラーメッセージの全文は固定しない。

R2-002 — containers/base/Dockerfile#bao

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

なぜ: bao の RUN の case は amd64 / arm64 が選べることは test_both_architectures_are_selectable で固定されているが、未対応アーキテクチャで停止する枝 (*) echo ... exit 1) は固定されていない。ssm / gcloud の同種の error 枝は test_base_dockerfile_shellcheck.py の _case_branches で固定済みだが bao だけ欠けている。

手順: 1. _bao_run_block() を使い bao を入れる RUN の 1 命令分を取り出す
2. 行継続の \ を畳んでから、bao_arch の case を {パターン: 値} に写す
3. amd64 -> amd64、arm64 -> arm64 を確認する
4. *) の枝に exit 1 が含まれること、その直前に echo の停止メッセージがあることを確認する
5. 期待値は現行 Dockerfile を実行せず文言から読み取った現状値をそのまま置く

R2-003 — containers/base/Dockerfile#RUN user-config

兆候・経路 手法・階層 重要度 提案元 状態 コミット
normal unit — claude 未着手 0

なぜ: /.bashrc へ足す 2 行 (PATH と ai-cli-aliases.sh の source)、git の credential.helper、/.claude/settings.json の SessionStart フック(unset AWS_REGION)は、イメージ側の出力なのにどのテストにも固定されていない。test_entrypoint_ai_settings.py は仮の HOOKS 文字列を使っていて、Dockerfile が焼く中身は見ていない。フックの JSON はクォートが 3 重に入れ子になっていて、書き換えると壊れやすい

手順: 1. _run_blocks() から ~/.claude/settings.json を含む RUN をちょうど 1 つ取り出し、先頭の RUN を外す
2. tmp_path を HOME にして bash -c でその本文を実行する(ネットワークにも sudo にも依存しない)
3. $HOME/.bashrc の末尾 2 行が PATH の行と . /etc/devbase/ai-cli-aliases.sh であることを比べる
4. git config --global --get credential.helper が store を返すことを確かめる(HOME を差し替えた環境で実行する)
5. $HOME/.claude/settings.json を json.loads し、hooks.SessionStart[0].hooks[0] の type が command、command に unset AWS_REGION と $CLAUDE_ENV_FILE が含まれることを要点比較する

R2-004 — containers/base/Dockerfile#RUN user-setup

兆候・経路 手法・階層 重要度 提案元 状態 コミット
branch unit — claude 未着手 0

なぜ: ユーザー設定の RUN (groupadd / 条件付き useradd / usermod / sudoers) を固定するテストがない。if ! id -u $USERNAME の分岐で、既存ユーザーがいれば useradd を飛ばして usermod だけ行う。npm グループの GID は ARG NPM_GID=2000 に固定されていて、派生イメージ lfm が依存している。sudoers の 2 ファイルは 0440。どれも RUN を分けたりまとめたりするときに落としやすいが、どこにも固定されていない

手順: 1. 既存の _run_blocks() から useradd を含む RUN をちょうど 1 つ取り出す
2. ARG NPM_GID="2000" が Dockerfile にあり、その RUN に groupadd -g "$NPM_GID" npm があることを確かめる
3. 行継続を畳み、if ! id -u $USERNAME >/dev/null 2>&1; then から fi; までの本体が useradd だけで、usermod -aG users,docker,npm $USERNAME が if の外(fi の後)にあることを確かめる
4. /etc/sudoers.d/users と /etc/sudoers.d/$USERNAME の 2 ファイルが書かれ、両方が chmod 0440 の対象になっていることを集合で比べる
5. この RUN が npm 領域を作る RUN(install -d -m 2775)より前にあることを、_run_blocks() の並びで確かめる(npm グループが先に要る)

R2-005 — containers/base/Dockerfile#aws-cli

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

なぜ: AWS CLI v2 のダウンロードは ssm / gcloud と異なり case を持たず $(uname -m) を URL へ直接埋める正常経路である。この代表経路が固定されていないため、RUN を組み替えたときに arch の埋め込みが黙って欠けても検出できない。

手順: 1. ssm_arch / gcloud_arch を持つ RUN の 1 命令分を取り出す (test_base_dockerfile_shellcheck.py の _aws_gcloud_run と同じ判定)
2. awscli-exe-linux-$(uname -m).zip を含む URL 文字列があることを確認する
3. unzip -q /tmp/awscliv2.zip と /tmp/aws/install が続くことを確認する
4. AWS CLI の download には case (amd64/arm64 の分岐) が無いことを、この URL 断片の周辺に別の case ブロックが挟まらない形で確認する
5. 期待値は現行 Dockerfile の文言から読み取った現状値をそのまま置く

見送った項目

ラウンド 対象 兆候・経路 理由
1 containers/base/Dockerfile#gcloud branch 1 ラウンドの採用上限 5 件を超えた
1 containers/base/Dockerfile#gcloud error 1 ラウンドの採用上限 5 件を超えた
1 containers/base/Dockerfile#kirocli branch 1 ラウンドの採用上限 5 件を超えた
1 containers/base/Dockerfile#session-manager-plugin branch 1 ラウンドの採用上限 5 件を超えた
1 containers/base/Dockerfile#session-manager-plugin error 1 ラウンドの採用上限 5 件を超えた
2 containers/base/Dockerfile#bao branch 1 ラウンドの採用上限 5 件を超えた
2 containers/base/Dockerfile#claude-hooks normal 1 ラウンドの採用上限 5 件を超えた
2 containers/base/Dockerfile#user-setup branch 1 ラウンドの採用上限 5 件を超えた

takemi-ohama and others added 4 commits September 24, 2026 08:20
…-npm

session-manager-plugin と gcloud SDK のアーキテクチャ分岐を現状固定する。
ssm_arch の case (amd64→ubuntu_64bit / arm64→ubuntu_arm64 / *→exit 1) と
gcloud_arch の case (x86_64→x86_64 / aarch64→arm / *→exit 1) の各枝、および
選んだ値がダウンロード URL の ${ssm_arch} / ${gcloud_arch} で参照されることを
固定した。RUN を分けたりまとめたりしたときに片方の対応や未対応時の停止が
欠けても検出できる。対象コードは変更していない。

Item-Id: R1-004
Round: 1
Impl-Runtime: kiro
Impl-Model: default
版の確認の RUN のコマンド一式 (gh / node / npm / aws / gcloud /
session-manager-plugin / shellcheck の --version) を集合で固定する。
RUN を組み替えたときに確認が黙って欠けても検出できるようにする。

Item-Id: R1-005
Round: 1
Impl-Runtime: claude
Impl-Model: default
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Add characterization tests for R2-001, R2-002, and R2-005 without changing the Dockerfile.

Item-Id: R2-001
Round: 2
Impl-Runtime: codex
Impl-Model: default
cross-refactoring のテスト整備ラウンドが --scope(containers/base/Dockerfile)を
ファイル単位で読み、#249 と関係しない既存の命令(AWS CLI / gcloud / bao / agy /
ブラウザ / npm のグローバル)の現状固定テストを 4 コミット積んだ。shellcheck の
2 か所は既存のテストが固定しているため、4 コミットをまとめて戻す。

Revert f2f2c81 8414aaa 38b1a52 a67ca10

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

@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

PLAN67(#249)の要件に従って base イメージへの shellcheck 追加、ビルド時検証、Dockerfile 構造の回帰テスト、および文書と CHANGELOG の更新が反映されており、修正を要する問題はありません。

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

PR #252 の main に対する正味変更(Dockerfile への shellcheck 追加、版確認 RUN への shellcheck --version、新規テスト、docs/CHANGELOG)は目的と一貫しており、派生イメージの継承関係(lfm/snapshot は base を継がない)や rebuild の挙動記述も既存コードと整合する。head の revert(4 コミット)は既存コメントの cross-refactoring 計画どおりの意図的なスコープ判断で、そこは指摘しない。修正提案は新規テストの 1 件の締まりの弱さのみ。

Comment thread tests/containers/test_base_dockerfile_shellcheck.py
_first_apt_install が 2 回目の apt-get install の直前までを返しており、
locale-gen やリポジトリの設定に語が残るだけでも通ってしまっていた。

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

🔧 /ndf:fix サマリ | round 1 | commit 5990a30

対応件数: critical=0 / major=0 / minor=1(合計 1 件)
決着: 1 件 / 見送り: 0 件 / 却下: 0 件
CI: SUCCESS

@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

指定コミットの差分について、新規の修正指摘はありません。

@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

PLAN67 (#249) の base イメージへの shellcheck 追加。変更は 1 回目の apt-get install への 1 パッケージ追加と版確認 RUN への shellcheck --version 追加に限定され、目的と変更範囲が一貫している。文字列固定テスト 4 件は tests/containers 全体 (197 件) と併せて緑で、5990a30 の範囲絞り込み (_first_apt_install を最初の ; まで) も妥当。docs の rebuild vs --no-cache の説明も rebuild=build --expires=7 の実装と整合。スナップショットの R1/R2 の特性化テスト群はプラン注記どおり e379a6c で戻され #249 の範囲外。修正を要する critical/major/minor の指摘は見当たらず、APPROVE とする。

@takemi-ohama

Copy link
Copy Markdown
Contributor Author

🔧 /ndf:fix サマリ | commit (なし)

対応件数: critical=0 / major=0 / minor=0(合計 0 件)
決着: 0 件 / 見送り: 0 件 / 却下: 0 件
CI: NONE

@takemi-ohama
takemi-ohama marked this pull request as ready for review September 23, 2026 23:50
PLAN67 の要求・設計・実装計画を issues/old/ へ移し、置き場所・入れ損ないの
止め方・版の扱い・伝播の規則・テスト観点を base-image-shellcheck.md として
確定仕様にした。利用者向けの小節から新しい仕様へリンクする。

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

範囲外と判断し、#254(v3.7.0 のタグと GitHub Release が無い)として残した。

@takemi-ohama
takemi-ohama merged commit 676cba5 into main Sep 24, 2026
7 checks passed
@takemi-ohama

Copy link
Copy Markdown
Contributor Author

配布の記録

段階: 本番(検証のチャネルが無いため main へのマージが本番への配布にあたる。2026-09-24 に head 1d4c3b4 に対して承認、2026-09-24 09:42 JST にマージ。マージコミット 676cba5)
版: 3.7.0 → 3.7.0 + main@676cba5(版数は上げない。[Unreleased] に積み、タグは溜まった分をまとめて切る)
まとまり: PR #252

形: パッケージ・プラグイン(利用者が git pull --ff-only で取得する)
配布物の差分: 利用者の環境で振る舞いが変わるのは containers/base/Dockerfile の 1 ファイル(全体は 8 ファイル)
取り消しの手段: main で revert する PR をマージ → 利用者が pull 後に base と派生を建て直す。既に建て直したイメージからは建て直すまで shellcheck が消えない
完了の確認: git ls-remote origin refs/heads/main → 676cba5aae584e6f83e9f7bab6413c1a48ec263b(マージコミットと一致)

届き方:

git -C <devbase> pull --ff-only
devbase build base --no-cache
devbase build <使っている派生イメージ> --no-cache
devbase down && devbase up

タグ・GitHub Release(v3.7.0 の分を含む)は今回行わない(#254 に残す)。
次の工程: リリース後テスト

@takemi-ohama
takemi-ohama deleted the feature/plan67-shellcheck branch September 24, 2026 00:43
@takemi-ohama

takemi-ohama commented Sep 24, 2026 •

Copy link
Copy Markdown
Contributor Author

リリース後テスト

対象の版: 3.7.0 + main@676cba5(2026-09-24 09:42 JST にマージ)
導入経路: 主ディレクトリ(利用者と同じ clone)で git pull --ff-only → HEAD 676cba5 を確認 → devbase build base --no-cache → devbase build general --no-cache → devbase build php --no-cache(すべて exit=0、09:43:56〜09:47:25 JST)。派生 2 つのレイヤー列が新しい base のレイヤー列で始まることを docker image inspect で確認(general / php とも True)
環境: macOS / Docker Desktop(arm64)、Ubuntu 26.04

課題 受け入れ条件 実行したこと 実行時刻 結果
#249 1. 建てた base で shellcheck --version が exit=0、version: を出す docker run --rm --entrypoint /bin/bash devbase-base:latest -c 'shellcheck --version' 2026-09-24 09:47:43 合格 / exit=0、version: 0.11.0
#249 2. 派生 devbase-general / devbase-php でも同じコマンドが exit=0 同じコマンドを devbase-general:latest / devbase-php:latest で(どちらも base の建て直し後に建てたもの) 2026-09-24 09:47:43〜44 合格 / 2 つとも exit=0、version: 0.11.0
#249 3. echo $foo のスクリプトへ走らせると SC2086 を含み exit=1 base の中で printf '#!/bin/bash\necho $foo\n' > /tmp/t.sh; shellcheck /tmp/t.sh 2026-09-24 09:47:44 合格 / exit=1、SC2086 (info)(と SC2154)を出力
#249 6. 新しく入るのは shellcheck と libnuma1 の 2 パッケージ 変更前(fd5fa48 の containers/base)を docker build --no-cache で devbase-base:pre249 として建て、apt-get update 後に apt-get install -s --no-install-recommends shellcheck | grep '^Inst'。あわせて pre249 と新しい latest の dpkg-query -W の一覧を diff 2026-09-24 09:50:58 合格 / Inst はちょうど libnuma1・shellcheck の 2 行。dpkg の差分も libnuma1 と shellcheck の 2 件だけ(5.99GB → 6.02GB)
#242 amd64 での建て直し(#249 の受け入れ条件の外。#242 の範囲) — — 保留(理由: arm64 の手元しか無い。#242 で持ち越す)

受け入れ条件 4・5(Dockerfile の文字列検査)はマージ前の全体テストと CI で確認済みのため対象外。
ビルドログの ERROR: (gcloud.components.remove) ... not currently installed と agy の logging before google.Init は変更前から出る既存の出力で、ビルドは exit=0。

合否: 合格(受け入れ条件 1〜3・6 の 4 件を実施し全件合格。amd64 は #242 で保留)
起票したもの: なし

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.

chore: base イメージに shellcheck を入れる(言語サーバによる Bash の診断に要る)

1 participant