From 12ed6c372a1b4162c3f9d337d5a05ecb0a510c09 Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Wed, 14 Oct 2026 10:02:29 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat(#454):=20env=20=E3=81=AE=E8=A3=9C?= =?UTF-8?q?=E5=AE=8C=E3=81=AE=E3=82=B5=E3=83=96=E3=82=B3=E3=83=9E=E3=83=B3?= =?UTF-8?q?=E3=83=89=E3=81=AE=E4=B8=80=E8=A6=A7=E3=81=AB=20token=20?= =?UTF-8?q?=E3=81=A8=20backend=20=E3=82=92=E8=B6=B3=E3=81=97=E3=80=81?= =?UTF-8?q?=E4=B8=80=E8=87=B4=E3=83=86=E3=82=B9=E3=83=88=E3=81=A7=E6=AF=94?= =?UTF-8?q?=E3=81=B9=E3=82=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- etc/_devbase | 2 ++ etc/devbase-completion.bash | 2 +- tests/cli/test_name_context_consistency.py | 14 ++++++++++---- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/etc/_devbase b/etc/_devbase index 179b12b8..937eb480 100644 --- a/etc/_devbase +++ b/etc/_devbase @@ -127,10 +127,12 @@ _devbase() { 'import:Import .env bundle (age decrypt + merge)' 'keygen:Generate the devbase age key used by the secret store' 'exec:Run a command with the decrypted secrets in its environment' + 'token:Refresh the OpenBao token in running dev containers' 'encrypt:Move plaintext settings into the encrypted store' 'decrypt:Move encrypted settings back to plaintext' 'rekey:Change who can decrypt the secrets and re-encrypt them' 'doctor:Check for leftover plaintext secrets and ignore-rule gaps' + 'backend:Choose where secrets are stored (age / plaintext / openbao)' ) plugin_subcommands=( diff --git a/etc/devbase-completion.bash b/etc/devbase-completion.bash index 974091b4..fa6a82cf 100644 --- a/etc/devbase-completion.bash +++ b/etc/devbase-completion.bash @@ -49,7 +49,7 @@ _devbase_completions() { # project / container は同じサブコマンド群 (container は非推奨だが補完は維持)。 local project_subcommands="up down ps login logs scale build rebuild list profile open post-start" local container_subcommands="up down ps login logs scale build rebuild profile open" - local env_subcommands="init sync list set get delete edit project export import keygen exec encrypt decrypt rekey doctor" + local env_subcommands="init sync list set get delete edit project export import keygen exec token encrypt decrypt rekey doctor backend" local plugin_subcommands="list install uninstall update info sync repo" local repo_subcommands="add remove list refresh" local snapshot_subcommands="create list restore copy delete rotate" diff --git a/tests/cli/test_name_context_consistency.py b/tests/cli/test_name_context_consistency.py index 8f56c7ec..5d98286d 100644 --- a/tests/cli/test_name_context_consistency.py +++ b/tests/cli/test_name_context_consistency.py @@ -291,25 +291,31 @@ def test_zsh_completion_offers_context(): # --------------------------------------------------------------------------- -# 補完: project / container のサブコマンドの一覧 +# 補完: project / container / env のサブコマンドの一覧 # --------------------------------------------------------------------------- +# サブコマンドの全部を比べるグループ(`[name]`・`--context` を取るかによらない) +_ALL_SUBCOMMAND_GROUPS = ("env",) + + def _group_subcommands(group): + if group in _ALL_SUBCOMMAND_GROUPS: + return {p[1] for p, _ in _walk(cli._create_parser()) if len(p) == 2 and _canonical(p)[0] == group} # 入れ子の `profile` は親の `profile` として数える return {p[1] for p in NAME_PATHS | CONTEXT_PATHS if len(p) >= 2 and p[0] == group} -@pytest.mark.parametrize("group", ["project", "container"]) +@pytest.mark.parametrize("group", ["project", "container", "env"]) def test_bash_completion_lists_subcommands(group, fake_root): expected = _group_subcommands(group) - assert expected, f"argparse の {group} に `[name]` / `--context` を取るサブコマンドが無い" + assert expected, f"argparse の {group} に比べるサブコマンドが無い" offered = _bash_complete((group,), fake_root) missing = expected - offered assert not missing, (f"etc/devbase-completion.bash の {group} のサブコマンドの一覧に無い: " f"{sorted(missing)}") -@pytest.mark.parametrize("group", ["project", "container"]) +@pytest.mark.parametrize("group", ["project", "container", "env"]) def test_zsh_completion_lists_subcommands(group): expected = _group_subcommands(group) m = re.search(rf"^\s*{group}_subcommands=\((.*?)^\s*\)", ZSH_COMPLETION.read_text(), re.MULTILINE | re.DOTALL) From 7dd8c769442221573d6d5107ac361651daa52b3f Mon Sep 17 00:00:00 2001 From: "takemi.ohama" Date: Wed, 14 Oct 2026 10:03:31 +0900 Subject: [PATCH 2/2] =?UTF-8?q?docs(#454):=20=E4=B8=80=E8=87=B4=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=81=8C=20env=20=E3=81=AE=E3=82=B5=E3=83=96?= =?UTF-8?q?=E3=82=B3=E3=83=9E=E3=83=B3=E3=83=89=E3=81=AE=E4=B8=80=E8=A6=A7?= =?UTF-8?q?=E3=82=92=E6=AF=94=E3=81=B9=E3=82=8B=E3=81=93=E3=81=A8=E3=82=92?= =?UTF-8?q?=E7=A2=BA=E5=AE=9A=E4=BB=95=E6=A7=98=E3=81=A8=20CHANGELOG=20?= =?UTF-8?q?=E3=81=AB=E6=9B=B8=E3=81=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 5.5 --- CHANGELOG.md | 3 +++ docs/specifications/cli-argument-resolution.md | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d88dd25..03a23f90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,9 @@ `~/.vscode-server/bin` を開発ユーザーが書ける形に揃えます。 ### Fixed +- **`devbase env ` の候補に `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` のホストを diff --git a/docs/specifications/cli-argument-resolution.md b/docs/specifications/cli-argument-resolution.md index 197bfc8c..846e0a42 100644 --- a/docs/specifications/cli-argument-resolution.md +++ b/docs/specifications/cli-argument-resolution.md @@ -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 <グループ...> ` の形で、間の語が道の頭になる。2 列目にバッククォートで並べた語を `` に入れる。表は `[name]` の集合・`--context` の集合にそれぞれ等しい | 補完の例外は `project profile up` / `down` / `list` の 3 つで、理由は「1 つ目の位置引数は、値が 1 個なら