2026-05-10 13:12:44 +08:00

242 lines
9.2 KiB
YAML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ═══════════════════════════════════════════════
# 🔺 Sovereign: TCS-0002∞ | Root: SYS-GLW-0001
# 📜 Copyright: 国作登字-2026-A-00037559
# ═══════════════════════════════════════════════
# .github/workflows/sandbox-deploy.yml
# 🏠 沙盒部署自动化 · 铸渊 · 光湖代码守护人格体
# 触发: 开发者 push 到 dev/DEV-XXX/模块名 分支
name: "🏠 Sandbox Deploy"
on:
push:
branches:
- 'dev/DEV-*/**'
permissions:
contents: write
jobs:
# ===== Job 1: 解析 + 校验 =====
parse-and-validate:
runs-on: ubuntu-latest
outputs:
dev_id: ${{ steps.parse.outputs.dev_id }}
module: ${{ steps.parse.outputs.module }}
email: ${{ steps.parse.outputs.email }}
steps:
- uses: actions/checkout@v4
- name: "🔍 解析分支名"
id: parse
run: |
BRANCH="${GITHUB_REF#refs/heads/}"
DEV_ID=$(echo "$BRANCH" | cut -d'/' -f2)
MODULE=$(echo "$BRANCH" | cut -d'/' -f3)
echo "dev_id=$DEV_ID" >> $GITHUB_OUTPUT
echo "module=$MODULE" >> $GITHUB_OUTPUT
echo "🆔 开发者: $DEV_ID"
echo "📦 模块: $MODULE"
# 从 dev-registry.json 获取邮箱
EMAIL=$(cat data/dev-registry.json 2>/dev/null | \
python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('$DEV_ID',{}).get('email',''))" 2>/dev/null || echo '')
echo "email=$EMAIL" >> $GITHUB_OUTPUT
- name: "✅ 校验 DEV 编号"
run: |
DEV_ID="${{ steps.parse.outputs.dev_id }}"
if [[ ! "$DEV_ID" =~ ^DEV-[0-9]{3}$ ]]; then
echo "❌ 无效的 DEV 编号: $DEV_ID"
exit 1
fi
# ===== Job 2: 部署到服务器沙盒 =====
deploy-to-sandbox:
needs: parse-and-validate
runs-on: ubuntu-latest
outputs:
deploy_result: ${{ steps.check.outputs.result }}
deploy_detail: ${{ steps.check.outputs.detail }}
steps:
- uses: actions/checkout@v4
- name: "🔑 配置 SSH"
run: |
mkdir -p ~/.ssh
echo "${{ secrets.ZY_SERVER_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.ZY_SERVER_HOST }} >> ~/.ssh/known_hosts 2>/dev/null
- name: "🏠 部署到沙盒"
id: deploy
env:
DEV_ID: ${{ needs.parse-and-validate.outputs.dev_id }}
MODULE: ${{ needs.parse-and-validate.outputs.module }}
HOST: ${{ secrets.ZY_SERVER_HOST }}
USER: ${{ secrets.ZY_SERVER_USER }}
run: |
SANDBOX="/var/www/${DEV_ID}/${MODULE}"
echo "📦 部署目标: ${SANDBOX}"
# 创建沙盒目录(如不存在)
ssh ${USER}@${HOST} "mkdir -p ${SANDBOX}"
# rsync 同步代码
rsync -avz --delete \
--exclude='.git' \
--exclude='.dev-profile' \
--exclude='node_modules' \
./ ${USER}@${HOST}:${SANDBOX}/
# 设置权限(遵守部署适配协议 v1.0
ssh ${USER}@${HOST} "
chown -R nginx:nginx /var/www/${DEV_ID}/${MODULE}
find /var/www/${DEV_ID}/${MODULE} -type d -exec chmod 755 {} \;
find /var/www/${DEV_ID}/${MODULE} -type f -exec chmod 644 {} \;
"
echo "✅ 文件同步完成"
- name: "🔍 运行 deploy-check.sh"
id: check
env:
DEV_ID: ${{ needs.parse-and-validate.outputs.dev_id }}
MODULE: ${{ needs.parse-and-validate.outputs.module }}
HOST: ${{ secrets.ZY_SERVER_HOST }}
USER: ${{ secrets.ZY_SERVER_USER }}
run: |
# 上传自检脚本
scp scripts/deploy-check.sh ${USER}@${HOST}:/tmp/deploy-check.sh
# 运行自检
RESULT=$(ssh ${USER}@${HOST} "bash /tmp/deploy-check.sh ${DEV_ID} ${MODULE}" 2>&1) || true
echo "$RESULT"
if echo "$RESULT" | grep -q "❌ FAIL:"; then
echo "result=failed" >> $GITHUB_OUTPUT
echo "detail=$RESULT" >> $GITHUB_OUTPUT
else
echo "result=passed" >> $GITHUB_OUTPUT
echo "detail=All checks passed" >> $GITHUB_OUTPUT
fi
- name: "🔥 运行 smoke-test.sh"
id: smoke
env:
HOST: ${{ secrets.ZY_SERVER_HOST }}
USER: ${{ secrets.ZY_SERVER_USER }}
run: |
scp scripts/smoke-test.sh ${USER}@${HOST}:/tmp/smoke-test.sh
SMOKE=$(ssh ${USER}@${HOST} "bash /tmp/smoke-test.sh" 2>&1) || true
echo "$SMOKE"
if echo "$SMOKE" | grep -q "异常"; then
echo "⚠️ 有模块冒烟检查失败,但不阻断当前部署"
fi
# ===== Job 3: 写结果 + 通知 =====
notify-and-sync:
needs: [parse-and-validate, deploy-to-sandbox]
runs-on: ubuntu-latest
if: always()
steps:
- uses: actions/checkout@v4
- name: "📊 写入 deploy-status.json"
env:
DEV_ID: ${{ needs.parse-and-validate.outputs.dev_id }}
MODULE: ${{ needs.parse-and-validate.outputs.module }}
RESULT: ${{ needs.deploy-to-sandbox.outputs.deploy_result }}
DETAIL: ${{ needs.deploy-to-sandbox.outputs.deploy_detail }}
run: |
export TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)
# 读取现有状态文件或初始化
export STATUS_FILE="data/deploy-status.json"
mkdir -p data
[ -f "$STATUS_FILE" ] || echo '{}' > "$STATUS_FILE"
# 更新状态
python3 << 'EOF'
import json, os
status_file = os.environ.get('STATUS_FILE', 'data/deploy-status.json')
dev_id = os.environ['DEV_ID']
module = os.environ['MODULE']
result = os.environ.get('RESULT', '')
detail = os.environ.get('DETAIL', '')
timestamp = os.environ.get('TIMESTAMP', '')
commit = os.environ.get('GITHUB_SHA', '')
with open(status_file, 'r') as f:
data = json.load(f)
data[f'{dev_id}/{module}'] = {
'dev_id': dev_id,
'module': module,
'result': result,
'detail': detail,
'timestamp': timestamp,
'commit': commit
}
with open(status_file, 'w') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
EOF
git config user.name "zhuyuan-bot"
git config user.email "zhuyuan@guanghulab.com"
git add data/deploy-status.json
git commit -m "🧠 deploy-status: ${DEV_ID}/${MODULE} → ${RESULT}" || true
git push || true
- name: "📧 发送部署结果邮件"
if: needs.parse-and-validate.outputs.email != ''
env:
SMTP_USER: ${{ secrets.ZY_SMTP_USER }}
SMTP_PASS: ${{ secrets.ZY_SMTP_PASS }}
TO_EMAIL: ${{ needs.parse-and-validate.outputs.email }}
DEV_ID: ${{ needs.parse-and-validate.outputs.dev_id }}
MODULE: ${{ needs.parse-and-validate.outputs.module }}
RESULT: ${{ needs.deploy-to-sandbox.outputs.deploy_result }}
run: |
python3 << 'PYEOF'
import smtplib, os
from email.mime.text import MIMEText
from email.header import Header
smtp_user = os.environ['SMTP_USER']
smtp_pass = os.environ['SMTP_PASS']
to_email = os.environ['TO_EMAIL']
dev_id = os.environ['DEV_ID']
module = os.environ['MODULE']
result = os.environ.get('RESULT', '')
if result == 'passed':
subject = f'✅ 部署成功:{dev_id}/{module}'
body = f'你的模块 {module} 已成功部署到 guanghulab.com\n\n访问地址https://guanghulab.com/{module}/\n\n铸渊 · 光湖代码守护人格体'
else:
subject = f'❌ 部署失败:{dev_id}/{module}'
body = f'你的模块 {module} 部署失败\n\n请检查你的模块是否符合「服务器部署适配协议 v1.0」\n\n错误详情请看仓库公告栏或 GitHub Actions 日志\n\n铸渊 · 光湖代码守护人格体'
msg = MIMEText(body, 'plain', 'utf-8')
msg['Subject'] = Header(subject, 'utf-8')
msg['From'] = smtp_user
msg['To'] = to_email
try:
server = smtplib.SMTP_SSL('smtp.qq.com', 465)
server.login(smtp_user, smtp_pass)
server.sendmail(smtp_user, to_email, msg.as_string())
server.quit()
print(f'✅ 邮件已发送到 {to_email}')
except Exception as e:
print(f'⚠️ 邮件发送失败: {e}')
PYEOF
- name: "📝 同步到 Notion 部署注册表"
env:
NOTION_TOKEN: ${{ secrets.ZY_NOTION_TOKEN }}
FINGERPRINT_DB_ID: ${{ secrets.ZY_NOTION_FINGERPRINT_DB }}
DEV_ID: ${{ needs.parse-and-validate.outputs.dev_id }}
MODULE: ${{ needs.parse-and-validate.outputs.module }}
RESULT: ${{ needs.deploy-to-sandbox.outputs.deploy_result }}
run: |
node scripts/sync-deploy-to-notion.js || echo "⚠️ Notion 同步失败(不阻断主流程)"