1120 lines
26 KiB
Markdown
1120 lines
26 KiB
Markdown
|
|
# Synology環境 完全構築ロードマップ
|
|||
|
|
|
|||
|
|
**作成日**: 2026-02-23
|
|||
|
|
**期間**: 12週間(3フェーズ)
|
|||
|
|
**目標**: プロダクション品質のAI駆動開発環境構築
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 **Phase 1: インフラ完全構築(Week 1-4)**
|
|||
|
|
|
|||
|
|
### **Week 1: 緊急対応 - 既存システムの安定化**
|
|||
|
|
|
|||
|
|
#### **Day 1-2: Tailscale Funnel 永続化** 🔴 Critical
|
|||
|
|
|
|||
|
|
**目標**: Synology再起動でもGitea外部公開を維持
|
|||
|
|
|
|||
|
|
**タスク**:
|
|||
|
|
```bash
|
|||
|
|
# posimai-lab (100.76.7.3) にSSH接続
|
|||
|
|
ssh admin@100.76.7.3
|
|||
|
|
|
|||
|
|
# systemdサービス化(最も堅牢)
|
|||
|
|
sudo nano /etc/systemd/system/tailscale-funnel.service
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**設定内容**:
|
|||
|
|
```ini
|
|||
|
|
[Unit]
|
|||
|
|
Description=Tailscale Funnel for Gitea
|
|||
|
|
After=network.target tailscaled.service
|
|||
|
|
Requires=tailscaled.service
|
|||
|
|
|
|||
|
|
[Service]
|
|||
|
|
Type=simple
|
|||
|
|
ExecStart=/usr/local/bin/tailscale funnel --bg 3000
|
|||
|
|
Restart=always
|
|||
|
|
RestartSec=10
|
|||
|
|
User=root
|
|||
|
|
|
|||
|
|
[Install]
|
|||
|
|
WantedBy=multi-user.target
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**有効化**:
|
|||
|
|
```bash
|
|||
|
|
sudo systemctl daemon-reload
|
|||
|
|
sudo systemctl enable tailscale-funnel.service
|
|||
|
|
sudo systemctl start tailscale-funnel.service
|
|||
|
|
sudo systemctl status tailscale-funnel.service
|
|||
|
|
|
|||
|
|
# 動作確認
|
|||
|
|
curl https://posimai-lab.tail72e846.ts.net
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**成功基準**:
|
|||
|
|
- ✅ Synology再起動後も自動起動
|
|||
|
|
- ✅ `systemctl status` でactive (running)
|
|||
|
|
- ✅ 外部からGiteaアクセス可能
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### **Day 3-4: バックアップ戦略確立** 🔴 Critical
|
|||
|
|
|
|||
|
|
**目標**: データ損失ゼロ保証
|
|||
|
|
|
|||
|
|
**タスク1: Gitea データバックアップ**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# posimai-lab で実行
|
|||
|
|
sudo nano /usr/local/bin/gitea-backup.sh
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**スクリプト内容**:
|
|||
|
|
```bash
|
|||
|
|
#!/bin/bash
|
|||
|
|
BACKUP_DIR="/volume1/backups/gitea"
|
|||
|
|
DATE=$(date +%Y%m%d_%H%M%S)
|
|||
|
|
GITEA_DIR="/var/lib/gitea"
|
|||
|
|
|
|||
|
|
mkdir -p $BACKUP_DIR
|
|||
|
|
|
|||
|
|
# Giteaバックアップコマンド(公式)
|
|||
|
|
cd /usr/local/bin
|
|||
|
|
./gitea dump -c /etc/gitea/app.ini -f $BACKUP_DIR/gitea-dump-$DATE.zip
|
|||
|
|
|
|||
|
|
# 7日以上古いバックアップを削除
|
|||
|
|
find $BACKUP_DIR -name "gitea-dump-*.zip" -mtime +7 -delete
|
|||
|
|
|
|||
|
|
echo "Backup completed: gitea-dump-$DATE.zip"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**cron設定**:
|
|||
|
|
```bash
|
|||
|
|
# 毎日午前3時にバックアップ
|
|||
|
|
sudo crontab -e
|
|||
|
|
# 追加
|
|||
|
|
0 3 * * * /usr/local/bin/gitea-backup.sh >> /var/log/gitea-backup.log 2>&1
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**タスク2: プロジェクトファイルバックアップ**
|
|||
|
|
|
|||
|
|
**Synology Hyper Backup設定**:
|
|||
|
|
1. DSM → Hyper Backup → 外部ストレージ(USB HDD推奨)
|
|||
|
|
2. 対象ディレクトリ:
|
|||
|
|
- `/volume1/docker/gitea` (Gitea全体)
|
|||
|
|
- `/volume1/projects` (全プロジェクト)
|
|||
|
|
- `/volume1/backups` (バックアップデータ)
|
|||
|
|
3. スケジュール: 毎日午前2時
|
|||
|
|
4. バージョン管理: 30世代保持
|
|||
|
|
|
|||
|
|
**タスク3: 外部クラウドバックアップ(推奨)**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Google Drive同期(rclone使用)
|
|||
|
|
# posimai-lab で実行
|
|||
|
|
curl https://rclone.org/install.sh | sudo bash
|
|||
|
|
rclone config # Google Drive設定
|
|||
|
|
|
|||
|
|
# 自動同期スクリプト
|
|||
|
|
sudo nano /usr/local/bin/gdrive-sync.sh
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**スクリプト内容**:
|
|||
|
|
```bash
|
|||
|
|
#!/bin/bash
|
|||
|
|
rclone sync /volume1/backups gdrive:posimai-backups \
|
|||
|
|
--exclude "*.tmp" \
|
|||
|
|
--log-file=/var/log/rclone-sync.log \
|
|||
|
|
--stats 1m
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**cron設定**:
|
|||
|
|
```bash
|
|||
|
|
# 毎日午前4時にクラウド同期
|
|||
|
|
0 4 * * * /usr/local/bin/gdrive-sync.sh
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**成功基準**:
|
|||
|
|
- ✅ Gitea自動バックアップ(毎日)
|
|||
|
|
- ✅ Synology Hyper Backup設定完了
|
|||
|
|
- ✅ 外部クラウド同期(オプション)
|
|||
|
|
- ✅ リストア手順のドキュメント作成
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### **Day 5-7: PostgreSQL + Redis 導入** 🟡 Important
|
|||
|
|
|
|||
|
|
**目標**: データ永続化とパフォーマンス向上
|
|||
|
|
|
|||
|
|
**タスク1: Docker Compose 統合管理**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# posimai-lab で実行
|
|||
|
|
mkdir -p /volume1/docker/posimai-stack
|
|||
|
|
cd /volume1/docker/posimai-stack
|
|||
|
|
nano docker-compose.yml
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**docker-compose.yml**:
|
|||
|
|
```yaml
|
|||
|
|
version: '3.8'
|
|||
|
|
|
|||
|
|
services:
|
|||
|
|
# PostgreSQL - 将来のアプリ用データベース
|
|||
|
|
postgres:
|
|||
|
|
image: postgres:16-alpine
|
|||
|
|
container_name: posimai-postgres
|
|||
|
|
restart: always
|
|||
|
|
environment:
|
|||
|
|
POSTGRES_USER: posimai
|
|||
|
|
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
|||
|
|
POSTGRES_DB: posimai_db
|
|||
|
|
volumes:
|
|||
|
|
- /volume1/docker/postgres/data:/var/lib/postgresql/data
|
|||
|
|
ports:
|
|||
|
|
- "5432:5432"
|
|||
|
|
networks:
|
|||
|
|
- posimai-net
|
|||
|
|
healthcheck:
|
|||
|
|
test: ["CMD-SHELL", "pg_isready -U posimai"]
|
|||
|
|
interval: 10s
|
|||
|
|
timeout: 5s
|
|||
|
|
retries: 5
|
|||
|
|
|
|||
|
|
# Redis - Proxyレート制限 & キャッシュ
|
|||
|
|
redis:
|
|||
|
|
image: redis:7-alpine
|
|||
|
|
container_name: posimai-redis
|
|||
|
|
restart: always
|
|||
|
|
command: redis-server --appendonly yes
|
|||
|
|
volumes:
|
|||
|
|
- /volume1/docker/redis/data:/data
|
|||
|
|
ports:
|
|||
|
|
- "6379:6379"
|
|||
|
|
networks:
|
|||
|
|
- posimai-net
|
|||
|
|
healthcheck:
|
|||
|
|
test: ["CMD", "redis-cli", "ping"]
|
|||
|
|
interval: 10s
|
|||
|
|
timeout: 5s
|
|||
|
|
retries: 5
|
|||
|
|
|
|||
|
|
# Gemini Proxy - レート制限永続化版
|
|||
|
|
gemini-proxy:
|
|||
|
|
build: ./proxy
|
|||
|
|
container_name: posimai-gemini-proxy
|
|||
|
|
restart: always
|
|||
|
|
environment:
|
|||
|
|
GEMINI_API_KEY: ${GEMINI_API_KEY}
|
|||
|
|
REDIS_HOST: redis
|
|||
|
|
REDIS_PORT: 6379
|
|||
|
|
ports:
|
|||
|
|
- "3001:3001"
|
|||
|
|
networks:
|
|||
|
|
- posimai-net
|
|||
|
|
depends_on:
|
|||
|
|
redis:
|
|||
|
|
condition: service_healthy
|
|||
|
|
|
|||
|
|
networks:
|
|||
|
|
posimai-net:
|
|||
|
|
driver: bridge
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**.env設定**:
|
|||
|
|
```bash
|
|||
|
|
nano .env
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
POSTGRES_PASSWORD=your_secure_password_here
|
|||
|
|
GEMINI_API_KEY=your_gemini_api_key
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**起動**:
|
|||
|
|
```bash
|
|||
|
|
docker-compose up -d
|
|||
|
|
docker-compose ps # 全て healthy確認
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**タスク2: Proxy サーバー Redis対応**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
mkdir -p /volume1/docker/posimai-stack/proxy
|
|||
|
|
cd /volume1/docker/posimai-stack/proxy
|
|||
|
|
nano server.js
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**server.js(Redis永続化版)**:
|
|||
|
|
```javascript
|
|||
|
|
const express = require('express');
|
|||
|
|
const { GoogleGenerativeAI } = require('@google/generative-ai');
|
|||
|
|
const redis = require('redis');
|
|||
|
|
|
|||
|
|
const app = express();
|
|||
|
|
const PORT = 3001;
|
|||
|
|
|
|||
|
|
// Redis接続
|
|||
|
|
const redisClient = redis.createClient({
|
|||
|
|
url: `redis://${process.env.REDIS_HOST}:${process.env.REDIS_PORT}`
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
redisClient.on('error', (err) => console.error('Redis Error:', err));
|
|||
|
|
redisClient.connect();
|
|||
|
|
|
|||
|
|
// Gemini初期化
|
|||
|
|
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
|
|||
|
|
|
|||
|
|
app.use(express.json());
|
|||
|
|
|
|||
|
|
// レート制限チェック(Redis永続化)
|
|||
|
|
async function checkRateLimit(userId) {
|
|||
|
|
const today = new Date().toISOString().split('T')[0];
|
|||
|
|
const key = `quota:${userId}:${today}`;
|
|||
|
|
|
|||
|
|
const count = await redisClient.get(key);
|
|||
|
|
|
|||
|
|
if (!count) {
|
|||
|
|
// 初回アクセス - 明日0時にexpire
|
|||
|
|
const tomorrow = new Date();
|
|||
|
|
tomorrow.setDate(tomorrow.getDate() + 1);
|
|||
|
|
tomorrow.setHours(0, 0, 0, 0);
|
|||
|
|
const ttl = Math.floor((tomorrow - new Date()) / 1000);
|
|||
|
|
|
|||
|
|
await redisClient.set(key, 1, { EX: ttl });
|
|||
|
|
return { allowed: true, count: 1, limit: 1000 };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const currentCount = parseInt(count);
|
|||
|
|
|
|||
|
|
if (currentCount >= 1000) {
|
|||
|
|
return { allowed: false, count: currentCount, limit: 1000 };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
await redisClient.incr(key);
|
|||
|
|
return { allowed: true, count: currentCount + 1, limit: 1000 };
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// プロキシエンドポイント
|
|||
|
|
app.post('/api/gemini', async (req, res) => {
|
|||
|
|
const userId = req.body.userId || 'anonymous';
|
|||
|
|
|
|||
|
|
// レート制限チェック
|
|||
|
|
const rateLimit = await checkRateLimit(userId);
|
|||
|
|
|
|||
|
|
if (!rateLimit.allowed) {
|
|||
|
|
return res.status(429).json({
|
|||
|
|
error: 'Rate limit exceeded',
|
|||
|
|
quota: rateLimit
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
try {
|
|||
|
|
const model = genAI.getGenerativeModel({
|
|||
|
|
model: 'gemini-2.0-flash-exp',
|
|||
|
|
generationConfig: { responseMimeType: 'application/json' }
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const result = await model.generateContent(req.body.prompt);
|
|||
|
|
const response = result.response.text();
|
|||
|
|
|
|||
|
|
res.json({
|
|||
|
|
result: JSON.parse(response),
|
|||
|
|
quota: rateLimit
|
|||
|
|
});
|
|||
|
|
} catch (error) {
|
|||
|
|
console.error('Gemini API Error:', error);
|
|||
|
|
res.status(500).json({ error: error.message });
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
app.listen(PORT, '0.0.0.0', () => {
|
|||
|
|
console.log(`Proxy listening on http://0.0.0.0:${PORT}`);
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Dockerfile**:
|
|||
|
|
```dockerfile
|
|||
|
|
FROM node:20-alpine
|
|||
|
|
WORKDIR /app
|
|||
|
|
COPY package.json .
|
|||
|
|
RUN npm install
|
|||
|
|
COPY server.js .
|
|||
|
|
EXPOSE 3001
|
|||
|
|
CMD ["node", "server.js"]
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**package.json**:
|
|||
|
|
```json
|
|||
|
|
{
|
|||
|
|
"name": "gemini-proxy",
|
|||
|
|
"version": "2.0.0",
|
|||
|
|
"dependencies": {
|
|||
|
|
"express": "^4.18.2",
|
|||
|
|
"@google/generative-ai": "^0.21.0",
|
|||
|
|
"redis": "^4.7.0"
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**再ビルド・再起動**:
|
|||
|
|
```bash
|
|||
|
|
cd /volume1/docker/posimai-stack
|
|||
|
|
docker-compose build gemini-proxy
|
|||
|
|
docker-compose up -d
|
|||
|
|
docker-compose logs -f gemini-proxy # 動作確認
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**成功基準**:
|
|||
|
|
- ✅ PostgreSQL起動・接続確認
|
|||
|
|
- ✅ Redis起動・接続確認
|
|||
|
|
- ✅ Proxy サーバーがRedis経由でレート制限管理
|
|||
|
|
- ✅ Synology再起動後も自動起動
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **Week 2: 監視・アラート - 障害を即座に検知**
|
|||
|
|
|
|||
|
|
#### **Day 8-10: Uptime Kuma 導入** 🟡 Important
|
|||
|
|
|
|||
|
|
**目標**: ダウンタイムを即座に検知・通知
|
|||
|
|
|
|||
|
|
**タスク1: Uptime Kuma インストール**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# posimai-lab で実行
|
|||
|
|
cd /volume1/docker/posimai-stack
|
|||
|
|
nano docker-compose.yml
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**docker-compose.yml に追加**:
|
|||
|
|
```yaml
|
|||
|
|
# Uptime Kuma - 監視・アラート
|
|||
|
|
uptime-kuma:
|
|||
|
|
image: louislam/uptime-kuma:1
|
|||
|
|
container_name: posimai-uptime-kuma
|
|||
|
|
restart: always
|
|||
|
|
volumes:
|
|||
|
|
- /volume1/docker/uptime-kuma:/app/data
|
|||
|
|
ports:
|
|||
|
|
- "3002:3001"
|
|||
|
|
networks:
|
|||
|
|
- posimai-net
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**起動**:
|
|||
|
|
```bash
|
|||
|
|
docker-compose up -d uptime-kuma
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**初期設定**:
|
|||
|
|
1. ブラウザで `http://100.76.7.3:3002` にアクセス
|
|||
|
|
2. 管理者アカウント作成
|
|||
|
|
3. 監視対象を追加:
|
|||
|
|
- **Gitea**: https://posimai-lab.tail72e846.ts.net (HTTP 200)
|
|||
|
|
- **Vercel配布ページ**: https://ponshu-room.vercel.app (HTTP 200)
|
|||
|
|
- **Proxy API**: http://localhost:3001/health (HTTP 200)
|
|||
|
|
- **PostgreSQL**: TCP接続 localhost:5432
|
|||
|
|
- **Redis**: TCP接続 localhost:6379
|
|||
|
|
|
|||
|
|
**タスク2: 通知設定**
|
|||
|
|
|
|||
|
|
**Slack通知** (推奨):
|
|||
|
|
1. Slack App作成 → Incoming Webhook URL取得
|
|||
|
|
2. Uptime Kuma → Settings → Notifications → Slack
|
|||
|
|
3. Webhook URL入力
|
|||
|
|
4. テスト送信
|
|||
|
|
|
|||
|
|
**メール通知** (代替):
|
|||
|
|
1. Uptime Kuma → Settings → Notifications → Email (SMTP)
|
|||
|
|
2. Gmail SMTP設定:
|
|||
|
|
- Host: smtp.gmail.com
|
|||
|
|
- Port: 587
|
|||
|
|
- Username: your-email@gmail.com
|
|||
|
|
- Password: App Password(2段階認証必須)
|
|||
|
|
|
|||
|
|
**成功基準**:
|
|||
|
|
- ✅ 全サービスが "Up" 状態
|
|||
|
|
- ✅ ダウン時にSlack/メール通知
|
|||
|
|
- ✅ 稼働率グラフ表示
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### **Day 11-14: ログ集約・分析基盤** 🟢 Nice to Have
|
|||
|
|
|
|||
|
|
**目標**: トラブルシューティング効率化
|
|||
|
|
|
|||
|
|
**Option A: Loki + Grafana(軽量)**
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
# Loki - ログ集約
|
|||
|
|
loki:
|
|||
|
|
image: grafana/loki:latest
|
|||
|
|
container_name: posimai-loki
|
|||
|
|
restart: always
|
|||
|
|
ports:
|
|||
|
|
- "3100:3100"
|
|||
|
|
volumes:
|
|||
|
|
- /volume1/docker/loki:/loki
|
|||
|
|
networks:
|
|||
|
|
- posimai-net
|
|||
|
|
|
|||
|
|
# Grafana - 可視化
|
|||
|
|
grafana:
|
|||
|
|
image: grafana/grafana:latest
|
|||
|
|
container_name: posimai-grafana
|
|||
|
|
restart: always
|
|||
|
|
ports:
|
|||
|
|
- "3003:3000"
|
|||
|
|
environment:
|
|||
|
|
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD}
|
|||
|
|
volumes:
|
|||
|
|
- /volume1/docker/grafana:/var/lib/grafana
|
|||
|
|
networks:
|
|||
|
|
- posimai-net
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Option B: スキップ(Week 2-4で時間不足の場合)**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **Week 3-4: CI/CD構築 - デプロイ完全自動化**
|
|||
|
|
|
|||
|
|
#### **Day 15-18: Gitea Actions 設定** 🟡 Important
|
|||
|
|
|
|||
|
|
**目標**: git push だけで自動ビルド・デプロイ
|
|||
|
|
|
|||
|
|
**タスク1: Gitea Actions 有効化**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# posimai-lab で実行
|
|||
|
|
sudo nano /etc/gitea/app.ini
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**app.ini 追加**:
|
|||
|
|
```ini
|
|||
|
|
[actions]
|
|||
|
|
ENABLED = true
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Gitea再起動**:
|
|||
|
|
```bash
|
|||
|
|
sudo systemctl restart gitea
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**タスク2: Runner 登録**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Runner用ディレクトリ作成
|
|||
|
|
mkdir -p /volume1/docker/gitea-runner
|
|||
|
|
cd /volume1/docker/gitea-runner
|
|||
|
|
|
|||
|
|
# Runner起動(Docker版)
|
|||
|
|
docker run -d \
|
|||
|
|
--name gitea-runner \
|
|||
|
|
--restart always \
|
|||
|
|
-v /volume1/docker/gitea-runner:/data \
|
|||
|
|
-v /var/run/docker.sock:/var/run/docker.sock \
|
|||
|
|
gitea/act_runner:latest
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Runner登録**:
|
|||
|
|
1. Gitea Web UI → Settings → Actions → Runners
|
|||
|
|
2. 登録トークン取得
|
|||
|
|
3. Runner登録:
|
|||
|
|
```bash
|
|||
|
|
docker exec -it gitea-runner \
|
|||
|
|
act_runner register \
|
|||
|
|
--instance http://100.76.7.3:3000 \
|
|||
|
|
--token YOUR_REGISTRATION_TOKEN
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**タスク3: Workflow 作成**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# ponshu_room_lite リポジトリ
|
|||
|
|
cd /path/to/ponshu_room_lite
|
|||
|
|
mkdir -p .gitea/workflows
|
|||
|
|
nano .gitea/workflows/release.yml
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**.gitea/workflows/release.yml**:
|
|||
|
|
```yaml
|
|||
|
|
name: Auto Release to Gitea & Vercel
|
|||
|
|
|
|||
|
|
on:
|
|||
|
|
push:
|
|||
|
|
tags:
|
|||
|
|
- 'v*.*.*'
|
|||
|
|
|
|||
|
|
jobs:
|
|||
|
|
build-and-release:
|
|||
|
|
runs-on: ubuntu-latest
|
|||
|
|
|
|||
|
|
steps:
|
|||
|
|
- name: Checkout code
|
|||
|
|
uses: actions/checkout@v4
|
|||
|
|
|
|||
|
|
- name: Setup Flutter
|
|||
|
|
uses: subosito/flutter-action@v2
|
|||
|
|
with:
|
|||
|
|
flutter-version: '3.19.0'
|
|||
|
|
|
|||
|
|
- name: Build APKs
|
|||
|
|
run: |
|
|||
|
|
chmod +x build_all_apks.sh
|
|||
|
|
./build_all_apks.sh
|
|||
|
|
|
|||
|
|
- name: Release to Gitea
|
|||
|
|
env:
|
|||
|
|
GITEA_TOKEN: ${{ secrets.GITEA_TOKEN }}
|
|||
|
|
run: |
|
|||
|
|
pwsh -ExecutionPolicy Bypass -File release_to_gitea.ps1
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Secrets設定**:
|
|||
|
|
1. Gitea → ponshu_room_lite → Settings → Secrets
|
|||
|
|
2. 追加: `GITEA_TOKEN` = あなたのGiteaトークン
|
|||
|
|
|
|||
|
|
**テスト**:
|
|||
|
|
```bash
|
|||
|
|
git tag v1.0.17
|
|||
|
|
git push origin v1.0.17
|
|||
|
|
# → 自動でAPKビルド・リリース・Vercelデプロイ
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**成功基準**:
|
|||
|
|
- ✅ タグpushで自動ビルド開始
|
|||
|
|
- ✅ APK 4本自動生成
|
|||
|
|
- ✅ Giteaリリース自動作成
|
|||
|
|
- ✅ Vercel自動デプロイ
|
|||
|
|
- ✅ 所要時間: 15分以内
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### **Day 19-21: マルチプロジェクト対応** 🟡 Important
|
|||
|
|
|
|||
|
|
**目標**: 日本酒アプリ以外もCI/CD対応
|
|||
|
|
|
|||
|
|
**タスク1: 共通Workflowテンプレート作成**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Giteaに共通テンプレートリポジトリ作成
|
|||
|
|
mkdir -p /volume1/projects/workflow-templates
|
|||
|
|
cd /volume1/projects/workflow-templates
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**flutter-release-template.yml**:
|
|||
|
|
```yaml
|
|||
|
|
name: Flutter APK Release
|
|||
|
|
|
|||
|
|
on:
|
|||
|
|
push:
|
|||
|
|
tags:
|
|||
|
|
- 'v*'
|
|||
|
|
|
|||
|
|
jobs:
|
|||
|
|
release:
|
|||
|
|
runs-on: ubuntu-latest
|
|||
|
|
steps:
|
|||
|
|
- uses: actions/checkout@v4
|
|||
|
|
- uses: subosito/flutter-action@v2
|
|||
|
|
- run: flutter pub get
|
|||
|
|
- run: flutter build apk --release
|
|||
|
|
- run: |
|
|||
|
|
# リリース作成スクリプト
|
|||
|
|
# プロジェクトごとにカスタマイズ
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**タスク2: スキャンアプリCI/CD設定**
|
|||
|
|
|
|||
|
|
(日本酒アプリと同様の手順)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
#### **Day 22-28: ドキュメント整備**
|
|||
|
|
|
|||
|
|
**成果物**:
|
|||
|
|
1. **インフラ運用マニュアル** (INFRASTRUCTURE_MANUAL.md)
|
|||
|
|
- 各サービスの起動/停止方法
|
|||
|
|
- トラブルシューティング
|
|||
|
|
- 復旧手順
|
|||
|
|
|
|||
|
|
2. **CI/CDガイド** (CICD_GUIDE.md)
|
|||
|
|
- Workflowの書き方
|
|||
|
|
- Secretsの管理方法
|
|||
|
|
- デプロイフロー図
|
|||
|
|
|
|||
|
|
3. **緊急時対応マニュアル** (EMERGENCY_PROCEDURES.md)
|
|||
|
|
- Synologyダウン時の対応
|
|||
|
|
- データリストア手順
|
|||
|
|
- 連絡先リスト
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 **Phase 2: プロジェクト構造最適化(Week 5-8)**
|
|||
|
|
|
|||
|
|
### **Week 5-6: 共通資産の抽出**
|
|||
|
|
|
|||
|
|
#### **目標**: AI分析・OCR等を00_coreに集約
|
|||
|
|
|
|||
|
|
**現状の問題**:
|
|||
|
|
```
|
|||
|
|
ponshu_room_lite/
|
|||
|
|
├─ lib/services/gemini_service.dart # AI分析
|
|||
|
|
├─ lib/services/ocr_service.dart # OCR
|
|||
|
|
|
|||
|
|
scan_app/ # 未完成プロジェクト
|
|||
|
|
├─ lib/services/gemini_service.dart # 重複!
|
|||
|
|
├─ lib/services/ocr_service.dart # 重複!
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**理想の構造**:
|
|||
|
|
```
|
|||
|
|
posimai-project/
|
|||
|
|
├─ 00_core/ # 共通ライブラリ
|
|||
|
|
│ ├─ packages/
|
|||
|
|
│ │ ├─ posimai_ai/ # Gemini統合
|
|||
|
|
│ │ │ ├─ lib/
|
|||
|
|
│ │ │ │ ├─ gemini_client.dart
|
|||
|
|
│ │ │ │ ├─ proxy_client.dart
|
|||
|
|
│ │ │ │ └─ rate_limiter.dart
|
|||
|
|
│ │ │ └─ pubspec.yaml
|
|||
|
|
│ │ │
|
|||
|
|
│ │ ├─ posimai_ocr/ # OCR統合
|
|||
|
|
│ │ │ ├─ lib/ocr_service.dart
|
|||
|
|
│ │ │ └─ pubspec.yaml
|
|||
|
|
│ │ │
|
|||
|
|
│ │ └─ posimai_ui/ # 共通UIコンポーネント
|
|||
|
|
│ │ ├─ lib/
|
|||
|
|
│ │ │ ├─ theme.dart
|
|||
|
|
│ │ │ ├─ widgets/loading.dart
|
|||
|
|
│ │ │ └─ widgets/error_dialog.dart
|
|||
|
|
│ │ └─ pubspec.yaml
|
|||
|
|
│ │
|
|||
|
|
│ └─ docs/
|
|||
|
|
│ ├─ ARCHITECTURE.md
|
|||
|
|
│ └─ API_REFERENCE.md
|
|||
|
|
│
|
|||
|
|
├─ ponshu_room_lite/ # 日本酒アプリ
|
|||
|
|
│ └─ pubspec.yaml
|
|||
|
|
│ dependencies:
|
|||
|
|
│ posimai_ai:
|
|||
|
|
│ path: ../00_core/packages/posimai_ai
|
|||
|
|
│
|
|||
|
|
└─ scan_app/ # スキャンアプリ
|
|||
|
|
└─ pubspec.yaml
|
|||
|
|
dependencies:
|
|||
|
|
posimai_ai:
|
|||
|
|
path: ../00_core/packages/posimai_ai
|
|||
|
|
posimai_ocr:
|
|||
|
|
path: ../00_core/packages/posimai_ocr
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**実装手順**:
|
|||
|
|
|
|||
|
|
**Day 29-32: posimai_ai パッケージ作成**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd /volume1/projects/posimai-project
|
|||
|
|
mkdir -p 00_core/packages/posimai_ai
|
|||
|
|
cd 00_core/packages/posimai_ai
|
|||
|
|
|
|||
|
|
flutter create --template=package posimai_ai
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**pubspec.yaml**:
|
|||
|
|
```yaml
|
|||
|
|
name: posimai_ai
|
|||
|
|
version: 1.0.0
|
|||
|
|
description: Posimai AI統合ライブラリ(Gemini API + Proxy対応)
|
|||
|
|
|
|||
|
|
dependencies:
|
|||
|
|
flutter:
|
|||
|
|
sdk: flutter
|
|||
|
|
http: ^1.1.0
|
|||
|
|
|
|||
|
|
dev_dependencies:
|
|||
|
|
flutter_test:
|
|||
|
|
sdk: flutter
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**lib/gemini_client.dart**:
|
|||
|
|
```dart
|
|||
|
|
/// ponshu_room_lite/lib/services/gemini_service.dart から抽出
|
|||
|
|
class GeminiClient {
|
|||
|
|
final String? apiKey;
|
|||
|
|
final String? proxyUrl;
|
|||
|
|
final bool useProxy;
|
|||
|
|
|
|||
|
|
GeminiClient({
|
|||
|
|
this.apiKey,
|
|||
|
|
this.proxyUrl,
|
|||
|
|
this.useProxy = false,
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
Future<Map<String, dynamic>> analyze({
|
|||
|
|
required String prompt,
|
|||
|
|
String? imageBase64,
|
|||
|
|
}) async {
|
|||
|
|
if (useProxy) {
|
|||
|
|
return _analyzeViaProxy(prompt, imageBase64);
|
|||
|
|
} else {
|
|||
|
|
return _analyzeDirectAPI(prompt, imageBase64);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 実装...
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Day 33-35: 日本酒アプリを共通パッケージに移行**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd ponshu_room_lite
|
|||
|
|
nano pubspec.yaml
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**追加**:
|
|||
|
|
```yaml
|
|||
|
|
dependencies:
|
|||
|
|
posimai_ai:
|
|||
|
|
path: ../00_core/packages/posimai_ai
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**lib/services/gemini_service.dart 書き換え**:
|
|||
|
|
```dart
|
|||
|
|
// 変更前
|
|||
|
|
class GeminiService {
|
|||
|
|
// 全実装がここに...
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 変更後
|
|||
|
|
import 'package:posimai_ai/posimai_ai.dart';
|
|||
|
|
|
|||
|
|
class GeminiService {
|
|||
|
|
final GeminiClient _client;
|
|||
|
|
|
|||
|
|
GeminiService()
|
|||
|
|
: _client = GeminiClient(
|
|||
|
|
apiKey: Secrets.geminiApiKey,
|
|||
|
|
useProxy: Secrets.useProxy,
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
Future<SakeAnalysisResult> analyzeSake(String imageBase64) async {
|
|||
|
|
final result = await _client.analyze(
|
|||
|
|
prompt: '...日本酒分析プロンプト...',
|
|||
|
|
imageBase64: imageBase64,
|
|||
|
|
);
|
|||
|
|
return SakeAnalysisResult.fromJson(result);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**テスト**:
|
|||
|
|
```bash
|
|||
|
|
flutter test
|
|||
|
|
flutter run # 動作確認
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**成功基準**:
|
|||
|
|
- ✅ 日本酒アプリが共通パッケージで動作
|
|||
|
|
- ✅ テスト全てパス
|
|||
|
|
- ✅ ビルドサイズ変化なし
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **Week 7-8: 新プロジェクトテンプレート作成**
|
|||
|
|
|
|||
|
|
**目標**: 新規アプリを30分で立ち上げ
|
|||
|
|
|
|||
|
|
**テンプレート作成**:
|
|||
|
|
```bash
|
|||
|
|
cd /volume1/projects/posimai-project/00_core
|
|||
|
|
mkdir -p templates/flutter_app_template
|
|||
|
|
cd templates/flutter_app_template
|
|||
|
|
|
|||
|
|
flutter create --org com.posimai flutter_app_template
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**事前設定済みの内容**:
|
|||
|
|
- ✅ posimai_ai, posimai_ui 依存関係
|
|||
|
|
- ✅ ダークモード対応テーマ
|
|||
|
|
- ✅ Hive永続化設定
|
|||
|
|
- ✅ 多言語対応(日英)
|
|||
|
|
- ✅ CI/CD Workflow (.gitea/workflows/release.yml)
|
|||
|
|
- ✅ README.md(開発手順)
|
|||
|
|
|
|||
|
|
**新規プロジェクト作成スクリプト**:
|
|||
|
|
```bash
|
|||
|
|
nano /usr/local/bin/posimai-new-project
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**スクリプト内容**:
|
|||
|
|
```bash
|
|||
|
|
#!/bin/bash
|
|||
|
|
PROJECT_NAME=$1
|
|||
|
|
|
|||
|
|
if [ -z "$PROJECT_NAME" ]; then
|
|||
|
|
echo "Usage: posimai-new-project <project_name>"
|
|||
|
|
exit 1
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
cd /volume1/projects/posimai-project
|
|||
|
|
cp -r 00_core/templates/flutter_app_template $PROJECT_NAME
|
|||
|
|
cd $PROJECT_NAME
|
|||
|
|
|
|||
|
|
# プロジェクト名置換
|
|||
|
|
find . -type f -exec sed -i "s/flutter_app_template/$PROJECT_NAME/g" {} \;
|
|||
|
|
|
|||
|
|
echo "✅ Project created: $PROJECT_NAME"
|
|||
|
|
echo "Next steps:"
|
|||
|
|
echo " cd $PROJECT_NAME"
|
|||
|
|
echo " flutter pub get"
|
|||
|
|
echo " flutter run"
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**使い方**:
|
|||
|
|
```bash
|
|||
|
|
# 香道アプリを30分で立ち上げ
|
|||
|
|
posimai-new-project kodo_app
|
|||
|
|
cd kodo_app
|
|||
|
|
flutter pub get
|
|||
|
|
flutter run # 即座に動作するテンプレート
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 **Phase 3: AI駆動開発の高速化(Week 9-12)**
|
|||
|
|
|
|||
|
|
### **Week 9-10: AI開発ワークフロー最適化**
|
|||
|
|
|
|||
|
|
#### **目標**: Claude + Antigravity の協調効率を最大化
|
|||
|
|
|
|||
|
|
**現状の問題**:
|
|||
|
|
- Claude Code, Antigravity, Geminiを手動で切り替え
|
|||
|
|
- コンテキスト共有が手動(コピペ)
|
|||
|
|
- レビュー結果の蓄積なし
|
|||
|
|
|
|||
|
|
**理想の姿**:
|
|||
|
|
```
|
|||
|
|
git push
|
|||
|
|
→ Gitea Actions起動
|
|||
|
|
→ Claude Codeが自動コードレビュー
|
|||
|
|
→ Antigravityが自動修正提案
|
|||
|
|
→ 人間が承認
|
|||
|
|
→ 自動マージ・デプロイ
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**実装: AI Code Review Bot**
|
|||
|
|
|
|||
|
|
**タスク1: Gitea Webhook設定**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# posimai-lab で実行
|
|||
|
|
cd /volume1/docker/posimai-stack
|
|||
|
|
mkdir -p ai-review-bot
|
|||
|
|
cd ai-review-bot
|
|||
|
|
nano server.js
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**server.js**:
|
|||
|
|
```javascript
|
|||
|
|
const express = require('express');
|
|||
|
|
const { exec } = require('child_process');
|
|||
|
|
|
|||
|
|
const app = express();
|
|||
|
|
app.use(express.json());
|
|||
|
|
|
|||
|
|
// Gitea Webhookエンドポイント
|
|||
|
|
app.post('/webhook/gitea', async (req, res) => {
|
|||
|
|
const { action, pull_request } = req.body;
|
|||
|
|
|
|||
|
|
if (action === 'opened' || action === 'synchronized') {
|
|||
|
|
const prNumber = pull_request.number;
|
|||
|
|
const repo = pull_request.base.repo.full_name;
|
|||
|
|
|
|||
|
|
console.log(`New PR #${prNumber} in ${repo}`);
|
|||
|
|
|
|||
|
|
// Claude Code でレビュー実行
|
|||
|
|
exec(`claude-code review ${repo} ${prNumber}`, (error, stdout) => {
|
|||
|
|
if (error) {
|
|||
|
|
console.error('Review failed:', error);
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
console.log('Review completed:', stdout);
|
|||
|
|
|
|||
|
|
// レビュー結果をPRコメントに投稿
|
|||
|
|
// ... Gitea API経由でコメント投稿 ...
|
|||
|
|
});
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
res.sendStatus(200);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
app.listen(3004, () => {
|
|||
|
|
console.log('AI Review Bot listening on port 3004');
|
|||
|
|
});
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**Gitea Webhook設定**:
|
|||
|
|
1. Gitea → リポジトリ → Settings → Webhooks
|
|||
|
|
2. URL: `http://localhost:3004/webhook/gitea`
|
|||
|
|
3. イベント: Pull Request
|
|||
|
|
|
|||
|
|
**成功基準**:
|
|||
|
|
- ✅ PR作成で自動レビュー開始
|
|||
|
|
- ✅ レビュー結果がPRコメントに投稿
|
|||
|
|
- ✅ 人間が承認→自動マージ
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### **Week 11-12: ドキュメント自動生成 & ナレッジベース構築**
|
|||
|
|
|
|||
|
|
**目標**: AI開発の学習を蓄積
|
|||
|
|
|
|||
|
|
**タスク1: 自動ドキュメント生成**
|
|||
|
|
|
|||
|
|
```yaml
|
|||
|
|
# .gitea/workflows/docs.yml
|
|||
|
|
name: Auto Documentation
|
|||
|
|
|
|||
|
|
on:
|
|||
|
|
push:
|
|||
|
|
branches:
|
|||
|
|
- main
|
|||
|
|
|
|||
|
|
jobs:
|
|||
|
|
generate-docs:
|
|||
|
|
runs-on: ubuntu-latest
|
|||
|
|
steps:
|
|||
|
|
- uses: actions/checkout@v4
|
|||
|
|
|
|||
|
|
- name: Generate API docs
|
|||
|
|
run: |
|
|||
|
|
flutter pub get
|
|||
|
|
flutter pub run dartdoc
|
|||
|
|
|
|||
|
|
- name: Deploy to GitHub Pages
|
|||
|
|
uses: peaceiris/actions-gh-pages@v3
|
|||
|
|
with:
|
|||
|
|
github_token: ${{ secrets.GITEA_TOKEN }}
|
|||
|
|
publish_dir: ./doc/api
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**タスク2: ナレッジベース(Obsidian連携)**
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Synologyに Obsidian Vault作成
|
|||
|
|
mkdir -p /volume1/projects/posimai-knowledge
|
|||
|
|
cd /volume1/projects/posimai-knowledge
|
|||
|
|
|
|||
|
|
# 構造
|
|||
|
|
# ├─ AI開発ログ/
|
|||
|
|
# │ ├─ 2026-02-23_配布システム構築.md
|
|||
|
|
# │ └─ 2026-02-24_共通パッケージ化.md
|
|||
|
|
# ├─ トラブルシューティング/
|
|||
|
|
# │ ├─ Flutter_ビルドエラー集.md
|
|||
|
|
# │ └─ Docker_ネットワーク問題.md
|
|||
|
|
# └─ アーキテクチャ決定記録/
|
|||
|
|
# ├─ ADR-001_Tailscale-Funnel選定.md
|
|||
|
|
# └─ ADR-002_共通パッケージ戦略.md
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**自動連携スクリプト**:
|
|||
|
|
```bash
|
|||
|
|
#!/bin/bash
|
|||
|
|
# git commit時に自動でナレッジベースにログ追加
|
|||
|
|
|
|||
|
|
DATE=$(date +%Y-%m-%d)
|
|||
|
|
LOG_FILE="/volume1/projects/posimai-knowledge/AI開発ログ/${DATE}_作業ログ.md"
|
|||
|
|
|
|||
|
|
echo "## $(date +%H:%M) - $1" >> $LOG_FILE
|
|||
|
|
git log -1 --pretty=format:"%B" >> $LOG_FILE
|
|||
|
|
echo "" >> $LOG_FILE
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📊 **Phase別優先順位マトリクス**
|
|||
|
|
|
|||
|
|
| フェーズ | 必須 (Must Have) | 重要 (Should Have) | あれば良い (Nice to Have) |
|
|||
|
|
|---------|-----------------|-------------------|-------------------------|
|
|||
|
|
| **Phase 1** | Tailscale Funnel永続化<br>バックアップ戦略<br>PostgreSQL/Redis | Uptime Kuma<br>CI/CD基礎 | ログ集約(Loki) |
|
|||
|
|
| **Phase 2** | 共通パッケージ化<br>プロジェクトテンプレート | 新規アプリテスト作成 | 既存アプリ全移行 |
|
|||
|
|
| **Phase 3** | ドキュメント整備 | AI Code Review Bot | ナレッジベース自動化 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎯 **成功指標(KPI)**
|
|||
|
|
|
|||
|
|
### **Phase 1完了時**
|
|||
|
|
- [ ] Synology再起動後も全サービス自動起動
|
|||
|
|
- [ ] バックアップから30分以内にリストア可能
|
|||
|
|
- [ ] サービスダウン時に5分以内に通知
|
|||
|
|
- [ ] git tag push → 自動デプロイ完了(15分以内)
|
|||
|
|
|
|||
|
|
### **Phase 2完了時**
|
|||
|
|
- [ ] 新規Flutterアプリを30分で立ち上げ
|
|||
|
|
- [ ] 既存アプリ2つ以上が共通パッケージ使用
|
|||
|
|
- [ ] コード重複率50%削減
|
|||
|
|
|
|||
|
|
### **Phase 3完了時**
|
|||
|
|
- [ ] PR作成→自動レビュー→コメント投稿(10分以内)
|
|||
|
|
- [ ] ドキュメントカバレッジ80%以上
|
|||
|
|
- [ ] トラブルシューティング時間50%削減
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## ⚠️ **リスクと対策**
|
|||
|
|
|
|||
|
|
| リスク | 影響 | 対策 |
|
|||
|
|
|--------|------|------|
|
|||
|
|
| Phase 1が長引く | Phase 2/3に影響 | Week 1-2に集中、Week 3-4は柔軟調整 |
|
|||
|
|
| Synology容量不足 | Docker起動失敗 | 事前に空き容量確認(推奨: 500GB以上) |
|
|||
|
|
| CI/CD学習コスト高 | 挫折リスク | 最小構成から開始、段階的拡張 |
|
|||
|
|
| 新規プロジェクト誘惑 | 12週間計画放棄 | Phase 1完了までは厳格に新規着手禁止 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 📅 **週次チェックポイント**
|
|||
|
|
|
|||
|
|
### **毎週金曜17時: 進捗レビュー**
|
|||
|
|
|
|||
|
|
**確認事項**:
|
|||
|
|
1. 今週の目標達成率は?(%)
|
|||
|
|
2. ブロッカーは何か?
|
|||
|
|
3. 来週の優先順位調整は必要か?
|
|||
|
|
|
|||
|
|
**AI活用**:
|
|||
|
|
- Claude Code: コードレビュー
|
|||
|
|
- Antigravity: 実装加速
|
|||
|
|
- Gemini: アーキテクチャ相談
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 🎓 **学習リソース**
|
|||
|
|
|
|||
|
|
### **必読ドキュメント**
|
|||
|
|
- [ ] Tailscale Funnel公式ドキュメント
|
|||
|
|
- [ ] Gitea Actions ガイド
|
|||
|
|
- [ ] Docker Compose Best Practices
|
|||
|
|
- [ ] Flutter Package開発ガイド
|
|||
|
|
|
|||
|
|
### **推奨チュートリアル**
|
|||
|
|
- [ ] Uptime Kuma セットアップ(30分)
|
|||
|
|
- [ ] PostgreSQL Docker運用(1時間)
|
|||
|
|
- [ ] CI/CDパイプライン構築(2時間)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
**次のアクション**: Phase 1 Week 1 Day 1のTailscale Funnel永続化から開始してください。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
_作成者: Claude (Sonnet 4.5)_
|
|||
|
|
_対象: 日本酒アプリ完成後の開発環境最適化_
|
|||
|
|
_期間: 12週間(2026-02-24 ~ 2026-05-18)_
|