feat(phase8): CI/CD Pipeline 與 K8s 部署自動化

Phase 8 CI/CD 藍圖:
- GitHub Actions deploy-prod.yml (沿用 AIOPS 成熟模式)
- Signal Worker K8s Deployment
- Telegram Notify 閉環
- Bootstrap 自動化腳本

架構鐵律:
- Build: 110 金庫 (Harbor + Self-Hosted Runner)
- Deploy: 120 K3s Master
- 嚴禁 Docker Compose,K8s 唯一合法部署

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
OG T
2026-03-22 18:01:01 +08:00
parent ccdf757edd
commit f037812f15
11 changed files with 1236 additions and 0 deletions

214
scripts/bootstrap_prod.sh Executable file
View File

@@ -0,0 +1,214 @@
#!/bin/bash
# =============================================================================
# AWOOOI Production Bootstrap Script
# =============================================================================
# Phase 8: 全自動化初始腳本
#
# 功能:
# A. 讀取本地 .env 中的機密
# B. 產出 03-secrets.yaml 並 kubectl apply
# C. 自動 git add, commit, push
#
# 用法:
# ./scripts/bootstrap_prod.sh
#
# 前置條件:
# - kubectl 已配置 (KUBECONFIG 指向 120 K3s)
# - .env 檔案已填寫機密
# =============================================================================
set -euo pipefail
# 顏色定義
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
echo -e "${BLUE}╔══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${BLUE}║ AWOOOI Production Bootstrap Script (Phase 8) ║${NC}"
echo -e "${BLUE}╚══════════════════════════════════════════════════════════════╝${NC}"
echo ""
# =============================================================================
# 配置
# =============================================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
ENV_FILE="${PROJECT_ROOT}/.env"
SECRETS_TEMPLATE="${PROJECT_ROOT}/k8s/awoooi-prod/03-secrets.example.yaml"
SECRETS_OUTPUT="${PROJECT_ROOT}/k8s/awoooi-prod/03-secrets.yaml"
K8S_NAMESPACE="awoooi-prod"
# =============================================================================
# Step 1: 檢查前置條件
# =============================================================================
echo -e "${YELLOW}[1/5] 檢查前置條件...${NC}"
# 檢查 .env 檔案
if [ ! -f "$ENV_FILE" ]; then
echo -e "${RED}❌ 錯誤: .env 檔案不存在${NC}"
echo " 請複製 .env.example 並填入機密:"
echo " cp .env.example .env"
exit 1
fi
echo -e "${GREEN} ✓ .env 檔案存在${NC}"
# 檢查 kubectl
if ! command -v kubectl &> /dev/null; then
echo -e "${RED}❌ 錯誤: kubectl 未安裝${NC}"
exit 1
fi
echo -e "${GREEN} ✓ kubectl 已安裝${NC}"
# 檢查 K8s 連線
if ! kubectl cluster-info &> /dev/null; then
echo -e "${RED}❌ 錯誤: 無法連接 K8s 叢集${NC}"
echo " 請確認 KUBECONFIG 設定正確"
exit 1
fi
echo -e "${GREEN} ✓ K8s 叢集連線正常${NC}"
# =============================================================================
# Step 2: 讀取 .env 並產生 secrets.yaml
# =============================================================================
echo ""
echo -e "${YELLOW}[2/5] 讀取 .env 並產生 K8s Secrets...${NC}"
# 載入 .env
set -a
source "$ENV_FILE"
set +a
# 檢查必要的環境變數
REQUIRED_VARS=(
"DATABASE_URL"
"REDIS_URL"
"OPENCLAW_TG_BOT_TOKEN"
"OPENCLAW_TG_CHAT_ID"
)
for var in "${REQUIRED_VARS[@]}"; do
if [ -z "${!var:-}" ]; then
echo -e "${RED}❌ 錯誤: 環境變數 $var 未設定${NC}"
exit 1
fi
done
echo -e "${GREEN} ✓ 所有必要環境變數已設定${NC}"
# 產生 secrets.yaml
cat > "$SECRETS_OUTPUT" << EOF
# AWOOOI Production Secrets
# 自動產生於: $(date -Iseconds)
# ⚠️ 此檔案包含機密,請勿提交至 Git
apiVersion: v1
kind: Secret
metadata:
name: awoooi-secrets
namespace: ${K8S_NAMESPACE}
type: Opaque
stringData:
# 資料庫
DATABASE_URL: "${DATABASE_URL:-postgresql+asyncpg://awoooi:changeme@192.168.0.188:5432/awoooi_prod}"
# Redis
REDIS_URL: "${REDIS_URL:-redis://192.168.0.188:6380/10}"
# AI 服務
GEMINI_API_KEY: "${GEMINI_API_KEY:-}"
CLAUDE_API_KEY: "${CLAUDE_API_KEY:-}"
# Telegram Gateway
OPENCLAW_TG_BOT_TOKEN: "${OPENCLAW_TG_BOT_TOKEN}"
OPENCLAW_TG_CHAT_ID: "${OPENCLAW_TG_CHAT_ID}"
OPENCLAW_TG_USER_WHITELIST: "${OPENCLAW_TG_USER_WHITELIST:-${OPENCLAW_TG_CHAT_ID}}"
# Webhook 安全
WEBHOOK_HMAC_SECRET: "${WEBHOOK_HMAC_SECRET:-$(openssl rand -hex 32)}"
# JWT (未來擴展)
JWT_SECRET: "${JWT_SECRET:-$(openssl rand -hex 32)}"
JWT_ALGORITHM: "HS256"
EOF
echo -e "${GREEN} ✓ 已產生 k8s/awoooi-prod/03-secrets.yaml${NC}"
# =============================================================================
# Step 3: 套用 K8s Secrets
# =============================================================================
echo ""
echo -e "${YELLOW}[3/5] 套用 K8s Secrets 至 ${K8S_NAMESPACE}...${NC}"
# 確保 namespace 存在
kubectl create namespace "$K8S_NAMESPACE" --dry-run=client -o yaml | kubectl apply -f - 2>/dev/null || true
# 套用 secrets
kubectl apply -f "$SECRETS_OUTPUT" --namespace="$K8S_NAMESPACE"
echo -e "${GREEN} ✓ K8s Secrets 已套用${NC}"
# 驗證
echo ""
echo -e "${BLUE} 驗證 Secrets:${NC}"
kubectl get secret awoooi-secrets -n "$K8S_NAMESPACE" -o jsonpath='{.metadata.name}' && echo " exists"
# =============================================================================
# Step 4: 清理敏感檔案 (不提交到 Git)
# =============================================================================
echo ""
echo -e "${YELLOW}[4/5] 清理敏感檔案...${NC}"
# 確保 secrets.yaml 在 .gitignore
if ! grep -q "03-secrets.yaml" "${PROJECT_ROOT}/.gitignore" 2>/dev/null; then
echo "k8s/awoooi-prod/03-secrets.yaml" >> "${PROJECT_ROOT}/.gitignore"
echo -e "${GREEN} ✓ 已將 03-secrets.yaml 加入 .gitignore${NC}"
fi
# 刪除敏感檔案
rm -f "$SECRETS_OUTPUT"
echo -e "${GREEN} ✓ 已刪除本地 secrets.yaml (僅保留在 K8s)${NC}"
# =============================================================================
# Step 5: Git Commit & Push
# =============================================================================
echo ""
echo -e "${YELLOW}[5/5] Git Commit & Push...${NC}"
cd "$PROJECT_ROOT"
# 檢查是否有變更
if git diff --quiet && git diff --cached --quiet; then
echo -e "${BLUE} 沒有變更需要提交${NC}"
else
git add .
git commit -m "chore: Phase 8 CI/CD bootstrap
- Add deploy-prod.yml GitHub Actions workflow
- Add Signal Worker K8s deployment
- Update Harbor image paths
- Configure Telegram notification
Co-Authored-By: Claude <noreply@anthropic.com>"
echo -e "${GREEN} ✓ Git commit 完成${NC}"
# Push
git push origin main
echo -e "${GREEN} ✓ Git push 完成${NC}"
fi
# =============================================================================
# 完成
# =============================================================================
echo ""
echo -e "${GREEN}╔══════════════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}║ Bootstrap 完成! ║${NC}"
echo -e "${GREEN}╚══════════════════════════════════════════════════════════════╝${NC}"
echo ""
echo -e "下一步:"
echo -e " 1. 確認 110 主機 GitHub Runner 已啟動"
echo -e " 2. 前往 GitHub Actions 查看部署狀態"
echo -e " 3. 監控 Telegram 接收部署通知"
echo ""
echo -e "${BLUE}🔗 GitHub Actions: https://github.com/$(git remote get-url origin | sed 's/.*github.com[:/]\(.*\)\.git/\1/')/actions${NC}"