From 4646b8ad10d1d753ef3f43486db099684bc80866 Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Wed, 23 Sep 2026 14:57:55 +0900 Subject: [PATCH 1/2] =?UTF-8?q?docs(PLAN67):=20base=20=E3=82=A4=E3=83=A1?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=81=AB=20shellcheck=20=E3=82=92=E5=85=A5?= =?UTF-8?q?=E3=82=8C=E3=82=8B=E8=A6=81=E6=B1=82=E3=81=A8=E8=A8=AD=E8=A8=88?= =?UTF-8?q?=20(#249)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 (1M context) --- issues/PLAN67_base-shellcheck-design.md | 193 ++++++++++++++++++++++++ issues/PLAN67_base-shellcheck.md | 172 +++++++++++++++++++++ 2 files changed, 365 insertions(+) create mode 100644 issues/PLAN67_base-shellcheck-design.md create mode 100644 issues/PLAN67_base-shellcheck.md diff --git a/issues/PLAN67_base-shellcheck-design.md b/issues/PLAN67_base-shellcheck-design.md new file mode 100644 index 00000000..d49aa64a --- /dev/null +++ b/issues/PLAN67_base-shellcheck-design.md @@ -0,0 +1,193 @@ +# PLAN67: base イメージに shellcheck を入れる の設計 + +要求と受け入れ条件は [PLAN67_base-shellcheck.md](PLAN67_base-shellcheck.md) にある。 +この文書は「どう作るか」だけを扱う。 + +## 機能一覧 + +| # | 機能 | 誰が使うか | +| --- | --- | --- | +| F1 | base とその派生イメージのコンテナで、`shellcheck` で Bash スクリプトを検査する | コンテナの中で Bash を書く利用者と、shellcheck を呼ぶ言語サーバ(bash-language-server) | +| F2 | shellcheck が入っていないイメージを、ビルドの時点で止める | base を建てる devbase の開発者・利用者 | +| F3 | 上の 2 つを回帰テストで固定し、利用者向け文書と CHANGELOG を合わせる | devbase の開発者・利用者 | + +## 構成要素 + +| 要素 | 変更 | 責務 | +| --- | --- | --- | +| `containers/base/Dockerfile` の 1 つ目の `RUN` の 1 回目の `apt-get install` | 変える | `poppler-utils` の行の後へ、理由のコメントと `shellcheck` を足す | +| `containers/base/Dockerfile` の版の確認の `RUN` | 変える | `&&` の連なりの末尾へ `shellcheck --version` を足す。入っていなければビルドをここで止める | +| `tests/containers/test_base_dockerfile_shellcheck.py`(新設) | 足す | Docker を起動せずに、上の 2 か所の**形**を固定する | +| `docs/user/container-operations.md` | 変える | 「文書を扱う道具も base に入っています」の段の後へ、shellcheck の 1 段を足す。反映の注記(`devbase build base --no-cache` と派生イメージの建て直し)は既存の引用を共有させる | +| `CHANGELOG.md` | 変える | `[Unreleased]` に `### Added` を立て、shellcheck を足したことと、**反映には `devbase build base --no-cache` が要る**ことを書く | + +次のものは変えない。 + +- 派生イメージの Dockerfile(base を継ぐ 7 つはすべて `FROM devbase-base:latest`) +- `containers/lfm` と `containers/snapshot`(base を継がない。決定 5) +- `.github/workflows/ci.yml`(CI の ShellCheck ジョブは runner の shellcheck を使い、コンテナを使わない) +- `tests/containers/test_base_image_font_matching.py`(決定 4) + +## 実測(2026-09-23 / arm64 の `devbase-base:latest`) + +同じイメージから作った一時コンテナ(`--rm --user root`)で `apt-get update` の後に測った。 +イメージは建て直していない。 + +| 項目 | 値 | +| --- | --- | +| 取得元 | `ports.ubuntu.com` の `resolute/universe`(標準のアーカイブ。リポジトリの追加は要らない) | +| 版 | `0.11.0-2`(`shellcheck --version` は `version: 0.11.0`) | +| 依存を含めて新しく入るパッケージ | **2**(`shellcheck` / `libnuma1`)。`libc6` / `libffi8` / `libgmp10` は既に入っている | +| `Installed-Size` | `shellcheck` 24971 KB(arm64)/ 22867 KB(amd64) | +| `/usr` の増分 | 25052 KB(`du -sk /usr` の前後) | +| 置き場所 | `/usr/bin/shellcheck` | +| 診断 | `echo $foo` の 1 行で `SC2154` / `SC2086` を出し、終了コード 1 | + +amd64 の値はアーカイブの `binary-amd64/Packages.gz` から読んだもので、建てて確かめてはいない。 + +## 入出力の契約 + +### `containers/base/Dockerfile` の差分の形 + +**1 つ目の `RUN` の 1 回目の `apt-get install`**: 一覧の最後の行(`poppler-utils ...;`)の +`;` を `\` に変え、その後へ足す。理由は決定 1。 + +```dockerfile + poppler-utils python3-pil python3-defusedxml python3-lxml \ + # Bash の静的検査 (#249)。bash-language-server は診断を shellcheck に任せており、 + # 無いとエラーも警告も出さずに診断が空になる。 + shellcheck; \ +``` + +**版の確認の `RUN`**: 末尾へ足す。理由は決定 2。 + +```dockerfile +RUN gh --version && node --version && npm --version && aws --version && gcloud --version && session-manager-plugin --version && shellcheck --version +``` + +この `RUN` は `USER ${USERNAME}` より前にあり root で走る。`/usr/bin/shellcheck` は `PATH` に +あるため、パスを書かずに呼べる。 + +## 処理の流れ + +ビルドの層と、この変更が触る位置。 + +```mermaid +graph TD + L1["RUN 1: apt(locales / git / fonts / poppler …)
+ docker / terraform / gh / node / chromium
★ 1 回目の一覧へ shellcheck を足す"] --> L2["RUN: ユーザーとグループ"] + L2 --> L3["RUN: aws / gcloud / uv / npm globals"] + L3 --> L4["RUN: bao"] + L4 --> L5["RUN: 版の確認 gh / node / npm / aws / gcloud / ssm
★ 末尾へ shellcheck --version を足す"] + L5 --> L6["USER ubuntu 以降: claude / agy / kiro / playwright / COPY 群"] + L6 --> D["派生イメージ 7 つ
FROM devbase-base:latest"] +``` + +**`L1` で入らなければ、`L5` で `shellcheck: command not found` となり、ビルドが終了コード 127 で +止まる。** 派生イメージは `L6` までの層をそのまま継ぐため、Dockerfile を変えずに入る。 + +## 非機能の実現方式 + +| 大項目 | 条件(受け入れ条件) | 実現方式 | +| --- | --- | --- | +| システム環境 | 2 パッケージ・30 MB 以下(6)。arm64 で建つ(8) | 標準のアーカイブの 1 パッケージだけを指定し、`--no-install-recommends` の既存の一覧へ入れる。層もリポジトリも増やさない | + +## 決定の記録 + +### 決定 1: shellcheck は、1 つ目の `RUN` の 1 回目の `apt-get install` の一覧へ足す + +shellcheck は標準のアーカイブ(`resolute/universe`)にあり、外部のリポジトリを要さない。 +1 回目の一覧は標準のアーカイブのパッケージを入れる場所で、PLAN63 の `poppler-utils` などと +同じ扱いになる。 + +**新しい `RUN` を立てる案は採らない。** 理由は PLAN63 の決定 4 と同じで、代償が 3 つある。 + +| 代償 | 内容 | +| --- | --- | +| 層が 1 つ増える | 派生イメージ 7 つがこの上に積む | +| `apt-get update` をもう 1 回走らせる | 1 つ目の `RUN` は最後にリストを消す | +| クリーンアップを書き写す | `apt-get clean` と `rm -rf` を 2 か所に持つ | + +この変更そのものが 1 つ目の `RUN` の文字列を変えるため、層を分けても分けなくても、この変更では +1 度建て直される。 + +**2 回目の一覧(`docker-ce` / `terraform` / `gh` / `nodejs` / `chromium-browser`)へ足す案も +採らない。** 2 回目は後から足したリポジトリのパッケージを入れる場所で、標準のアーカイブの +パッケージを混ぜると、一覧の分け方の意味が崩れる。 + +### 決定 2: 入れ損ないは、版の確認の `RUN` へ `shellcheck --version` を足して止める + +版の確認の `RUN` は、`gh` / `node` / `aws` などが入ったことをビルドの時点で確かめる既存の +仕組みである。そこへ 1 語足せば、shellcheck が無いイメージは建たない。**「イメージに入って +いること」を守るのはテストではなくビルドになる。** テストの側は、この 1 語が消えないことを +固定すればよい(決定 4)。 + +**`apt-get install` の終了コードに任せる案は採らない。** apt はパッケージが一覧から消えても +失敗しない。一覧の編集で `shellcheck` が落ちたときに止まるのは、版の確認の側だけである。 + +### 決定 3: 版は固定せず、Ubuntu のアーカイブが配る版を入れる + +アーカイブの版(`0.11.0-2`)で、#249 の目的である Bash の診断は満たせる(受け入れ条件 3)。 +`gh` / `terraform` / `nodejs` も版を固定しておらず、base の流儀に合う。 + +**上流の GitHub Releases から静的バイナリを取り、`bao` と同じく `ARG` で版を固定してチェック +サムで確かめる案は採らない。** `bao` を固定するのはサーバの版と揃える必要があるためで、 +shellcheck にはその制約が無い。版を上げるたびに `ARG` とチェックサムの手入れが要り、 +アーキテクチャの分岐も書くことになる。**`apt-get install shellcheck=0.11.0-2` と版を書く案も +採らない。** アーカイブが版を上げると、その版が消えてビルドが止まる。 + +### 決定 4: 回帰テストは Docker を使わない文字列検査だけにし、イメージの中は手で確かめる + +`test_base_dockerfile_shellcheck.py` を新設し、Dockerfile の文字列で次の 3 つを固定する。 + +| 固定すること | 受け入れ条件 | +| --- | --- | +| `shellcheck` が 1 つ目の `RUN` の 1 回目の `apt-get install` の一覧にある | 5 | +| `shellcheck` を入れる `RUN` が他に無く、`apt-get update` が 2 回のまま | 5 | +| 版の確認の `RUN` に `shellcheck --version` がある | 4 | + +イメージの中に入っていることは、決定 2 によりビルドが守る。受け入れ条件 1〜3・6 は、実装の +持ち場で建てたイメージから採って Pull Request 本文へ貼る(PLAN63 と同じ扱い)。 + +**`test_base_image_font_matching.py` の `EXPECTED_COMMANDS` へ `shellcheck: True` を足す案は +採らない。** あのテストは `/etc/fonts/local.conf` の有無で古いイメージを見分けて skip する。 +PLAN63 の後、この変更の前に建てた base は `local.conf` を持つが shellcheck を持たない。 +そのため、建て直していない全員の `pytest tests/` が赤くなる。赤の意味が「壊れている」と +「イメージが古い」で混ざる(PLAN63 の決定 6 が避けたこと)。 + +**shellcheck 用の Docker のテストを別に立て、shellcheck が無ければ skip する案も採らない。** +「無ければ skip」は「無い」を検査できず、入っているイメージでだけ通る検査になる。入っている +ことはビルドが保証しているため、足しても新しく捕まえるものが無い。 + +補助の関数は `test_base_dockerfile_fonts.py` から import せず、新しいファイルに持つ。 +対象はコメント行を除く `_statements` と、行継続をつなぐ `_run_blocks` の 2 つである。 +テストのファイルどうしを依存させない(`test_base_dockerfile_bao.py` も自前の `_statements` を持つ)。 + +### 決定 5: `containers/lfm` には入れない + +lfm は `FROM nvidia/cuda:...` で base を継がない。base からは `/usr/local` / `/usr/bin/gh` / +`/usr/bin/node` / `/opt` などを選んで `COPY` するだけで、`/usr/bin/shellcheck` は届かない。 + +#249 の受け入れ条件が挙げるのは「general / php など」の base を継ぐ派生イメージで、lfm で +Bash を書く用途は挙がっていない。入れるなら lfm 自身の `apt-get install` か `COPY` の一覧へ +足す別の変更になる。必要が出た時点で起票する。 + +## テスト設計 + +| 受け入れ条件 | 何で確かめるか | +| --- | --- | +| 1 | `devbase build base --no-cache` の後、`docker run --rm --entrypoint /bin/bash devbase-base:latest -c 'shellcheck --version; echo exit=$?'`。出力を Pull Request 本文へ貼る | +| 2 | base の後に `devbase-general` と `devbase-php` を建て直し、同じコマンドを走らせる。出力を Pull Request 本文へ貼る | +| 3 | 建てた base で `printf '#!/bin/bash\necho $foo\n' > /tmp/t.sh; shellcheck /tmp/t.sh; echo exit=$?`。`SC2086` と `exit=1` を見る | +| 4・5 | `test_base_dockerfile_shellcheck.py`(決定 4 の表) | +| 6 | 建てた base で `dpkg-query -W -f='${Installed-Size}\n' shellcheck libnuma1` の合計が 30720 以下。あわせて変更前のイメージで `dpkg -l libnuma1` が未導入であることを採り、新しく入るのが 2 つであることを示す | +| 7 | `uv run --locked pytest tests/ -q` | +| 8 | `devbase build base --no-cache`(arm64) | +| 9 | 差分の目視(`docs/user/container-operations.md` と `CHANGELOG.md`) | + +## 未確認のまま残ること + +| 項目 | 内容 | +| --- | --- | +| amd64 での建て直し | 手元は arm64 のみ。amd64 はアーカイブに同じ版があり依存も同じことまで確かめた。建てて確かめるのは amd64 の端末を使う人が建て直した時点になる | +| 言語サーバからの診断 | bash-language-server は範囲外。devbasex/ai-plugins#818 の設計が、コンテナの shellcheck を前提に進める | +| 利用者への周知 | 建て直すまで反映されないため、CHANGELOG と利用者向け文書に `devbase build base --no-cache` が要ることを書く。既に建てた人がいつ建て直すかは devbase の側から決められない | diff --git a/issues/PLAN67_base-shellcheck.md b/issues/PLAN67_base-shellcheck.md new file mode 100644 index 00000000..ff508ce1 --- /dev/null +++ b/issues/PLAN67_base-shellcheck.md @@ -0,0 +1,172 @@ +# PLAN67: base イメージに shellcheck を入れる + +対象 issue: devbasex/devbase#249 + +- ワークフローモード: `standard` + - 根拠: base イメージの本番の振る舞い(同梱するコマンド)を変える。base はすべての派生 + イメージとプロジェクトの土台で、変更は再ビルドした全員に届く(前例: PLAN63 / #160) +- ベースブランチ: `main`(`.ndf/worktree.json` に起点も本番のチャネルも宣言が無く、既定 + ブランチに落ちる) + +## 目的 + +- **base と、base から派生したイメージのコンテナで、`shellcheck` がそのまま使える。** + Bash スクリプトの静的検査を手元で走らせられ、shellcheck を内部で呼ぶ言語サーバ + (bash-language-server)が診断を返せる状態にする +- **shellcheck が入っていないイメージは建たない。** 入れ損ないをビルドの時点で止める + +## 影響 + +| 対象 | 影響 | +| --- | --- | +| 公開インタフェース | 変わらない(devbase の CLI の引数・環境変数・コマンドは増減しない) | +| データ | 変わらない | +| 既存の振る舞い | **変わる。** base とその派生イメージのコンテナの `PATH` に `shellcheck` が加わる。イメージを建て直すまでは変わらない。CHANGELOG では Added に書く | +| イメージのサイズ | +約 25 MB(`shellcheck` と、依存で新しく入る `libnuma1` の 2 パッケージ) | +| 利用者の操作 | **`devbase build base --no-cache` が要る。`devbase up` だけでは反映されない。** 派生イメージ(`containers/general` など)を使っているプロジェクトは、その派生イメージも建て直す。稼働中のコンテナは `devbase down` → `devbase up` で作り直す | + +## 前提 + +- **前提 1: 版は Ubuntu のアーカイブが配る版に任せ、固定しない。** 2026-09-23 の時点で + `resolute/universe` の版は `0.11.0-2`(arm64 / amd64 とも)。`gh` / `terraform` / `nodejs` と + 同じく、建てた時点のアーカイブの版が入る +- **前提 2: CI はこの変更を検査しない。** `.github/workflows/ci.yml` にイメージを建てるジョブは + 無い(ジョブは python-syntax / lint / shellcheck / pytest の 4 つ)。イメージの中でしか + 確かめられない受け入れ条件の証跡は、**手元で建てたイメージから採って Pull Request 本文へ載せる** +- **前提 3: 対象は `FROM devbase-base:latest` の派生イメージに限る。** `general` / `go` / + `latex` / `bi-tools` / `php` / `php85` / `trygroup` の 7 つがこれに当たり、base を建て直した + 後に建て直せば自動的に入る。`containers/lfm`(`FROM nvidia/cuda:...`)と `containers/snapshot` + (`FROM ubuntu:26.04`)は base を継がない。lfm は base から `/usr/local` などを選んで `COPY` + するだけで、`/usr/bin/shellcheck` は届かない + +## 対象範囲 + +含む: + +- `containers/base/Dockerfile` の 1 つ目の `RUN` の 1 回目の `apt-get install` の一覧への + `shellcheck` の追加 +- 同じ Dockerfile の版の確認の `RUN`(`gh --version && ... && session-manager-plugin --version`) + への `shellcheck --version` の追加 +- 回帰テスト(`tests/containers/`) +- 利用者向け文書(`docs/user/container-operations.md`)と CHANGELOG + +含まない: + +- bash-language-server の導入。Serena は自分で入れる。Claude Code の plugin LSP で要るかは + devbasex/ai-plugins#818 の設計で決める(#249 の範囲外) +- `bin/devbase` の既存の指摘の片付けと、CI の severity の変更(#247) +- CI の ShellCheck ジョブを base の shellcheck へ寄せること。CI の runner はコンテナを使わない +- `containers/lfm` と `containers/snapshot` への導入(前提 3) +- 版の固定(前提 1) +- 派生イメージの Dockerfile の変更。いずれも `FROM devbase-base:latest` のため不要 +- 新しい型・永続データ・画面・呼び出される約束の追加(そのためクラス図・ER 図・画面遷移図・ + API 仕様を作らない) + +## 前提とする取り決め + +| 項目 | 参照先 / 決めたこと | +| --- | --- | +| プロジェクト構造 | base イメージの構成物は `containers/base/` の直下に置く | +| コーディング規約 | `containers/base/Dockerfile` の既存の書き方に合わせる。追加の理由を直前のコメントに書く(PLAN63 の `poppler-utils` の行と同じ流儀) | +| テスト戦略 | `tests/containers/` の既存の流儀に合わせる。Docker に依存しない検査(Dockerfile の文字列)を既定にする(`test_base_dockerfile_fonts.py` / `test_base_dockerfile_bao.py`) | + +## 境界 + +| 区分 | 内容 | +| --- | --- | +| 常に行う | 手元で全体テスト、`devbase build base --no-cache` と、派生イメージを建て直しての確認 | +| 確認してから行う | 前提 3 の範囲(lfm を含めないこと)。設計 Pull Request の承認で確かめる | +| 行わない | bash-language-server の導入、#247 の片付け、CI の変更、版の固定 | + +## 実装計画 + +設計は [PLAN67_base-shellcheck-design.md](PLAN67_base-shellcheck-design.md)。 +**タスクへの分解は実装の持ち場で `/ndf:implementation-plan` が行う。** ここでは触る対象だけを挙げる。 + +### 修正対象 + +- `containers/base/Dockerfile` +- `tests/containers/test_base_dockerfile_shellcheck.py`(新設) +- `docs/user/container-operations.md` +- `CHANGELOG.md` + +### 切り戻し手順 + +- データの移行は無い。変わるのはイメージの中身だけである +- 戻すには次の 4 つを順に行う。 + 1. ブランチの revert + 2. `devbase build base --no-cache` + 3. 使っている派生イメージの建て直し + 4. 稼働中のコンテナの作り直し(`devbase down` → `devbase up`) +- **`devbase rebuild` はここでは使えない。** `devbase build --expires=7` のシノニムで、期限内なら + ビルドを飛ばす。コンテナも作り直さない + +## 受け入れ条件 + +**実測の基準**: 以下の「現状」は 2026-09-23 に手元の `devbase-base:latest`(Ubuntu 26.04.1 / +arm64、作成 2026-09-22T23:10:59Z)で採った。導入の結果は、同じイメージから作った一時コンテナへ +`apt-get install -y --no-install-recommends shellcheck` して採った。 + +### 使えること(#249 の受け入れ条件) + +- [ ] 1. 建てた base イメージで次のコマンドが終了コード 0 で終わり、`version:` の行を出す。 + 現状は `shellcheck` が `PATH` に無い + `docker run --rm --entrypoint /bin/bash devbase-base:latest -c 'shellcheck --version'` +- [ ] 2. 派生イメージ `devbase-general:latest` と `devbase-php:latest` でも、同じコマンドが + 終了コード 0 で終わる。どちらも base を建て直した後に建てたものを使う +- [ ] 3. **診断を返す。** 建てた base イメージの中で `echo $foo` の 1 行を持つ Bash スクリプトへ + `shellcheck` を走らせると、出力に `SC2086` を含み、終了コード 1 で終わる。 + 言語サーバが使うのはこの診断で、版を出すだけでは確かめたことにならない + +### 入れ損ないを止めること + +- [ ] 4. 版の確認の `RUN` に `shellcheck --version` がある。対象は + `gh --version && ... && session-manager-plugin --version` の行で、 + **shellcheck が無ければ `docker build` がこの行で失敗する** + 検証: `tests/containers/` の Dockerfile の文字列検査 +- [ ] 5. `shellcheck` は 1 つ目の `RUN` の 1 回目の `apt-get install` の一覧にあり、 + `shellcheck` を入れるための `RUN` は増えていない(`apt-get update` は 2 回のまま) + 検証: 同上 + +### 退行しないこと + +- [ ] 6. 依存を含めて新しく入るのは `shellcheck` と `libnuma1` の 2 パッケージである。 + 建てたイメージの中で次の値の合計が 30720(KB。30 MB)以下である。arm64 の実測は + `shellcheck` 単体で 24971 + `dpkg-query -W -f='${Installed-Size}\n' shellcheck libnuma1` + **合否を `docker images` の前後の差で決めない。** `--no-cache` の建て直しは + `claude` / `nodejs` などの取得物も新しい版へ入れ替える。差にこの変更以外の増減が混ざる +- [ ] 7. `uv run --locked pytest tests/ -q` が終了コード 0 +- [ ] 8. `devbase build base --no-cache` が arm64 で成功する +- [ ] 9. 次の 2 か所に shellcheck があり、どちらも**反映に `devbase build base --no-cache` が + 要る**ことを書いている + - `docs/user/container-operations.md` の base の道具の説明 + - `CHANGELOG.md` の `[Unreleased]` の `### Added` + +## 検証手段 + +| 項目 | 手段 | +| --- | --- | +| テスト | `uv run --locked pytest tests/ -q` | +| イメージの中 | `devbase build base --no-cache` と派生イメージの建て直しの後、`docker run --rm --entrypoint /bin/bash -c '...'`(受け入れ条件 1・2・3・6)。出力を Pull Request 本文へ貼る | +| CI | **イメージを建てない**(前提 2)。CI が緑でも受け入れ条件 1〜3・6・8 は確かめていない | + +## 未確認のまま残ること + +| 項目 | 内容 | +| --- | --- | +| amd64 での建て直し | 手元は arm64 のみ。amd64 はアーカイブの `Packages.gz` に `0.11.0-2`(Installed-Size 22867 KB、依存は arm64 と同じ)があることまで確かめた | +| 言語サーバからの診断 | bash-language-server は入れない(範囲外)。確かめるのは shellcheck 単体の診断まで(受け入れ条件 3) | + +## 依頼(原文) + +#249: + +> **base イメージに `shellcheck` を入れる。** コンテナの中で Bash スクリプトの静的検査と、言語サーバによる Bash の診断を使えるようにする。 +> +> `containers/base/Dockerfile` の `apt-get install -y --no-install-recommends` の一覧に `shellcheck` を足す。末尾の版の確認(187 行目の `RUN ... --version`)に `shellcheck --version` を加える。 +> +> - [ ] base から作ったコンテナで `shellcheck --version` が終了コード 0 で終わる +> - [ ] 派生イメージ(general / php など)でも同じく使える +> +> 範囲外: bash-language-server の導入。Serena は自分で入れる。Claude Code の plugin LSP で要るかは devbasex/ai-plugins#818 の設計で決める / 既存の指摘の片付け(#247) From 4cbb1b82a41a014932fe93c67375adda97a30951 Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Wed, 23 Sep 2026 15:13:39 +0900 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20PLAN67=20=E3=81=AE=E6=96=87?= =?UTF-8?q?=E6=9B=B8=E3=81=AE=E8=BF=BD=E8=A8=98=E4=BD=8D=E7=BD=AE=E3=83=BB?= =?UTF-8?q?=E3=83=86=E3=82=B9=E3=83=88=E3=81=AE=E8=A3=9C=E5=8A=A9=E9=96=A2?= =?UTF-8?q?=E6=95=B0=E3=83=BB=E6=96=B0=E8=A6=8F=E3=83=91=E3=83=83=E3=82=B1?= =?UTF-8?q?=E3=83=BC=E3=82=B8=E3=81=AE=E7=A2=BA=E3=81=8B=E3=82=81=E6=96=B9?= =?UTF-8?q?=E3=82=92=E7=9B=B4=E3=81=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - container-operations.md は独立した小節「Bash の静的検査(base 以降)」を立て、 イメージの詳細の表の base の「主な内容」にも shellcheck を足す - 新しいテストの補助関数に _first_apt_install を加える - 受け入れ条件 6 は apt-get install -s の Inst 行で新規の集合そのものを列挙して確かめる Co-Authored-By: Claude Opus 5.5 (1M context) --- issues/PLAN67_base-shellcheck-design.md | 13 +++++++++---- issues/PLAN67_base-shellcheck.md | 18 ++++++++++++------ 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/issues/PLAN67_base-shellcheck-design.md b/issues/PLAN67_base-shellcheck-design.md index d49aa64a..8aa690fd 100644 --- a/issues/PLAN67_base-shellcheck-design.md +++ b/issues/PLAN67_base-shellcheck-design.md @@ -18,7 +18,8 @@ | `containers/base/Dockerfile` の 1 つ目の `RUN` の 1 回目の `apt-get install` | 変える | `poppler-utils` の行の後へ、理由のコメントと `shellcheck` を足す | | `containers/base/Dockerfile` の版の確認の `RUN` | 変える | `&&` の連なりの末尾へ `shellcheck --version` を足す。入っていなければビルドをここで止める | | `tests/containers/test_base_dockerfile_shellcheck.py`(新設) | 足す | Docker を起動せずに、上の 2 か所の**形**を固定する | -| `docs/user/container-operations.md` | 変える | 「文書を扱う道具も base に入っています」の段の後へ、shellcheck の 1 段を足す。反映の注記(`devbase build base --no-cache` と派生イメージの建て直し)は既存の引用を共有させる | +| `docs/user/container-operations.md` の「イメージの詳細」の表(366 行目の base の行) | 変える | 「主な内容」の末尾へ shellcheck を足す | +| `docs/user/container-operations.md` の新しい小節「Bash の静的検査(base 以降)」 | 足す | 「文字の描画と、文書を扱う道具(base 以降)」の節(375〜419 行目)の後、「AI CLI エイリアス」の前に立てる。shellcheck の用途と、反映に `devbase build base --no-cache` と派生イメージの建て直しが要ることを書く。既存の節は末尾で `base-image-rendering.md` を参照しており、shellcheck はその仕様の範囲外のため同居させない | | `CHANGELOG.md` | 変える | `[Unreleased]` に `### Added` を立て、shellcheck を足したことと、**反映には `devbase build base --no-cache` が要る**ことを書く | 次のものは変えない。 @@ -159,7 +160,11 @@ PLAN63 の後、この変更の前に建てた base は `local.conf` を持つ ことはビルドが保証しているため、足しても新しく捕まえるものが無い。 補助の関数は `test_base_dockerfile_fonts.py` から import せず、新しいファイルに持つ。 -対象はコメント行を除く `_statements` と、行継続をつなぐ `_run_blocks` の 2 つである。 +対象はコメント行を除く `_statements`、行継続をつなぐ `_run_blocks`、1 つ目の `RUN` の +1 回目の `apt-get install` の一覧を切り出す `_first_apt_install` の 3 つである。 +1 つ目の `RUN` は `apt-get install` を 2 回呼ぶため、`RUN` の本文全体で探すと 2 回目の一覧に +あっても通ってしまう。`_first_apt_install` は `test_base_dockerfile_fonts.py` の同名の関数と +同じく、1 回目と 2 回目の `apt-get install` の出現位置の間を切り出す。 テストのファイルどうしを依存させない(`test_base_dockerfile_bao.py` も自前の `_statements` を持つ)。 ### 決定 5: `containers/lfm` には入れない @@ -179,10 +184,10 @@ Bash を書く用途は挙がっていない。入れるなら lfm 自身の `ap | 2 | base の後に `devbase-general` と `devbase-php` を建て直し、同じコマンドを走らせる。出力を Pull Request 本文へ貼る | | 3 | 建てた base で `printf '#!/bin/bash\necho $foo\n' > /tmp/t.sh; shellcheck /tmp/t.sh; echo exit=$?`。`SC2086` と `exit=1` を見る | | 4・5 | `test_base_dockerfile_shellcheck.py`(決定 4 の表) | -| 6 | 建てた base で `dpkg-query -W -f='${Installed-Size}\n' shellcheck libnuma1` の合計が 30720 以下。あわせて変更前のイメージで `dpkg -l libnuma1` が未導入であることを採り、新しく入るのが 2 つであることを示す | +| 6 | 変更前のイメージ(shellcheck を持たない `devbase-base`)で `apt-get update` の後に `apt-get install -s --no-install-recommends shellcheck \| grep '^Inst'` を走らせ、行がちょうど `shellcheck` と `libnuma1` の 2 行であることを見る。建てた base で `dpkg-query -W -f='${Installed-Size}\n' shellcheck libnuma1` の合計が 30720 以下 | | 7 | `uv run --locked pytest tests/ -q` | | 8 | `devbase build base --no-cache`(arm64) | -| 9 | 差分の目視(`docs/user/container-operations.md` と `CHANGELOG.md`) | +| 9 | 差分の目視(`docs/user/container-operations.md` の「イメージの詳細」の表と「Bash の静的検査(base 以降)」の小節、`CHANGELOG.md`) | ## 未確認のまま残ること diff --git a/issues/PLAN67_base-shellcheck.md b/issues/PLAN67_base-shellcheck.md index ff508ce1..43dc6962 100644 --- a/issues/PLAN67_base-shellcheck.md +++ b/issues/PLAN67_base-shellcheck.md @@ -87,7 +87,7 @@ - `containers/base/Dockerfile` - `tests/containers/test_base_dockerfile_shellcheck.py`(新設) -- `docs/user/container-operations.md` +- `docs/user/container-operations.md`(「イメージの詳細」の表の base の行と、新しい小節「Bash の静的検査(base 以降)」) - `CHANGELOG.md` ### 切り戻し手順 @@ -131,16 +131,22 @@ arm64、作成 2026-09-22T23:10:59Z)で採った。導入の結果は、同じ ### 退行しないこと - [ ] 6. 依存を含めて新しく入るのは `shellcheck` と `libnuma1` の 2 パッケージである。 - 建てたイメージの中で次の値の合計が 30720(KB。30 MB)以下である。arm64 の実測は - `shellcheck` 単体で 24971 + 変更前のイメージ(shellcheck を持たない `devbase-base`)で `apt-get update` の後に + 次のコマンドを走らせ、出力がちょうど `shellcheck` と `libnuma1` の 2 行である。 + 名指しした 2 つを調べるのではなく、新しく入る集合そのものを列挙して確かめる + `apt-get install -s --no-install-recommends shellcheck | grep '^Inst'` + あわせて、建てたイメージの中で次の値の合計が 30720(KB。30 MB)以下である。arm64 の + 実測は `shellcheck` 単体で 24971 `dpkg-query -W -f='${Installed-Size}\n' shellcheck libnuma1` **合否を `docker images` の前後の差で決めない。** `--no-cache` の建て直しは `claude` / `nodejs` などの取得物も新しい版へ入れ替える。差にこの変更以外の増減が混ざる - [ ] 7. `uv run --locked pytest tests/ -q` が終了コード 0 - [ ] 8. `devbase build base --no-cache` が arm64 で成功する -- [ ] 9. 次の 2 か所に shellcheck があり、どちらも**反映に `devbase build base --no-cache` が - 要る**ことを書いている - - `docs/user/container-operations.md` の base の道具の説明 +- [ ] 9. 次の 3 か所に shellcheck がある。表を除く 2 か所は、**反映に + `devbase build base --no-cache` が要る**ことを書いている + - `docs/user/container-operations.md` の「イメージの詳細」の表の base の「主な内容」 + - `docs/user/container-operations.md` の新しい小節「Bash の静的検査(base 以降)」。 + 「文字の描画と、文書を扱う道具(base 以降)」の節には同居させない - `CHANGELOG.md` の `[Unreleased]` の `### Added` ## 検証手段