Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 1 addition & 13 deletions docs/user/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -151,20 +151,8 @@ devbase はホストマシンの認証情報を自動収集し、コンテナ内
| `DEVBASE_OPEN_INDEX` | scale 時に開く dev インスタンス番号(既定: `1`) |
| `DEVBASE_EDITOR_SSH_HOST` | Remote-SSH 跨ホスト構成での ssh-remote ホスト名(例 `mac2`)。**通常は `~/.vscode-server` から自動検出**され不要。検出が外れる場合のみ明示。下記「跨ホスト」参照 |
| `DEVBASE_EDITOR_DOCKER_CONTEXT` | 跨ホスト時に ssh 先で使う docker context(既定: ホストの `docker context show`) |
| `DEVBASE_OPEN_TERMINAL` | 真で `up` 後に folderOpen ターミナル用 `.vscode/tasks.json` を配置(**既定: ON**) |

都度の上書きは CLI フラグで行います: `devbase up --open` / `--no-open` / `--open-index N` / `--open-terminal` / `--no-open-terminal`(env より優先)。

### 起動時に統合ターミナルを自動表示(`DEVBASE_OPEN_TERMINAL`)

`up` 時に、開く dev コンテナのワークスペース(`/work/$GIT_REPO`)へ folderOpen タスク(`.vscode/tasks.json`)を `docker exec` で配置します(既存があれば変更しません)。VS Code はフォルダを開いた時にこのタスクで統合ターミナルを前面表示します。

VS Code 公式には「起動時にターミナルを開く」専用設定が無く、folderOpen タスクが唯一の方法です。なお自動実行には次の 2 つの **VS Code クライアント側ユーザー設定**が関わり、devbase からは制御できません(いずれも application/user スコープ専用):

- **Workspace Trust**: 信頼していないフォルダではタスクは自動実行されません(初回は「フォルダを信頼」が必要)。
- **`task.allowAutomaticTasks`**: 既定 `off` ではフォルダごとに 1 回「自動タスクを許可」を尋ねます。`on` にするとプロンプト無しで実行されます。

→ 実際は「初回のみ信頼(+許可)クリック、以降は自動でターミナルが開く」挙動になります。無効化は `DEVBASE_OPEN_TERMINAL=0` または `devbase up --no-open-terminal`。
都度の上書きは CLI フラグで行います: `devbase up --open` / `--no-open` / `--open-index N`(env より優先)。

### 実行コンテキスト別の挙動

Expand Down
7 changes: 0 additions & 7 deletions lib/devbase/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,6 @@ def _add_open_args(parser):
parser.add_argument('--open-index', dest='open_index', type=int, default=None,
metavar='N',
help='Container index to open (default: 1)')
parser.add_argument('--open-terminal', dest='open_terminal', action='store_true',
default=None,
help='Place .vscode/tasks.json so the integrated terminal '
'auto-opens on folder open (overrides DEVBASE_OPEN_TERMINAL)')
parser.add_argument('--no-open-terminal', dest='open_terminal', action='store_false',
help='Do not place the folderOpen terminal tasks.json '
'(overrides DEVBASE_OPEN_TERMINAL)')
return parser


Expand Down
82 changes: 6 additions & 76 deletions lib/devbase/commands/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -327,8 +327,7 @@ def _dispatch_lifecycle(args) -> int:
'up': lambda: cmd_up(project_name=project_name,
scale=getattr(args, 'scale', None),
open_editor=getattr(args, 'open_editor', None),
open_index=getattr(args, 'open_index', None),
open_terminal=getattr(args, 'open_terminal', None)),
open_index=getattr(args, 'open_index', None)),
'down': lambda: cmd_down(),
'login': lambda: cmd_login(index=getattr(args, 'index', '1')),
'ps': lambda: cmd_ps(all_containers=getattr(args, 'all', False)),
Expand Down Expand Up @@ -397,8 +396,8 @@ def _resolve_open_index(open_index: Optional[int], scale: int) -> int:
"""開く dev インスタンス番号を解決する (CLI 引数 → env ``DEVBASE_OPEN_INDEX`` → 既定 1)。

``1..scale`` の範囲外 (0・負数・``scale`` 超過) は存在しないコンテナを指し原因不明な
起動失敗を招くため、警告を出して 1 へフォールバックする。:func:`_maybe_place_terminal_task`
と :func:`_maybe_open_editor` で共有し env フォールバック・範囲チェックの重複を避ける
起動失敗を招くため、警告を出して 1 へフォールバックする。:func:`_maybe_open_editor`
env フォールバック・範囲チェックを共有する
"""
if open_index is None:
raw = os.environ.get('DEVBASE_OPEN_INDEX')
Expand All @@ -417,7 +416,7 @@ def _resolve_open_index(open_index: Optional[int], scale: int) -> int:

def _maybe_open_editor(project_name: str, open_flag: Optional[bool],
open_index: Optional[int], scale: int,
compose_file=None, container_name: Optional[str] = None) -> None:
compose_file=None) -> None:
"""`up` 完了後に dev コンテナへ接続したエディタを開く ([6/6])。

有効判定は ``open_flag`` (CLI ``--open``/``--no-open``) が優先、None なら env
Expand All @@ -430,10 +429,6 @@ def _maybe_open_editor(project_name: str, open_flag: Optional[bool],
``compose_file`` は実コンテナ名問い合わせ用の override compose。``up`` 起動時と
同じファイルを渡さないと ``{dev}-{index}`` サービスが見えず実名取得に失敗する。
未指定なら ``.docker-compose.scale.yml`` が存在すればそれ、無ければ None。

``container_name`` が渡されれば :func:`opener.open_editor` 内の
``resolve_container_name`` (= ``docker compose ps``) をスキップして再利用する
(``_maybe_place_terminal_task`` が既に解決済みの名前を使い回し二重実行を避ける)。
"""
from devbase.editor import opener

Expand All @@ -458,75 +453,14 @@ def _maybe_open_editor(project_name: str, open_flag: Optional[bool],
workdir=workdir,
index=open_index,
compose_file=compose_file,
container_name=container_name,
)
except Exception as e: # noqa: BLE001 - エディタ起動で up を倒さない
logger.warning("エディタの自動オープンに失敗しましたがデプロイは成功しています: %s", e)


def _maybe_place_terminal_task(project_name: str, open_flag: Optional[bool],
open_index: Optional[int], scale: int,
compose_file=None) -> Optional[str]:
"""`up` 後、開く dev コンテナの作業ディレクトリへ folderOpen ターミナル tasks.json を配置。

フォルダを開いた時に統合ターミナルを自動表示するための ``.vscode/tasks.json`` を、
対象 dev インスタンスのワークスペース (``/work/$GIT_REPO``) に置く。作業ディレクトリは
コンテナ内 (named volume) のためホストから直接書けず、起動済みコンテナへ ``docker exec``
で書き込む。**既存の ``.vscode/tasks.json`` があれば一切触らない**。

有効判定は ``open_flag`` (CLI ``--open-terminal``/``--no-open-terminal``) が優先、None なら
env ``DEVBASE_OPEN_TERMINAL`` (既定 ON)。配置失敗は warning に握り潰し ``up`` を倒さない。
``open_index`` は開くインスタンスに合わせる (範囲外は 1 へフォールバック)。

解決した実コンテナ名を返す (無効時は None)。直後の :func:`_maybe_open_editor` へ渡して
``resolve_container_name`` (= ``docker compose ps``) の二重実行を避けるため。
"""
from devbase.editor import opener

enabled = open_flag if open_flag is not None else opener.is_open_terminal_enabled()
if not enabled:
return None

open_index = _resolve_open_index(open_index, scale)

if compose_file is None and _SCALE_COMPOSE_FILE.exists():
compose_file = _SCALE_COMPOSE_FILE

dev_service_name = get_dev_service_name()
container = opener.resolve_container_name(dev_service_name, project_name,
open_index, compose_file=compose_file)
workdir = opener.resolve_workdir(os.environ, project_name)
content = opener.build_folder_open_tasks_json()

# 既存があれば書かず、無ければ stdin から書き込む (冪等)。workdir は引数で渡し
# シェル内クォートを避ける ($1)。
script = (
'set -e; d="$1/.vscode"; mkdir -p "$d"; '
'if [ -e "$d/tasks.json" ]; then echo keep; '
'else cat > "$d/tasks.json"; echo placed; fi'
)
try:
proc = subprocess.run(
["docker", "exec", "-i", container, "sh", "-c", script, "_", workdir],
input=content, text=True, capture_output=True, timeout=15,
)
except Exception as e: # noqa: BLE001 - 配置失敗で up を倒さない
logger.warning("ターミナル用 tasks.json の配置に失敗しましたが続行します: %s", e)
return container # 名前解決は済んでいるのでエディタ側で再利用させる
if proc.returncode != 0:
logger.warning("ターミナル用 tasks.json の配置に失敗しましたが続行します: %s",
(proc.stderr or "").strip())
return container
if (proc.stdout or "").strip() == "placed":
logger.info("[6/6] 統合ターミナル自動表示用 tasks.json を配置: %s/.vscode/tasks.json",
workdir)
return container


def cmd_up(project_name: str = None, scale: int = None,
open_editor: Optional[bool] = None,
open_index: Optional[int] = None,
open_terminal: Optional[bool] = None) -> int:
open_index: Optional[int] = None) -> int:
"""Deploy containers with specified scale"""
if project_name is None:
project_name = get_project_name()
Expand Down Expand Up @@ -593,12 +527,8 @@ def cmd_up(project_name: str = None, scale: int = None,
if deploy_script.exists() and deploy_script.is_file():
_run_deploy_script_for_instances(deploy_script, range(1, scale + 1))

# エディタを開く前に tasks.json を置く (開いた瞬間に folderOpen が効くように)。
# 解決済みコンテナ名を editor 側へ渡し docker compose ps の二重実行を避ける。
dev_container = _maybe_place_terminal_task(project_name, open_terminal, open_index,
scale, compose_file=override_file)
_maybe_open_editor(project_name, open_editor, open_index, scale,
compose_file=override_file, container_name=dev_container)
compose_file=override_file)

logger.info("=== Deploy completed successfully ===")
return 0
Expand Down
56 changes: 2 additions & 54 deletions lib/devbase/editor/opener.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,56 +128,6 @@ def is_open_enabled(environ=None) -> bool:
return value.strip().lower() in _TRUTHY


def is_open_terminal_enabled(environ=None) -> bool:
"""``DEVBASE_OPEN_TERMINAL`` env が真か (**未設定は True = 既定 ON**)。

``DEVBASE_OPEN_EDITOR`` (既定 OFF) と既定が逆である点に注意。up 時の tasks.json 配置は
暴発リスクが低く、ユーザ要望で既定 ON とする (PLAN31_3)。
"""
env = os.environ if environ is None else environ
value = env.get("DEVBASE_OPEN_TERMINAL")
if value is None:
return True
return value.strip().lower() in _TRUTHY


def build_folder_open_tasks_json() -> str:
"""フォルダを開いた時に統合ターミナルを表示する folderOpen タスク (.vscode/tasks.json)。

VS Code 公式には「起動時にターミナルを開く」単独設定が無く (``hideOnStartup`` は復元
された永続セッションを隠すか否かに過ぎず新規生成はしない)、``runOn: folderOpen`` の
タスクが新規ターミナルを出せる唯一の方法 (docs/terminal/*, docs/debugtest/tasks)。
``reveal: always`` でパネルを前面に出し対話シェルを起動する。``type: process`` で
``/bin/sh -lc 'exec "${SHELL:-/bin/sh}"'`` を直接起動し、``$SHELL`` 未設定のコンテナでも
``/bin/sh`` にフォールバックして必ずシェルが立ち上がるようにする (``type: shell`` +
``${env:SHELL}`` だと未設定時に command が空になりタスクが即失敗する)。

.. note:: 自動実行には2つの user 設定ゲートがあり devbase からは制御できない:
Workspace Trust (信頼済みフォルダのみ自動実行) と ``task.allowAutomaticTasks``
(既定 off = フォルダ毎に1回許可確認)。いずれも application/user スコープ専用。
"""
tasks = {
"version": "2.0.0",
"tasks": [
{
"label": "devbase: open terminal",
"type": "process",
"command": "/bin/sh",
"args": ["-lc", 'exec "${SHELL:-/bin/sh}"'],
"isBackground": True,
"problemMatcher": [],
"presentation": {
"reveal": "always",
"panel": "dedicated",
"focus": True,
},
"runOptions": {"runOn": "folderOpen"},
}
],
}
return json.dumps(tasks, indent=2, ensure_ascii=False) + "\n"


def resolve_editor_cmd(environ=None) -> Optional[list]:
"""起動に使うエディタコマンド (argv list) を解決する。

Expand Down Expand Up @@ -512,7 +462,7 @@ def _launch(cmd: list, env: dict) -> None:


def open_editor(*, project_name: str, dev_service_name: str, workdir: str,
index: int = 1, compose_file=None, container_name: Optional[str] = None,
index: int = 1, compose_file=None,
environ=None,
isatty: Optional[bool] = None, system: Optional[str] = None,
launcher: Optional[Callable[[list, dict], None]] = None) -> str:
Expand All @@ -522,8 +472,6 @@ def open_editor(*, project_name: str, dev_service_name: str, workdir: str,
握り潰して warning にし、``up`` 本体を絶対に失敗させない。``isatty`` /
``system`` は :func:`detect_context` への差し替え口 (テスト用)。``compose_file``
は実コンテナ名問い合わせ時に起動と同じ override compose を ``-f`` で渡すため。
``container_name`` が渡されれば :func:`resolve_container_name` (= ``docker compose
ps``) をスキップしてそれを使う (呼び出し側で解決済みの名前を使い回す)。
"""
env = os.environ if environ is None else environ
ctx = detect_context(env, isatty=isatty, system=system)
Expand All @@ -537,7 +485,7 @@ def open_editor(*, project_name: str, dev_service_name: str, workdir: str,
logger.info("エディタの自動オープンをスキップ: %s", plan.reason)
return "skip"

container = container_name or resolve_container_name(
container = resolve_container_name(
dev_service_name, project_name, index, compose_file=compose_file)
# SSH コンテキストでのみネスト authority (@ssh-remote+host) を組む。自動推測は
# VS Code Remote-SSH 統合端末 (in_vscode) の時だけ有効にする — plain SSH (VS Code 外)
Expand Down
1 change: 0 additions & 1 deletion lib/devbase/env/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,3 @@ def gcp_credentials_key(profile: str) -> str:
# Remote-SSH 跨ホスト構成 (Windows VS Code → ssh → Mac のコンテナ) 用。
DEVBASE_EDITOR_SSH_HOST = "DEVBASE_EDITOR_SSH_HOST" # 任意。ssh-remote ホスト名 (例 mac2)。通常は ~/.vscode-server から自動検出
DEVBASE_EDITOR_DOCKER_CONTEXT = "DEVBASE_EDITOR_DOCKER_CONTEXT" # 任意。ssh 先 docker context (既定: docker context show)
DEVBASE_OPEN_TERMINAL = "DEVBASE_OPEN_TERMINAL" # 真偽。up 後に folderOpen ターミナル tasks.json を配置 (既定 ON)
Loading
Loading