Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
5339270
feat(#463): VS Code Server の本体を全コンテナ共通の 1 本のボリュームに置く
takemi-ohama Oct 14, 2026
579b468
feat(#463): コンテナの起動で VS Code Server の bin を用意し旧版を片付ける
takemi-ohama Oct 14, 2026
08578ea
feat(#463): 起動の後の処理で bin の所有者を揃え、up で旧形式のボリュームを案内する
takemi-ohama Oct 14, 2026
feb6680
docs(#463): VS Code Server の本体だけを共有する構成と移り方を書く
takemi-ohama Oct 14, 2026
6b40e52
docs(#463): 起動の後の処理の順と VS Code Server の困りごとの節を今の振る舞いに合わせる
takemi-ohama Oct 14, 2026
86a232c
Merge pull request #485 from devbasex/feat/issue-463-m8d
takemi-ohama Oct 14, 2026
12ed6c3
feat(#454): env の補完のサブコマンドの一覧に token と backend を足し、一致テストで比べる
takemi-ohama Oct 14, 2026
7dd8c76
docs(#454): 一致テストが env のサブコマンドの一覧を比べることを確定仕様と CHANGELOG に書く
takemi-ohama Oct 14, 2026
53013e4
Merge pull request #486 from devbasex/feat/issue-454-m8d
takemi-ohama Oct 14, 2026
da42e5c
fix(#374): 起動の待ちの時間切れの文言に巡の回数と実際の経過の秒数を出す
takemi-ohama Oct 14, 2026
f18b449
docs(#374): 時間切れの新しい文言を確定仕様と CHANGELOG に書く
takemi-ohama Oct 14, 2026
789fa5a
Merge pull request #487 from devbasex/feat/issue-374-m8d
takemi-ohama Oct 14, 2026
9ad8c53
Test: 現状固定テストを足す — lib/devbase/volume/manager.py#VolumeManager.ensure…
takemi-ohama Oct 14, 2026
d4da43d
Refactor: extract_method — lib/devbase/volume/manager.py#VolumeManage…
takemi-ohama Oct 14, 2026
6471593
Refactor: extract_method — lib/devbase/utils/docker.py#wait_for_conta…
takemi-ohama Oct 14, 2026
17fe0a8
Refactor: centralize_configuration — lib/devbase/editor/vscode_server…
takemi-ohama Oct 14, 2026
ef4a39f
Refactor: extract_method — lib/devbase/commands/container.py#_prepare…
takemi-ohama Oct 14, 2026
f042cc4
fix(vscode-server): 片付けでリンクを辿らず、旧ボリューム削除の消失を明示する (#488)
takemi-ohama Oct 14, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,30 @@
**更新後の最初の `devbase up` の自動スナップショットは、系列ごとに新しい世代(フル)を作ります。**
除外の一覧が違う世代を `devbase snapshot create --name` で指定すると、差分を作らずに終了コード 1 で止まります。
既存の世代はそのまま一覧・復元できます。
- **VS Code Server の本体(`~/.vscode-server/bin`)だけを全コンテナ共通の 1 本のボリューム `devbase_vscode-server-bin` に
置くようにしました(#463)。** これまではコンテナ 1 つに 1 本の `devbase_vscode_<プロジェクト>_<番号>` が
`~/.vscode-server` を丸ごと持ち、VS Code の更新のたびに約 0.6GB の版が各ボリュームへ溜まっていました。
今は本体の版をプロジェクトとインスタンスの数だけ重ねて持たず、コンテナの起動が `bin/` の版を新しい順に 5 つまで残し、
同時の展開で残った入れ子の本体と古い展開の途中のディレクトリも消します(この片付けは base と派生イメージを
建て直した後から効きます)。
**拡張機能・リモート側の設定(`data/Machine/settings.json`)・ローカル履歴・拡張機能がリモート側に保存する状態は、
ボリュームに置かずコンテナの書き込みレイヤーに残るため、`devbase up` でコンテナを作り直すたびに消えるようになります。**
手で入れた拡張機能は入れ直しになり、Dev Containers の既定の拡張機能は作り直しの後の attach で入り直します。
`window.title` は `devbase up` が毎回書き直します。`docker restart` と端末の再起動では消えません。
移った後の最初の attach で本体(約 215MB)を取り直します。以前の `devbase_vscode_<プロジェクト>_<番号>` は付けず、
中身も引き継がず、devbase は消しません。残っている間は `devbase up` の最後に名前と消すコマンドが出るので、
利用者が `docker volume rm` で消してください([使わなくなった VS Code Server ボリュームを消す](docs/user/container-operations.md#使わなくなった-vs-code-server-ボリュームを消す))。
建て直す前のイメージでも attach できるよう、`devbase up` / `scale` / `project post-start` の起動の後の処理が
`~/.vscode-server/bin` を開発ユーザーが書ける形に揃えます。

### Fixed
- **`devbase up` / `devbase scale` の起動の待ちの時間切れの文言が、巡の回数と実際に待った秒数を出すようにしました(#374)。**
制限は 1 秒休む巡の回数(60 巡)で数え、docker の呼び出しにかかる時間を含まないため、実際に待つ時間は 60 秒より
長くなります。これまでの `timeout (60s) ...` は 60 秒で止まったと読めました。今は
`timeout after 60 rounds (73s elapsed) waiting for the entrypoint to complete` の形で出ます。数え方と制限は変わりません。
- **`devbase env <TAB>` の候補に `token` と `backend` が出るようにしました(#454)。** bash と zsh の補完の
サブコマンドの一覧に 2 つが無く、名前を手で打たないと使えませんでした。一致テストが `env` のサブコマンドの
全部を bash と zsh の一覧と比べるようになり、`env` のサブコマンドを足したときの取り残しで落ちます。
- **接続先 URL が手元のサーバ(`http://127.0.0.1:8200` など `http` の loopback)のとき、`devbase up` したコンテナの中の
`bao` がサーバへ届くようにしました(#295)。** これまではコンテナへ渡す `BAO_ADDR` がそのまま `127.0.0.1` を指し、
コンテナ自身へつながっていました。Docker が手元の端末のものなら、コンテナの `BAO_ADDR` のホストを
Expand Down
105 changes: 100 additions & 5 deletions containers/base/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -603,17 +603,112 @@ devbase_keep_replaced_link() {
}

# ===================================================================
# PLAN36: VS Code Server の永続ディレクトリ
# PLAN36 / #463: VS Code Server の本体の置き場
# ===================================================================
# ~/.vscode-server にはコンテナ 1 つにつき 1 本の named volume が割り当てられる
# (devbase_vscode_<project>_<index>)。空のボリュームは root 所有で作られるため、
# そのままでは開発ユーザーが VS Code Server をインストールできない。
# ~/.vscode-server/bin には全コンテナ共通の named volume (devbase_vscode-server-bin)
# が付く。本体の版 (bin/<commit>) だけを持ち、extensions/・data/ などはコンテナの
# 書き込みレイヤーに残る。空のボリュームは root 所有で付き、マウント先の親
# ~/.vscode-server も Docker が root 所有で作るため、そのままでは開発ユーザーが
# VS Code Server を置けない。
#
# マウントが無い構成でもディレクトリを作るだけで済み、VS Code の動作は変わらない。

# bin/ に残す本体の版の数 (#463)。1 版は約 0.6GB。VS Code はおおむね月に 1 版のため、
# 別の端末の VS Code が数か月更新されずに古い版で attach していても消しにくい数にする
DEVBASE_VSCODE_SERVER_KEEP=5

# 展開の途中のディレクトリ (bin/<commit>_<ミリ秒>) を残りと見なすまでの分数。
# 展開に 60 分かかることは無いため、動いている展開を消さない
DEVBASE_VSCODE_SERVER_STALE_MINUTES=60

devbase_setup_vscode_server_dir() {
local home_root="$1" owner="${2:-${USERNAME:-ubuntu}}"

devbase_ensure_persistent_root "${home_root}/.vscode-server" "$owner"
devbase_ensure_persistent_root "${home_root}/.vscode-server/bin" "$owner"
devbase_prune_vscode_server_bin "${home_root}/.vscode-server/bin"
}

# ファイルの更新時刻 (UNIX 秒)。GNU / uutils の stat と BSD の stat の両方で読む。
devbase_file_mtime() {
stat -c %Y "$1" 2>/dev/null || stat -f %m "$1" 2>/dev/null
}

# 片付けの 1 つのパスを消す。消せずに残ったときだけ WARNING を出す。
#
# ほかのコンテナの片付けが同時に同じパスを消すことがある。そのとき rm が途中で
# 失敗しても、パスが無くなっていれば WARNING を出さない。終了コードは常に 0。
devbase_remove_vscode_server_path() {
local path="$1" err

err=$(rm -rf -- "$path" 2>&1) && return 0
# ほかのコンテナが消している途中なら、もう一度で消え切る
if [ -e "$path" ] || [ -L "$path" ]; then
err=$(rm -rf -- "$path" 2>&1) && return 0
fi
if [ -e "$path" ] || [ -L "$path" ]; then
echo "WARNING: VS Code Server の片付けで消せなかった: ${path} (${err%%$'\n'*})" >&2
fi
return 0
}

# 共通のボリュームの bin/ を片付ける (#463)。消すのは次の 3 種だけで、bin/ のほかの
# もの・~/.vscode-server の bin 以外には触らない。終了コードは常に 0。
#
# 1. 残す版の数を超えた古い版。版は 40 桁の 16 進の名前で product.json を持つ
# ディレクトリ。product.json の更新時刻の新しい順 (同じなら名前の順) に並べる。
# product.json は片付けが書き換えないため、同時に走る片付けどうしで並びが同じに
# なり、残る版が残す数より減らない (ディレクトリの更新時刻では減った)
# 2. 残った版の直下の入れ子の本体 (product.json を持つディレクトリ)。本体の同時の
# 展開で、遅れた側の中身が bin/<commit>/vscode-server-linux-<arch>/ に残ったもの
# 3. 60 分より古い展開の途中のディレクトリ bin/<commit>_<数字>
#
# シンボリックリンクは辿らない。bin/ 自身・bin/<commit>・入れ子がリンクなら、版にも
# 片付けの対象にも数えない。リンク先の bin の外のものを消さないためである
devbase_prune_vscode_server_bin() {
local bin="$1" keep="${2:-$DEVBASE_VSCODE_SERVER_KEEP}"
local entry name mtime listing="" count=0 kept=() nested

[ -d "$bin" ] && [ ! -L "$bin" ] || return 0

for entry in "$bin"/*; do
name="${entry##*/}"
[[ "$name" =~ ^[0-9a-f]{40}$ ]] || continue
[ -d "$entry" ] && [ ! -L "$entry" ] || continue
[ -f "$entry/product.json" ] || continue
mtime=$(devbase_file_mtime "$entry/product.json") || continue
listing+="${mtime} ${name}"$'\n'
done

while read -r mtime name; do
[ -n "$name" ] || continue
count=$((count + 1))
if [ "$count" -le "$keep" ]; then
kept+=("$name")
else
devbase_remove_vscode_server_path "${bin}/${name}"
fi
done < <(printf '%s' "$listing" | LC_ALL=C sort -k1,1nr -k2,2)

for name in "${kept[@]}"; do
# 数えた後にリンクへ置き換わっていれば、リンク先を辿らない
[ ! -L "$bin" ] && [ ! -L "${bin}/${name}" ] || continue
for nested in "${bin}/${name}"/*/; do
nested="${nested%/}"
[ -d "$nested" ] && [ ! -L "$nested" ] || continue
[ -f "${nested}/product.json" ] || continue
devbase_remove_vscode_server_path "$nested"
done
done

while IFS= read -r entry; do
name="${entry##*/}"
[[ "$name" =~ ^[0-9a-f]{40}_[0-9]+$ ]] || continue
devbase_remove_vscode_server_path "$entry"
done < <(find "$bin" -mindepth 1 -maxdepth 1 -type d \
-mmin "+${DEVBASE_VSCODE_SERVER_STALE_MINUTES}" 2>/dev/null)

return 0
}

# ===================================================================
Expand Down Expand Up @@ -781,7 +876,7 @@ USERNAME="${USERNAME:-ubuntu}"
devbase_setup_cloud_config_dirs "$USERNAME"
devbase_setup_gcp_credentials "/home/${USERNAME}"

# 1.5. VS Code Server の永続ディレクトリ (PLAN36)
# 1.5. VS Code Server の本体の置き場と片付け (PLAN36 / #463)
devbase_setup_vscode_server_dir "/home/${USERNAME}" "$USERNAME"

# 2. Setup Git configuration
Expand Down
4 changes: 2 additions & 2 deletions docs/specifications/cli-argument-resolution.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,8 +128,8 @@ graph TD
| --- | --- |
| `bin/devbase` の `_PROJECT_NAME_SUBCOMMANDS` | `project` の直下で `[name]` を取る parser の名前の集合に等しい |
| `bin/devbase` の `_NAME_RESOLVABLE_SHORTCUTS` | `cli.SHORTCUTS` のキーと `build` の和に等しい。あわせて、トップレベルで `[name]` を取る parser がすべて `cli.SHORTCUTS` にあること |
| `etc/devbase-completion.bash` | 一時ディレクトリの `projects/` を `DEVBASE_ROOT` にして補完を実行し、`[name]` の集合から補完の例外を引いたすべての道の名前の位置でプロジェクト名が候補に出る。`--context` の集合のすべての道(`container` の道は `ct` で始めても)で `devbase <道> -` の候補に `--context` が出る。`[name]` の集合から補完の例外を引いた道では、`devbase <道> web -` の候補にも `--context` が出る。`--context` を取らない末端の道では、`devbase <道> -` の候補に `--context` が出ない。`project` / `container` の直下で `[name]` か `--context` を取るサブコマンド(入れ子は親の `profile` として数える)が、そのグループのサブコマンドの候補に含まれる |
| `etc/_devbase` | zsh を起動せず内容を読む。`case "$words[2]"` から字下げの深さで道の分岐(`up\|down)` のような `\|` 区切りの見出し)を辿り、`[name]` の集合から補完の例外を引いた道の本体に `_devbase_project_names` がある。`--context` の集合のすべての道の本体に、値の補完を持たない `'--context[...]:context:'`(`:context:` の後ろに補完の関数を置かない形)がある。`project_subcommands` / `container_subcommands` の一覧に bash と同じサブコマンドが含まれる |
| `etc/devbase-completion.bash` | 一時ディレクトリの `projects/` を `DEVBASE_ROOT` にして補完を実行し、`[name]` の集合から補完の例外を引いたすべての道の名前の位置でプロジェクト名が候補に出る。`--context` の集合のすべての道(`container` の道は `ct` で始めても)で `devbase <道> -` の候補に `--context` が出る。`[name]` の集合から補完の例外を引いた道では、`devbase <道> web -` の候補にも `--context` が出る。`--context` を取らない末端の道では、`devbase <道> -` の候補に `--context` が出ない。`project` / `container` の直下で `[name]` か `--context` を取るサブコマンド(入れ子は親の `profile` として数える)が、そのグループのサブコマンドの候補に含まれる。`env` の直下のサブコマンドは、`[name]`・`--context` を取るかによらず全部が `env` のサブコマンドの候補に含まれる |
| `etc/_devbase` | zsh を起動せず内容を読む。`case "$words[2]"` から字下げの深さで道の分岐(`up\|down)` のような `\|` 区切りの見出し)を辿り、`[name]` の集合から補完の例外を引いた道の本体に `_devbase_project_names` がある。`--context` の集合のすべての道の本体に、値の補完を持たない `'--context[...]:context:'`(`:context:` の後ろに補完の関数を置かない形)がある。`project_subcommands` / `container_subcommands` / `env_subcommands` の一覧に bash と同じサブコマンドが含まれる |
| この節の 2 つの表 | 見出し `` #### `[name]` を受け付けるサブコマンド `` と `` #### `--context` を受け付けるサブコマンド `` の直後の表を読む。1 列目は `devbase <グループ...> <sub>` の形で、間の語が道の頭になる。2 列目にバッククォートで並べた語を `<sub>` に入れる。表は `[name]` の集合・`--context` の集合にそれぞれ等しい |

補完の例外は `project profile up` / `down` / `list` の 3 つで、理由は「1 つ目の位置引数は、値が 1 個なら
Expand Down
5 changes: 3 additions & 2 deletions docs/specifications/compose-profiles.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ subcommand より前に置く。`<サービス...>` はプロファイル X に

起動の待ちの後、`cmd_scale` は増やしたインスタンス(`current + 1` から `new`)のうち起動できたものを
後処理の対象にして、`up` と共有する起動の後の処理の段(`_run_post_start`)を呼ぶ。順は
不足リポジトリの報告 → `./deploy` → bao の token → 窓のタイトルの設定で、`up` と同じである。
不足リポジトリの報告 → `./deploy` → bao の token → VS Code Server の `bin` の所有者の直し(#463)→
窓のタイトルの設定で、`up` と同じである。
起動できなかったインスタンスがあると、起動の待ちは `ContainerStartupError`(起動できた番号と、
起動できなかった番号ごとの理由)を投げる。`cmd_scale` はそれを受け、対象へ後処理を行った後に
`Scale failed` と起動できなかった全部の名前・理由・補う手順(`devbase project post-start <name>`)を
Expand Down Expand Up @@ -442,7 +443,7 @@ TUI では、復元境界が機密の注入履歴も戻すため、別プロジ
`os.environ` を変えないこと。起動の非 0 で `Failed to start new containers` と 1 になり例外を
出さないこと。プロファイルのサービスを起動の対象に入れないこと。正常系の順序
(グループの検査 → `write_scale` → ボリューム → network → 生成 → `default_services` → 起動 →
ready 待ち → 不足リポジトリの報告 → `./deploy` → bao の token → 窓のタイトル)、bao と `./deploy` の
ready 待ち → 不足リポジトリの報告 → `./deploy` → bao の token → VS Code Server の `bin` → 窓のタイトル)、bao と `./deploy` の
範囲が `current + 1` から `new` までであること、停止を呼ばないこと
(`tests/commands/test_container_scale_order.py`)。起動できなかったインスタンスがあるときの
後処理の対象と出力(`tests/commands/test_container_post_start.py`)
Expand Down
Loading
Loading