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
42 changes: 41 additions & 1 deletion CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -4,7 +4,46 @@

## [Unreleased]

## [3.0.0] - 2026-08-23

プロジェクト設定を `project.yml` へ移行する破壊的変更を含みます。プラグイン側の
プロジェクト定義も本バージョンに合わせた更新が必要です (`requires.devbase: ">=3.0.0"`)。

### Changed
- **1 プロジェクト = 1 コンテナ = 複数リポジトリ**に対応しました。プロジェクトが開発対象と
するリポジトリは `projects/<name>/project.yml` の `repos` 配列で指定し、すべてが同じ
コンテナの `/work` 配下へ clone されます。リポジトリごとに Git ホスト・オーナー・
ブランチ・clone 先ディレクトリ名・`init.sh` の実行有無を指定できます。関連する複数
リポジトリ (本体・ドキュメント・インフラ等) を 1 つの開発環境で横断的に扱えます。
リポジトリが 2 件以上あるときは、全リポジトリを含む multi-root ワークスペース
`/work/<プロジェクト名>.code-workspace` を生成してエディタで開きます。
詳細は [project.yml リファレンス](docs/user/project-yml.md) を参照してください。
- **プロジェクト設定を `env` から `project.yml` へ移しました (破壊的変更)。**
`GIT_USER` / `GIT_REPO` / `GIT_HOST` / `WORK_DIR` / `CONTAINER_SCALE` /
`DEVBASE_OPEN_EDITOR` は `project.yml` の `repos` / `work_dir` / `scale` /
`open_editor` に移行しました。`env` は「コンテナへ渡す環境変数」だけを持ちます。
配列を表現できない環境変数では複数リポジトリを書けないためです。
`project.yml` を持たないプロジェクトは `devbase up` が移行手順を案内して停止します
(旧形式へ暗黙にフォールバックすると、移行漏れを検出できないため)。
`devbase project scale N` の書き込み先も `project.yml` の `scale` になります。

> **Note:** リポジトリの clone は `entrypoint.sh` で行われ、これはイメージに焼き込まれます。
> 適用には `devbase build --no-cache` によるベースイメージの再ビルドが必要です。

### Added
- **ライフサイクルフックへ `project.yml` の値を環境変数で渡す**ようにしました。`pre-up` /
`deploy` に `DEVBASE_PRIMARY_DIR` (primary の clone 先ディレクトリ名) /
`DEVBASE_PRIMARY_URL` (primary の clone URL) / `DEVBASE_WORK_DIR` (コンテナ内の既定の
作業ディレクトリ) / `DEVBASE_REPO_DIRS` (全リポジトリのディレクトリ名・宣言順の空白
区切り) が渡ります。フックはホスト側で動くため `env` を読み込めず、`GIT_REPO` /
`WORK_DIR` の `project.yml` 移行によって `source ./env` に依存していたフックが値を
取れなくなるためです。値は子プロセス限定で、親プロセスの環境は汚しません。
詳細は [フックへ渡る環境変数](docs/plugin-dev/quickstart.md#フックへ渡る環境変数)
を参照してください。
- **`devbase project migrate-config`** を追加しました。旧 `env` 形式のプロジェクト定義を
`project.yml` へ機械的に変換します。`--dry-run` で変換結果を確認でき、既存の
`project.yml` は上書きしないため何度実行しても同じ状態に収束します。
変換対象は上記 6 キーのみで、`ENABLE_SSH` などそれ以外は `env` に残ります。
- **tmux 内では `VSCODE_IPC_HOOK_CLI` が古くても VS Code を自動で開く**ようにしました。
tmux サーバーはセッション作成時の環境変数を保持し続けますが、`update-environment` に
登録した変数は attach のたびに更新されるため、**ペインのシェルは古い値・tmux の
Expand DownExpand Up@@ -198,5 +237,6 @@ OSS 化に伴う初回リリース。devbase は本バージョンより `devbas
### Removed
- 「公式レジストリ」固定の概念を廃止。各レジストリは対等な扱いとなる。

[Unreleased]: https://github.com/devbasex/devbase/compare/v2.2.0...HEAD
[Unreleased]: https://github.com/devbasex/devbase/compare/v3.0.0...HEAD
[3.0.0]: https://github.com/devbasex/devbase/compare/v2.2.0...v3.0.0
[2.2.0]: https://github.com/devbasex/devbase/releases/tag/v2.2.0
1 change: 1 addition & 0 deletions README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -144,6 +144,7 @@ devbaseのコマンドは4つのグループにまとめられています。
| [はじめに](docs/user/getting-started.md) | 前提条件、初回セットアップ、日常ワークフロー |
| [CLIリファレンス](docs/user/cli-reference/README.md) | 全コマンドの構文・オプション・使用例(コマンドグループ別) |
| [プラグインレジストリ](docs/user/plugin-registries.md) | 公開・社内レジストリの一覧と追加方法 |
| [project.yml リファレンス](docs/user/project-yml.md) | プロジェクト設定(複数リポジトリ・scale・エディタ) |
| [環境変数ガイド](docs/user/environment-variables.md) | 3レベル構造、コレクター、ソース同期 |
| [環境変数の export/import ガイド](docs/user/env-export-import.md) | バンドル形式・age 暗号化・S3 連携・merge/replace の運用 |
| [コンテナ操作ガイド](docs/user/container-operations.md) | ライフサイクル、並行開発、ボリューム構造 |
Expand Down
159 changes: 133 additions & 26 deletions containers/base/entrypoint.sh
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,6 +2,133 @@

set -e

# ===================================================================
# PLAN32: 複数リポジトリの clone / workspace 生成
# ===================================================================
# ホスト側 (devbase up) が projects/<name>/project.yml を正規化し、clone プランを
# base64 のレコード列 (DEVBASE_REPOS) としてコンテナへ渡す。ここでは 1 行ずつ読んで clone
# するだけなので、コンテナイメージへ YAML/JSON パーサ依存を増やさずに済む。
#
# DEVBASE_REPOS : base64 の行区切りレコード。1 行 = url / dir / branch / init を
# US (0x1f) 区切りで並べたもの。branch は空可、init は 1/0。
# 行区切りは LF で末尾にも LF が付く (符号化側の契約:
# lib/devbase/project/config.py の encode_repo_plan)
# DEVBASE_PRIMARY_DIR : 起動後に cd する /work 配下のディレクトリ名
# DEVBASE_WORKSPACE : 書き出す *.code-workspace の絶対パス (複数 repo 時)
# DEVBASE_WORKSPACE_B64 : その中身 (base64 JSON)
#
# 関数定義だけを読み込みたいテストからは
# `DEVBASE_ENTRYPOINT_LIB_ONLY=1 . entrypoint.sh` で source する。

# clone プランを復号して 1 行 1 repo で出力する (未設定なら何も出さない)。
devbase_repo_plan_lines() {
[ -n "${DEVBASE_REPOS:-}" ] || return 0
printf '%s' "$DEVBASE_REPOS" | base64 -d
}

# clone プランの各リポジトリを <work_root>/<dir> へ clone する。
#
# 個々の失敗 (clone / checkout / init.sh) は warning に留めて次の repo へ進む。
# 1 つ落ちただけでコンテナが起動しないと、他リポジトリでの作業まで止まるため。
devbase_clone_repos() {
local work_root="${1:-/work}"
local plan url dir branch init target cloned

if ! plan="$(devbase_repo_plan_lines 2>/dev/null)"; then
echo "Warning: Failed to decode DEVBASE_REPOS (skipping repository setup)"
return 0
fi
if [ -z "$plan" ]; then
echo "No repositories configured (DEVBASE_REPOS is empty)"
return 0
fi

mkdir -p "$work_root"
local extra index=0
# フィールド区切りは US (0x1f)。タブだと IFS の空白扱いで連続する区切りが 1 つに
# 畳まれ、branch 未指定 (空フィールド) の行で init の値がずれる。
while IFS=$'\x1f' read -r url dir branch init extra; do
# 末尾の空行 (符号化側が付ける末尾改行) は読み飛ばす
[ -n "$url$dir$branch$init$extra" ] || continue
index=$((index + 1))
if [ -z "$url" ] || [ -z "$dir" ] || [ -n "$extra" ] ||
{ [ "$init" != "1" ] && [ "$init" != "0" ]; }; then
echo "Warning: Ignoring malformed clone plan entry (line $index)"
continue
fi
target="$work_root/$dir"

cloned=0
if [ -d "$target/.git" ]; then
echo "Repository already exists: $dir"
else
echo "Cloning repository: $url -> $target"
if ! git clone "$url" "$target"; then
echo "Warning: Failed to clone repository: $url"
continue
fi
cloned=1
fi

# checkout は clone 直後だけ。既存 clone に対して毎回実行すると、コンテナ内で
# 作業ブランチへ切り替えたユーザが再起動のたびに引き戻されてしまう。
# 失敗したら意図しない branch で init.sh を走らせないよう この repo は打ち切る。
if [ "$cloned" = "1" ] && [ -n "$branch" ]; then
if ! git -C "$target" checkout "$branch"; then
echo "Warning: Failed to checkout branch '$branch' in $dir (skipping)"
continue
fi
fi

if [ "$init" = "1" ] && [ -f "$target/init.sh" ]; then
echo "Running init.sh in $dir"
(cd "$target" && ./init.sh) || echo "Warning: init.sh failed in $dir"
fi
done <<EOF
$plan
EOF
}

# 複数 repo をまとめて開くための *.code-workspace を書き出す。
#
# 中身はホスト側で組み立てて base64 で渡ってくるので、ここでは復号して置くだけ。
# JSON の組み立て (エスケープ) をシェルでやらない分、壊れにくい。
devbase_write_workspace() {
[ -n "${DEVBASE_WORKSPACE:-}" ] || return 0
[ -n "${DEVBASE_WORKSPACE_B64:-}" ] || return 0

local dest="$DEVBASE_WORKSPACE"
mkdir -p "$(dirname "$dest")"
if printf '%s' "$DEVBASE_WORKSPACE_B64" | base64 -d > "$dest.tmp" 2>/dev/null; then
mv "$dest.tmp" "$dest"
echo "Workspace file written: $dest"
else
rm -f "$dest.tmp"
echo "Warning: Failed to write workspace file: $dest"
fi
}

# primary リポジトリのディレクトリへ移動する (ログイン直後の作業場所)。
devbase_enter_primary_dir() {
local work_root="${1:-/work}"
local target="$work_root/${DEVBASE_PRIMARY_DIR:-}"

if [ -z "${DEVBASE_PRIMARY_DIR:-}" ]; then
return 0
fi
if [ -d "$target" ]; then
cd "$target"
echo "Current directory: $(pwd)"
else
echo "Warning: Primary directory does not exist: $target"
fi
}

# テストは関数定義だけを使う (source 時のみ有効な return で以降を読み飛ばす)。
if [ -n "${DEVBASE_ENTRYPOINT_LIB_ONLY:-}" ]; then
return 0 2>/dev/null || exit 0
fi

# Setup authentication credentials from environment variables
USERNAME="${USERNAME:-ubuntu}"

Expand DownExpand Up@@ -261,32 +388,12 @@ done
echo "AI agent settings symlinks setup completed"
# ========================================

# Git operations (optional, don't fail if they error)
if [ -n "$GIT_USER" ] && [ -n "$GIT_REPO" ]; then
# Clone repository only if it doesn't exist
GIT_HOST="${GIT_HOST:-github.com}"
if [ ! -d "$GIT_REPO" ]; then
echo "Cloning repository: $GIT_HOST/$GIT_USER/$GIT_REPO"
git clone "https://$GIT_HOST/$GIT_USER/$GIT_REPO.git" || echo "Warning: Failed to clone repository"
else
echo "Repository already exists: $GIT_REPO"
fi
# Run init.sh from cloned repository root if it exists
[ -f "$GIT_REPO/init.sh" ] && (cd "$GIT_REPO" && ./init.sh) || true
fi

# Move to repository directory if it exists
echo "Current directory before cd: $(pwd)"
if [ -n "$GIT_REPO" ]; then
echo "GIT_REPO=$GIT_REPO"
if [ -d "$GIT_REPO" ]; then
echo "Directory $GIT_REPO exists, changing to it"
cd "$GIT_REPO"
echo "Current directory after cd: $(pwd)"
else
echo "Directory $GIT_REPO does not exist in $(pwd)"
fi
fi
# Repository setup (PLAN32: 1 project = 複数リポジトリ)
# 個々の失敗はコンテナ起動を止めない (関数内で warning 扱い)。
DEVBASE_WORK_ROOT="${DEVBASE_WORK_ROOT:-/work}"
devbase_clone_repos "$DEVBASE_WORK_ROOT"
devbase_write_workspace
devbase_enter_primary_dir "$DEVBASE_WORK_ROOT"

# Signal that entrypoint setup is complete
touch /tmp/entrypoint-ready
Expand Down
3 changes: 3 additions & 0 deletions docs/README.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,6 +45,7 @@ graph TD
| [はじめに](user/getting-started.md) | 前提条件、初回セットアップ、日常ワークフロー |
| [CLI リファレンス](user/cli-reference/README.md) | 全コマンドの構文・オプション・使用例 |
| [プラグインレジストリ](user/plugin-registries.md) | 公開・社内レジストリの一覧と追加方法 |
| [project.yml リファレンス](user/project-yml.md) | プロジェクト設定(複数リポジトリ・scale・エディタ) |
| [環境変数ガイド](user/environment-variables.md) | 3レベル構造、コレクター、ソース同期 |
| [環境変数の暗号化](user/env-encryption.md) | 認証情報を暗号化して保存する / 鍵とチーム共有 / 平文へ戻す |
| [コンテナ操作ガイド](user/container-operations.md) | ライフサイクル、並行開発、ボリューム構造 |
Expand DownExpand Up@@ -101,6 +102,7 @@ docs/
│ │ ├── 04-plugin.md ← plugin グループ
│ │ └── 05-snapshot.md ← snapshot グループ
│ ├── plugin-registries.md ← プラグインレジストリ
│ ├── project-yml.md ← project.yml リファレンス
│ ├── environment-variables.md ← 環境変数ガイド
│ ├── env-encryption.md ← 環境変数の暗号化
│ ├── container-operations.md ← コンテナ操作ガイド
Expand DownExpand Up@@ -128,6 +130,7 @@ docs/
| 環境変数を設定する | [環境変数ガイド](user/environment-variables.md#環境変数の操作) |
| 認証情報を暗号化して保存する | [環境変数の暗号化](user/env-encryption.md) |
| 複数コンテナで並行開発する | [コンテナ操作ガイド](user/container-operations.md#並行開発) |
| 1 つのコンテナで複数リポジトリを扱う | [project.yml リファレンス](user/project-yml.md#複数リポジトリ) |
| データをバックアップ・復元する | [スナップショットガイド](user/snapshot-guide.md) |
| エラーが発生した | [トラブルシューティング](user/troubleshooting.md) |
| 旧 Orca 接続から移行する | [Orca 削除の移行ガイド](user/orca-removal-migration.md) |
Expand Down
22 changes: 21 additions & 1 deletion docs/developer/architecture.md
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
# devbase アーキテクチャ概要

devbase v2.2.0 のアーキテクチャ設計と内部構造について説明する。
devbase v3.0.0 のアーキテクチャ設計と内部構造について説明する。

## 全体構成

Expand DownExpand Up@@ -139,6 +139,26 @@ flowchart LR

`snapshot/manager.py` の `SnapshotManager` クラスが全機能を提供する。差分バックアップとフルバックアップに対応し、zstd 圧縮を使用する。

### project/ -- プロジェクト設定 (project.yml)

`projects/<name>/project.yml` を読み、コンテナとエディタが使える形へ変換する層。
YAML の解釈をホスト側の Python に閉じ込めることで、コンテナ側 (`entrypoint.sh`) は
復号して 1 行ずつ clone するだけで済み、イメージへ YAML パーサ依存を持ち込まない。

| モジュール | 役割 |
|-----------|------|
| `config.py` | `project.yml` の読み込み・`defaults` 継承・検証・正規化 (`ProjectConfig` / `RepoSpec`)。clone プランの符号化 (`encode_repo_plan`) |
| `runtime.py` | コンテナへ渡す環境変数の組み立て (`DEVBASE_REPOS` / `DEVBASE_PRIMARY_DIR` / `DEVBASE_WORKSPACE*`)、multi-root ワークスペース JSON の生成、`scale` の読み書き |
| `migrate.py` | 旧 `env` 形式 (`GIT_USER` / `GIT_REPO` 等) から `project.yml` への変換 |

```mermaid
flowchart LR
Y["project.yml"] --> C["config.py<br/>検証・正規化"]
C --> R["runtime.py<br/>環境変数へ"]
R --> Compose[".docker-compose.scale.yml<br/>dev サービス"]
Compose --> E["entrypoint.sh<br/>復号して clone"]
```

### その他

| ディレクトリ | 役割 |
Expand Down
28 changes: 15 additions & 13 deletions docs/plugin-dev/compose-yml-guidelines.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -71,10 +71,9 @@ flowchart TB
G1["共通APIキー"]
G2["共有設定値"]
end
subgraph level2["レベル2: プロジェクト設定(env)"]
P1["GIT_USER / GIT_REPO"]
P2["WORK_DIR"]
P3["CONTAINER_SCALE"]
subgraph level2["レベル2: プロジェクト環境変数(env)"]
P1["ENABLE_SSH など"]
P2["アプリが読む変数"]
end
subgraph level3["レベル3: プロジェクト機密(.env)"]
S1["プロジェクト固有のAPIキー"]
Expand All@@ -90,7 +89,7 @@ flowchart TB
| レベル | ファイル | Git管理 | 用途 | 例 |
|--------|---------|---------|------|-----|
| 1 | `${DEVBASE_ROOT}/.env` | No | 全プロジェクト共通の設定 | 共通APIキー |
| 2 | `env` | Yes | プロジェクト固有の設定 | `GIT_REPO`, `CONTAINER_SCALE` |
| 2 | `env` | Yes | コンテナへ渡すプロジェクト固有の環境変数 | `ENABLE_SSH` |
| 3 | `.env` | No | プロジェクト固有の機密 | DB接続文字列、秘密鍵 |

---
Expand DownExpand Up@@ -204,9 +203,9 @@ ports:

例: `CONTAINER_INDEX=1` の場合は `13000:3000`、`CONTAINER_INDEX=2` の場合は `23000:3000`

### 5.3 CONTAINER_SCALE の設定
### 5.3 コンテナ数(scale)の設定

`env` ファイルで `CONTAINER_SCALE` を設定すると、`devbase up` 実行時に `.docker-compose.scale.yml` が自動生成され、指定された数のコンテナが起動します。
`project.yml` の `scale` を設定すると、`devbase up` 実行時に `.docker-compose.scale.yml` が自動生成され、指定された数のコンテナが起動します(既定: 2)。詳細は [project.yml リファレンス](../user/project-yml.md) を参照してください

---

Expand DownExpand Up@@ -241,15 +240,18 @@ networks:
external: true
```

対応する `env` ファイル:
対応する `project.yml`:

```bash
GIT_USER=your-org
GIT_REPO=my-webapp
WORK_DIR=/work/$GIT_REPO
CONTAINER_SCALE=1
```yaml
version: 1
scale: 1
repos:
- owner: your-org
repo: my-webapp
```

`env` にはコンテナへ渡す環境変数だけを書きます(無くてもファイル自体は残します。`env_file` が参照するため)。

### 6.2 データベースを含む構成

基本構成に `db` サービスを追加し、`depends_on` で依存関係を定義します。
Expand Down
Loading
Loading