Skip to content

Commit ef4a651

Browse files
committed
Initial commit: devbase v2.2.0
Docker-based Development Environment Manager. Features: - Plugin system (GitHub shorthand support, multi-registry) - Environment variable management (3-level, collectors, source sync) - Container lifecycle (up / down / login / ps / build / scale) - Snapshot management (incremental backup, generation rotation) See docs/ for user / plugin developer / contributor documentation. License: MIT (Copyright 2026 takemi-ohama)
0 parents  commit ef4a651

80 files changed

Lines changed: 11394 additions & 0 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
__pycache__/
2+
.venv/
3+
.env
4+
.env.backup
5+
.docker-compose.scale.yml
6+
plugins.yml
7+
plugins/*/
8+
!plugins/.gitkeep
9+
projects/*
10+
!projects/.gitkeep
11+
.serena/serena_config.yml
12+
.env.sources.yml

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 takemi-ohama
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# devbase
2+
3+
Dockerベースの開発環境マネージャー。コンテナ化された開発環境を**Plugin**によるプロジェクト管理で提供します。
4+
5+
## 概要
6+
7+
devbaseは、Docker Composeを使った再現性の高い開発環境を提供するCLIツールです。プロジェクトはPluginとして外部リポジトリで管理され、`devbase plugin install`でインストールします。
8+
9+
### 主な特徴
10+
11+
- **Pluginベースのプロジェクト管理**: 外部リポジトリからプロジェクト設定をインストール・更新
12+
- **コンテナ化された開発環境**: Docker Composeベースで再現性の高い環境を提供
13+
- **豊富なツールセット**: Docker CLI、AWS CLI、gcloud SDK、Terraform、Node.js、AI CLIツールがプリインストール
14+
- **複数コンテナの並行開発**: `devbase container scale`で既存コンテナを再起動せずにスケール可能
15+
- **データ永続化**: 名前付きボリュームでコンテナ再起動後もデータを保持
16+
- **スナップショット管理**: ホームボリュームのバックアップ・復元・世代管理
17+
- **環境変数の自動収集**: `devbase env init`でAWS/Git/GCP認証情報を対話的に設定
18+
19+
## クイックスタート
20+
21+
```bash
22+
# 1. クローンと初期化
23+
git clone https://github.com/devbasex/devbase.git
24+
cd devbase
25+
./bin/devbase init
26+
source ~/.bashrc # または ~/.zshrc
27+
28+
# 2. Pluginのインストール
29+
devbase plugin repo add user/repo # リポジトリ登録(initで公式は自動登録済み)
30+
devbase plugin install <name> # Plugin名でインストール
31+
32+
# 3. プロジェクトの起動
33+
cd projects/your-project
34+
devbase env init # 環境変数の設定(初回のみ)
35+
devbase build # コンテナイメージのビルド(初回のみ)
36+
devbase up # コンテナを起動
37+
devbase login # コンテナにログイン
38+
```
39+
40+
詳細なセットアップ手順は [はじめに](docs/user/getting-started.md) を参照してください。
41+
42+
## Plugin
43+
44+
devbaseのプロジェクトはPluginとして管理されます。Pluginは外部のGitリポジトリに格納され、リポジトリ登録後に`devbase plugin install`でインストールします。
45+
46+
```bash
47+
# リポジトリ登録(GitHubショートハンド対応)
48+
devbase plugin repo add user/repo
49+
50+
# インストール
51+
devbase plugin install adminer # 名前指定
52+
devbase plugin install user/repo:plugin-name # リポジトリ直接指定
53+
devbase plugin install /path/to/local:name --link # ローカルリンク
54+
55+
# 管理
56+
devbase plugin list # 一覧表示
57+
devbase plugin update # 全Plugin更新
58+
devbase plugin uninstall <name> # アンインストール
59+
```
60+
61+
Pluginをインストールすると、`plugins/<name>/`にリポジトリがクローンされ、内部のプロジェクトが`projects/`にシンボリックリンクとして自動作成されます。
62+
63+
## CLIコマンド体系
64+
65+
devbaseのコマンドは4つのグループにまとめられています。
66+
67+
| グループ | 略記 | 説明 |
68+
|---------|------|------|
69+
| `container` | `ct` | コンテナ管理(up / down / login / ps / logs / scale / build) |
70+
| `env` || 環境変数管理(init / sync / list / set / get / delete / edit / project) |
71+
| `plugin` | `pl` | プラグイン管理(list / install / uninstall / update / info / sync / repo) |
72+
| `snapshot` | `ss` | スナップショット管理(create / list / restore / copy / delete / rotate) |
73+
74+
- **ショートカット**: `up`, `down`, `login`, `build`, `ps` はトップレベルから直接使用可能
75+
- **プレフィックス略記**: `devbase p l``devbase plugin list`
76+
- **トップレベルコマンド**: `init`, `status`
77+
78+
全コマンドの構文・オプション・使用例は [CLIリファレンス](docs/user/cli-reference.md) を参照してください。
79+
80+
## 前提条件
81+
82+
- Docker Engine 20.10以上
83+
- Docker Compose v2.x以上
84+
- Bash 4.0以上 または Zsh 5.0以上
85+
- Python 3.10以上
86+
- Git
87+
88+
## ドキュメント
89+
90+
詳細なドキュメントは [docs/](docs/README.md) に整備されています。
91+
92+
### 利用者向け
93+
94+
| ドキュメント | 内容 |
95+
|-------------|------|
96+
| [はじめに](docs/user/getting-started.md) | 前提条件、初回セットアップ、日常ワークフロー |
97+
| [CLIリファレンス](docs/user/cli-reference.md) | 全コマンドの構文・オプション・使用例 |
98+
| [環境変数ガイド](docs/user/environment-variables.md) | 3レベル構造、コレクター、ソース同期 |
99+
| [コンテナ操作ガイド](docs/user/container-operations.md) | ライフサイクル、並行開発、ボリューム構造 |
100+
| [スナップショットガイド](docs/user/snapshot-guide.md) | 増分バックアップ、世代管理、復元手順 |
101+
| [トラブルシューティング](docs/user/troubleshooting.md) | カテゴリ別の問題と解決策 |
102+
103+
### プラグイン開発者向け
104+
105+
| ドキュメント | 内容 |
106+
|-------------|------|
107+
| [クイックスタート](docs/plugin-dev/quickstart.md) | 最小構成プラグインの作成手順 |
108+
| [plugin.ymlリファレンス](docs/plugin-dev/plugin-yml-reference.md) | プラグイン定義ファイルの全フィールド |
109+
| [compose.ymlガイドライン](docs/plugin-dev/compose-yml-guidelines.md) | Docker Compose設定のベストプラクティス |
110+
111+
### devbase開発者向け
112+
113+
| ドキュメント | 内容 |
114+
|-------------|------|
115+
| [アーキテクチャ](docs/developer/architecture.md) | ディレクトリ構造、モジュール設計、データフロー |
116+
| [コントリビューション](docs/developer/contributing.md) | 開発環境構築、コーディング規約、PRルール |
117+
| [拡張ガイド](docs/developer/extending.md) | 新コマンド・コレクター・イメージの追加方法 |
118+
119+
## リンク
120+
121+
- **リポジトリ**: [devbasex/devbase](https://github.com/devbasex/devbase)
122+
- **Issue報告**: [GitHub Issues](https://github.com/devbasex/devbase/issues)

backups/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*
2+
!.gitignore

bin/devbase

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
#!/bin/bash
2+
set -e
3+
4+
# devbase root directory (where devbase command is installed)
5+
# Resolve symlinks to find the actual location of the devbase script
6+
SCRIPT_PATH="${BASH_SOURCE[0]}"
7+
while [ -L "$SCRIPT_PATH" ]; do
8+
SCRIPT_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
9+
SCRIPT_PATH="$(readlink "$SCRIPT_PATH")"
10+
[[ $SCRIPT_PATH != /* ]] && SCRIPT_PATH="$SCRIPT_DIR/$SCRIPT_PATH"
11+
done
12+
SCRIPT_DIR="$(cd -P "$(dirname "$SCRIPT_PATH")" && pwd)"
13+
DEVBASE_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
14+
15+
# Environment setup
16+
export DOCKER_GID=$( [ "$(uname)" = "Darwin" ] && echo "0" || grep docker /etc/group | cut -d: -f3 )
17+
export COMPOSE_PROJECT_NAME=$(basename "$PWD")
18+
[ -f ".env" ] && set -a && source .env && set +a
19+
[ -f "env" ] && set -a && source ./env && set +a
20+
21+
# Export for Python modules
22+
export DEVBASE_ROOT
23+
24+
# ===================================================================
25+
# Function definitions
26+
# ===================================================================
27+
28+
cmd_build() {
29+
echo "=== Building devbase images ==="
30+
31+
# Helper: Check if Dockerfile uses devbase-* base images
32+
check_base_image_dependency() {
33+
local dockerfile_path="$1"
34+
if [ -f "$dockerfile_path" ]; then
35+
if grep -q "^FROM devbase-" "$dockerfile_path"; then
36+
# Extract base image name (e.g., "devbase-base", "devbase-general")
37+
grep "^FROM devbase-" "$dockerfile_path" | head -1 | awk '{print $2}' | cut -d: -f1
38+
return 0
39+
fi
40+
fi
41+
return 1
42+
}
43+
44+
# Helper: Build base image
45+
build_base_image() {
46+
local base_image="$1"
47+
shift
48+
local container_dir="${DEVBASE_ROOT}/containers/${base_image#devbase-}"
49+
50+
if [ ! -d "$container_dir" ]; then
51+
echo "✗ Container directory not found: $container_dir"
52+
return 1
53+
fi
54+
55+
echo "Building ${base_image}:latest..."
56+
if docker buildx build --load -t "${base_image}:latest" "$container_dir" "$@"; then
57+
echo "${base_image} built successfully"
58+
return 0
59+
else
60+
echo "✗ Failed to build ${base_image}"
61+
return 1
62+
fi
63+
}
64+
65+
# Detect Dockerfile path from compose.yml
66+
local dockerfile_path="Dockerfile"
67+
if [ -f "compose.yml" ]; then
68+
# Try to extract dockerfile path from compose.yml (simple grep approach)
69+
local dockerfile_line=$(grep -A 3 "build:" compose.yml | grep "dockerfile:" | head -1 | awk '{print $2}')
70+
if [ -n "$dockerfile_line" ]; then
71+
dockerfile_path="$dockerfile_line"
72+
fi
73+
74+
# If dockerfile is relative, combine with context path
75+
local context_line=$(grep -A 3 "build:" compose.yml | grep "context:" | head -1 | awk '{print $2}')
76+
if [ -n "$context_line" ]; then
77+
# Expand environment variables in context path
78+
context_line=$(eval echo "$context_line")
79+
if [[ "$dockerfile_path" != /* ]]; then
80+
dockerfile_path="${context_line}/${dockerfile_path}"
81+
fi
82+
fi
83+
fi
84+
85+
# --no-cache specified: always rebuild base first
86+
if [[ "$*" == *"--no-cache"* ]]; then
87+
echo ""
88+
echo "[1/3] Clearing buildx cache..."
89+
docker builder prune -af >/dev/null 2>&1 || true
90+
echo "✓ Buildx cache cleared"
91+
92+
echo ""
93+
echo "[2/3] Building devbase-base..."
94+
if ! build_base_image "devbase-base" "$@"; then
95+
exit 1
96+
fi
97+
98+
echo ""
99+
echo "[3/3] Building project image..."
100+
if docker compose build dev "$@"; then
101+
echo ""
102+
echo "✓ All images built successfully"
103+
else
104+
echo ""
105+
echo "✗ Failed to build project image"
106+
exit 1
107+
fi
108+
return
109+
fi
110+
111+
# Normal build: check if project uses devbase-* base image
112+
local base_image_name=$(check_base_image_dependency "$dockerfile_path")
113+
if [ -n "$base_image_name" ]; then
114+
echo ""
115+
echo "[1/2] Project uses ${base_image_name}, building base image..."
116+
if ! build_base_image "$base_image_name" "$@"; then
117+
exit 1
118+
fi
119+
else
120+
# Fallback: check if devbase-base exists
121+
if ! docker image inspect devbase-base:latest >/dev/null 2>&1; then
122+
echo ""
123+
echo "[1/2] Building devbase-base..."
124+
if ! build_base_image "devbase-base" "$@"; then
125+
exit 1
126+
fi
127+
else
128+
echo "[1/2] devbase-base already exists (use --no-cache to rebuild)"
129+
fi
130+
fi
131+
132+
echo ""
133+
echo "[2/2] Building project image..."
134+
if docker compose build dev "$@"; then
135+
echo ""
136+
echo "✓ All images built successfully"
137+
else
138+
echo ""
139+
echo "✗ Failed to build project image"
140+
exit 1
141+
fi
142+
}
143+
144+
# ===================================================================
145+
# Command dispatch
146+
# ===================================================================
147+
148+
# Ensure uv is available (auto-install if missing)
149+
ensure_uv() {
150+
if command -v uv >/dev/null 2>&1; then
151+
return 0
152+
fi
153+
echo "Installing uv..." >&2
154+
curl -LsSf https://astral.sh/uv/install.sh | sh >/dev/null 2>&1
155+
export PATH="$HOME/.local/bin:$PATH"
156+
if ! command -v uv >/dev/null 2>&1; then
157+
echo "Error: Failed to install uv" >&2
158+
exit 1
159+
fi
160+
}
161+
162+
# Helper to run Python implementation via uv
163+
run_python() {
164+
ensure_uv
165+
PYTHONPATH="${DEVBASE_ROOT}/lib:$PYTHONPATH" exec uv run --project "$DEVBASE_ROOT" python -m devbase.cli "$@"
166+
}
167+
168+
# Resolve abbreviated command to full command name via unique prefix matching
169+
resolve_command() {
170+
local input="$1"
171+
local commands="init status container ct env plugin pl snapshot ss up down login build ps help"
172+
local matches=()
173+
for cmd in $commands; do
174+
[[ "$cmd" == "$input"* ]] && matches+=("$cmd")
175+
done
176+
if [ ${#matches[@]} -eq 1 ]; then
177+
echo "${matches[0]}"
178+
else
179+
echo "$input" # no match or ambiguous -> return as-is
180+
fi
181+
}
182+
183+
# Resolve the command (skip flags like --version, -V, -h, --help)
184+
_resolved_cmd="${1:-}"
185+
case "$_resolved_cmd" in
186+
--*|-*|"") ;; # flags and empty: don't resolve
187+
*) _resolved_cmd="$(resolve_command "$_resolved_cmd")" ;;
188+
esac
189+
190+
case "$_resolved_cmd" in
191+
# Python-implemented commands
192+
--version|-V)
193+
run_python "$@" ;;
194+
init|status|container|ct|env|plugin|pl|snapshot|ss|up|down|login|ps)
195+
run_python "${_resolved_cmd}" "${@:2}" ;;
196+
# Shell-implemented commands
197+
build) shift; cmd_build "$@" ;;
198+
# Help and unknown
199+
-h|--help|help|"") run_python "--help" ;;
200+
*) echo "Error: unknown command '$1'" >&2; exit 1 ;;
201+
esac

0 commit comments

Comments
 (0)