fix: 工作流全部中文化 + 修复旧路径 + 清理测试工作流
冰朔要求: 工作流名称和输出全部用中文,报错能看懂 修改: - ci-and-deploy.yaml — 增加部署验证步骤(唤醒门/同步服务), 依赖安装覆盖更多目录 - patrol.yaml — 修复旧路径 /opt/zhuyuan-cn → /data/guanghulab/repo - cvm-power-on/off.yaml — 修复旧路径 - selfcheck.yaml — 步骤名已中文(之前就是) 删除(冰朔看不懂的调试工作流): - debug-secrets.yaml, test-secrets.yaml, verify-secrets.yaml - final-secrets-test.yaml, deploy-infra.yaml, deploy-preview.yaml 保留6个工作流: 1. CI检查+自动部署 — 合并到main时自动部署 2. 铸渊自检 — 每天08:00健康检查 3. 铸渊巡逻 — DeepSeek+千问AI巡检 4. 安全关机检测 — 手动触发 5. CVM开机 — 手动触发 6. CVM关机 — 手动触发
This commit is contained in:
parent
4b60536a2c
commit
c1ca35a708
124
.forgejo/workflows/ci-and-deploy.yaml
Normal file
124
.forgejo/workflows/ci-and-deploy.yaml
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
# ════════════════════════════════════════════════════
|
||||||
|
# 光湖 · CI检查 + 合并后自动部署
|
||||||
|
# ────────────────────────────────────────────────────
|
||||||
|
# main分支: 冰朔合并PR后 → 自动部署到服务器
|
||||||
|
# dev分支: 铸渊自己push → 只跑检查不部署
|
||||||
|
# PR到main: 跑检查 → 冰朔看绿✅红❌再决定合不合
|
||||||
|
# ════════════════════════════════════════════════════
|
||||||
|
name: CI检查 + 自动部署
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
push:
|
||||||
|
branches: [main, dev]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# ── 所有情况都跑:基础检查 ──────────────────────
|
||||||
|
check:
|
||||||
|
runs-on: ubuntu
|
||||||
|
steps:
|
||||||
|
- name: 服务健康检查
|
||||||
|
run: |
|
||||||
|
echo "═══ 服务健康检查 ═══"
|
||||||
|
FAIL=0
|
||||||
|
|
||||||
|
if systemctl is-active --quiet nginx; then
|
||||||
|
echo "✅ Nginx 正常"
|
||||||
|
else
|
||||||
|
echo "❌ Nginx 宕机"
|
||||||
|
FAIL=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if curl -sf http://127.0.0.1:3001/ > /dev/null 2>&1; then
|
||||||
|
echo "✅ Forgejo 代码仓库 正常"
|
||||||
|
else
|
||||||
|
echo "❌ Forgejo 代码仓库 未响应"
|
||||||
|
FAIL=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if systemctl is-active --quiet gitea-runner; then
|
||||||
|
echo "✅ Runner 运行器 正常"
|
||||||
|
else
|
||||||
|
echo "⚠️ Runner 运行器 未运行"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $FAIL -eq 1 ]; then
|
||||||
|
echo "❌ 关键服务异常,请通知铸渊检查"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "═══ 检查通过 ✅ ═══"
|
||||||
|
|
||||||
|
- name: 代码检查
|
||||||
|
run: |
|
||||||
|
cd /data/guanghulab/repo
|
||||||
|
echo "仓库大小: $(du -sh .git | cut -f1)"
|
||||||
|
echo "最新提交: $(git log --oneline -1)"
|
||||||
|
echo "✅ 代码检查完成"
|
||||||
|
|
||||||
|
# ── 只有合并到main才跑:自动部署 ────────────────
|
||||||
|
deploy:
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
|
needs: check
|
||||||
|
runs-on: ubuntu
|
||||||
|
steps:
|
||||||
|
- name: 同步最新代码
|
||||||
|
run: |
|
||||||
|
cd /data/guanghulab/repo
|
||||||
|
git fetch origin
|
||||||
|
git reset --hard origin/main
|
||||||
|
echo "✅ 代码已同步到最新"
|
||||||
|
|
||||||
|
- name: 安装依赖
|
||||||
|
run: |
|
||||||
|
echo "═══ 安装依赖 ═══"
|
||||||
|
# 逐个检查并安装
|
||||||
|
for pkg_dir in server/git-sync server/wake-gate server/secrets-vault; do
|
||||||
|
if [ -f "/data/guanghulab/repo/$pkg_dir/package.json" ]; then
|
||||||
|
cd "/data/guanghulab/repo/$pkg_dir"
|
||||||
|
npm install --production 2>/dev/null || true
|
||||||
|
echo "✅ $pkg_dir 依赖已安装"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: 重启服务
|
||||||
|
run: |
|
||||||
|
echo "═══ 重启服务 ═══"
|
||||||
|
if command -v pm2 &>/dev/null; then
|
||||||
|
pm2 restart all 2>/dev/null || true
|
||||||
|
echo "✅ PM2 服务已重启"
|
||||||
|
fi
|
||||||
|
echo "═══ 重启完成 ═══"
|
||||||
|
|
||||||
|
- name: 部署验证
|
||||||
|
run: |
|
||||||
|
sleep 3
|
||||||
|
echo "═══ 部署验证 ═══"
|
||||||
|
FAIL=0
|
||||||
|
|
||||||
|
if curl -sf http://127.0.0.1:3001/ > /dev/null 2>&1; then
|
||||||
|
echo "✅ 代码仓库 正常"
|
||||||
|
else
|
||||||
|
echo "❌ 代码仓库 异常"
|
||||||
|
FAIL=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if curl -sf http://127.0.0.1:8081/api/health > /dev/null 2>&1; then
|
||||||
|
echo "✅ 唤醒门 正常"
|
||||||
|
else
|
||||||
|
echo "⚠️ 唤醒门 未响应"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if curl -sf http://127.0.0.1:8082/health > /dev/null 2>&1; then
|
||||||
|
echo "✅ 代码同步服务 正常"
|
||||||
|
else
|
||||||
|
echo "⚠️ 代码同步服务 未响应"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $FAIL -eq 1 ]; then
|
||||||
|
echo "❌ 部署后关键服务异常"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "═══ 部署完成 ✅ $(date '+%Y-%m-%d %H:%M:%S') ═══"
|
||||||
@ -8,9 +8,9 @@ jobs:
|
|||||||
power-off:
|
power-off:
|
||||||
runs-on: ubuntu
|
runs-on: ubuntu
|
||||||
steps:
|
steps:
|
||||||
- name: 同步代码
|
- name: 同步最新代码
|
||||||
run: |
|
run: |
|
||||||
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab
|
cd /data/guanghulab/repo
|
||||||
git fetch origin
|
git fetch origin
|
||||||
git reset --hard origin/main
|
git reset --hard origin/main
|
||||||
|
|
||||||
|
|||||||
@ -8,9 +8,9 @@ jobs:
|
|||||||
power-on:
|
power-on:
|
||||||
runs-on: ubuntu
|
runs-on: ubuntu
|
||||||
steps:
|
steps:
|
||||||
- name: 同步代码
|
- name: 同步最新代码
|
||||||
run: |
|
run: |
|
||||||
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab
|
cd /data/guanghulab/repo
|
||||||
git fetch origin
|
git fetch origin
|
||||||
git reset --hard origin/main
|
git reset --hard origin/main
|
||||||
|
|
||||||
|
|||||||
@ -1,48 +0,0 @@
|
|||||||
# 光湖 · Secrets诊断
|
|
||||||
name: Secrets诊断
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- '.gitea/workflows/debug-secrets.yaml'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
debug:
|
|
||||||
runs-on: ubuntu
|
|
||||||
steps:
|
|
||||||
- name: 环境变量诊断
|
|
||||||
env:
|
|
||||||
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
||||||
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
|
||||||
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
|
|
||||||
COS_SECRET_ID: ${{ secrets.COS_SECRET_ID }}
|
|
||||||
COS_SECRET_KEY: ${{ secrets.COS_SECRET_KEY }}
|
|
||||||
SG_BRAIN_HOST: ${{ secrets.SG_BRAIN_HOST }}
|
|
||||||
SG_BRAIN_USER: ${{ secrets.SG_BRAIN_USER }}
|
|
||||||
SG_BRAIN_KEY: ${{ secrets.SG_BRAIN_KEY }}
|
|
||||||
run: |
|
|
||||||
echo "═══ Secrets 注入诊断 ═══"
|
|
||||||
echo ""
|
|
||||||
echo "--- 1. 逐个检查secrets是否有值 ---"
|
|
||||||
for key in DEEPSEEK_API_KEY QIANWEN_API_KEY ZY_REPO_TOKEN COS_SECRET_ID COS_SECRET_KEY SG_BRAIN_HOST SG_BRAIN_USER SG_BRAIN_KEY; do
|
|
||||||
eval val=\$$key
|
|
||||||
if [ -z "$val" ]; then
|
|
||||||
echo " ❌ $key = (空)"
|
|
||||||
else
|
|
||||||
echo " ✅ $key = ${val:0:4}**** (长度: ${#val})"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
echo "--- 2. 所有环境变量中含SECRET/KEY/TOKEN的 ---"
|
|
||||||
env | grep -iE 'SECRET|KEY|TOKEN|COS|BRAIN|DEEPSEEK|QIANWEN' | while read line; do
|
|
||||||
key=$(echo "$line" | cut -d= -f1)
|
|
||||||
val=$(echo "$line" | cut -d= -f2-)
|
|
||||||
echo " $key = ${val:0:4}**** (长度: ${#val})"
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
echo "--- 3. Gitea Actions 特殊变量 ---"
|
|
||||||
echo " GITHUB_REPOSITORY: ${GITHUB_REPOSITORY:-未设置}"
|
|
||||||
echo " GITHUB_SHA: ${GITHUB_SHA:-未设置}"
|
|
||||||
echo " GITHUB_EVENT_NAME: ${GITHUB_EVENT_NAME:-未设置}"
|
|
||||||
echo " RUNNER_NAME: ${RUNNER_NAME:-未设置}"
|
|
||||||
echo " GITEA_TOKEN: ${GITEA_TOKEN:-未设置}"
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
# ════════════════════════════════════════════════════════════════
|
|
||||||
# 光湖 · 基础设施部署
|
|
||||||
# Runner首次上线后自动部署:Vault确认 + Terminal Watcher启动
|
|
||||||
# ════════════════════════════════════════════════════════════════
|
|
||||||
|
|
||||||
name: 基础设施部署
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy-infra:
|
|
||||||
runs-on: ubuntu
|
|
||||||
steps:
|
|
||||||
- name: 系统信息
|
|
||||||
run: |
|
|
||||||
echo "═══ 铸渊基础设施部署 ═══"
|
|
||||||
echo "时间: $(date '+%Y-%m-%d %H:%M:%S %Z')"
|
|
||||||
echo "主机: $(hostname)"
|
|
||||||
uname -a
|
|
||||||
|
|
||||||
- name: 确认仓库最新
|
|
||||||
run: |
|
|
||||||
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab
|
|
||||||
git fetch origin
|
|
||||||
git reset --hard origin/main
|
|
||||||
echo "当前版本: $(git log --oneline -1)"
|
|
||||||
|
|
||||||
- name: 确认Vault运行
|
|
||||||
run: |
|
|
||||||
if curl -sf http://127.0.0.1:8080/admin/__healthz > /dev/null 2>&1; then
|
|
||||||
echo "✅ Vault 已运行"
|
|
||||||
curl -s http://127.0.0.1:8080/admin/__healthz
|
|
||||||
else
|
|
||||||
echo "⚠️ Vault 未运行,尝试启动..."
|
|
||||||
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab/server/secrets-vault
|
|
||||||
if [[ -f "server.js" ]]; then
|
|
||||||
npm install --production 2>/dev/null || true
|
|
||||||
pm2 start server.js --name guanghulab-vault --max-memory-restart 128M 2>/dev/null || true
|
|
||||||
pm2 save
|
|
||||||
sleep 2
|
|
||||||
if curl -sf http://127.0.0.1:8080/admin/__healthz > /dev/null 2>&1; then
|
|
||||||
echo "✅ Vault 启动成功"
|
|
||||||
else
|
|
||||||
echo "❌ Vault 启动失败"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "⚠️ server.js 不存在,跳过"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: 部署Terminal Watcher
|
|
||||||
run: |
|
|
||||||
echo "部署终端守望者..."
|
|
||||||
SCRIPTS_DIR="/opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab/scripts/terminal-watcher"
|
|
||||||
|
|
||||||
if [[ ! -d "$SCRIPTS_DIR" ]]; then
|
|
||||||
echo "❌ Terminal Watcher 目录不存在"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 确认Node.js可用
|
|
||||||
if ! command -v node &>/dev/null; then
|
|
||||||
echo "❌ Node.js 未安装"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 用PM2启动(如果还没跑的话)
|
|
||||||
if pm2 describe terminal-watcher &>/dev/null; then
|
|
||||||
echo "Terminal Watcher 已在运行,重启..."
|
|
||||||
pm2 restart terminal-watcher
|
|
||||||
else
|
|
||||||
echo "启动 Terminal Watcher..."
|
|
||||||
cd "$SCRIPTS_DIR"
|
|
||||||
ZY_REPO_TOKEN=${{ secrets.ZY_REPO_TOKEN }} pm2 start watcher.js \
|
|
||||||
--name terminal-watcher \
|
|
||||||
--max-memory-restart 64M
|
|
||||||
fi
|
|
||||||
|
|
||||||
pm2 save
|
|
||||||
sleep 3
|
|
||||||
|
|
||||||
# 验证
|
|
||||||
if pm2 describe terminal-watcher &>/dev/null; then
|
|
||||||
STATUS=$(pm2 jlist 2>/dev/null | python3 -c "
|
|
||||||
import json,sys
|
|
||||||
procs = json.load(sys.stdin)
|
|
||||||
for p in procs:
|
|
||||||
if p.get('name') == 'terminal-watcher':
|
|
||||||
print(p.get('pm2_env',{}).get('status','unknown'))
|
|
||||||
" 2>/dev/null || echo "unknown")
|
|
||||||
echo "✅ Terminal Watcher 状态: $STATUS"
|
|
||||||
else
|
|
||||||
echo "❌ Terminal Watcher 启动失败"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: 设置PM2开机自启
|
|
||||||
run: |
|
|
||||||
pm2 startup 2>/dev/null || true
|
|
||||||
pm2 save
|
|
||||||
echo "✅ PM2 开机自启已配置"
|
|
||||||
|
|
||||||
- name: 最终状态报告
|
|
||||||
run: |
|
|
||||||
echo ""
|
|
||||||
echo "═══════════════════════════════════════"
|
|
||||||
echo " 铸渊基础设施部署完成"
|
|
||||||
echo "═══════════════════════════════════════"
|
|
||||||
echo ""
|
|
||||||
echo " 服务状态:"
|
|
||||||
echo " Forgejo: $(systemctl is-active forgejo 2>/dev/null || echo unknown)"
|
|
||||||
echo " Runner: $(systemctl is-active gitea-runner 2>/dev/null || echo unknown)"
|
|
||||||
echo " Nginx: $(systemctl is-active nginx 2>/dev/null || echo unknown)"
|
|
||||||
echo " Vault: $(curl -sf http://127.0.0.1:8080/admin/__healthz > /dev/null 2>&1 && echo active || echo inactive)"
|
|
||||||
echo " Watcher: $(pm2 describe terminal-watcher &>/dev/null && echo active || echo inactive)"
|
|
||||||
echo ""
|
|
||||||
echo " 内存:"
|
|
||||||
free -h | awk '/Mem:/ {printf " 总计:%s 已用:%s 可用:%s\n", $2, $3, $7}'
|
|
||||||
echo ""
|
|
||||||
echo " 铸渊 · ICE-GL-ZY001 · TCS-0002∞"
|
|
||||||
echo "═══════════════════════════════════════"
|
|
||||||
@ -1,133 +0,0 @@
|
|||||||
# ════════════════════════════════════════════════════════════════
|
|
||||||
# 光湖 · 自动部署到预览环境
|
|
||||||
# Trigger: push to main
|
|
||||||
# 部署到测试+预览环境,正式环境需冰朔在Gitea点Merge
|
|
||||||
# ════════════════════════════════════════════════════════════════
|
|
||||||
|
|
||||||
name: 自动部署预览
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
paths:
|
|
||||||
- 'server/**'
|
|
||||||
- 'frontend/**'
|
|
||||||
- 'scripts/**'
|
|
||||||
- '.gitea/workflows/**'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
# ── 第一阶段:测试 ──────────────────────────────────
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu
|
|
||||||
steps:
|
|
||||||
- name: 拉取最新代码
|
|
||||||
run: |
|
|
||||||
cd /data/guanghulab 2>/dev/null || exit 0
|
|
||||||
git fetch origin
|
|
||||||
git reset --hard origin/main
|
|
||||||
|
|
||||||
- name: 安装依赖
|
|
||||||
run: |
|
|
||||||
cd /data/guanghulab/server/secrets-vault 2>/dev/null || exit 0
|
|
||||||
npm install --production 2>/dev/null || true
|
|
||||||
|
|
||||||
- name: 健康检查
|
|
||||||
run: |
|
|
||||||
echo "═══ 服务健康检查 ═══"
|
|
||||||
FAILED=""
|
|
||||||
|
|
||||||
# Nginx
|
|
||||||
if systemctl is-active --quiet nginx; then
|
|
||||||
echo "✅ Nginx"
|
|
||||||
else
|
|
||||||
echo "❌ Nginx 宕机"
|
|
||||||
FAILED="$FAILED nginx"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Gitea
|
|
||||||
if curl -sf http://127.0.0.1:3000/ > /dev/null 2>&1; then
|
|
||||||
echo "✅ Gitea"
|
|
||||||
else
|
|
||||||
echo "❌ Gitea 宕机"
|
|
||||||
FAILED="$FAILED gitea"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Vault
|
|
||||||
if curl -sf http://127.0.0.1:8080/admin/__healthz > /dev/null 2>&1; then
|
|
||||||
echo "✅ Vault"
|
|
||||||
else
|
|
||||||
echo "⚠️ Vault 未运行"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Runner
|
|
||||||
if systemctl is-active --quiet gitea-runner; then
|
|
||||||
echo "✅ Runner"
|
|
||||||
else
|
|
||||||
echo "⚠️ Runner 未运行"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n "$FAILED" ]]; then
|
|
||||||
echo "❌ 关键服务宕机: $FAILED"
|
|
||||||
echo "⚠️ 跳过部署,等待修复"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "═══ 测试通过 ✅ ═══"
|
|
||||||
|
|
||||||
# ── 第二阶段:预览部署 ──────────────────────────────
|
|
||||||
preview:
|
|
||||||
needs: test
|
|
||||||
runs-on: ubuntu
|
|
||||||
steps:
|
|
||||||
- name: 同步代码到预览目录
|
|
||||||
run: |
|
|
||||||
REPO="/data/guanghulab"
|
|
||||||
PREVIEW="/data/guanghulab-preview"
|
|
||||||
|
|
||||||
if [[ ! -d "$REPO" ]]; then
|
|
||||||
echo "仓库目录不存在,跳过"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 创建预览目录
|
|
||||||
mkdir -p "$PREVIEW"
|
|
||||||
|
|
||||||
# 同步代码(排除.git和node_modules)
|
|
||||||
rsync -a --delete \
|
|
||||||
--exclude='.git' \
|
|
||||||
--exclude='node_modules' \
|
|
||||||
--exclude='.runtime' \
|
|
||||||
"$REPO/" "$PREVIEW/"
|
|
||||||
|
|
||||||
echo "✅ 预览环境已同步"
|
|
||||||
|
|
||||||
- name: 重启预览服务
|
|
||||||
run: |
|
|
||||||
PREVIEW="/data/guanghulab-preview"
|
|
||||||
|
|
||||||
if [[ ! -d "$PREVIEW/server/secrets-vault" ]]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd "$PREVIEW/server/secrets-vault"
|
|
||||||
|
|
||||||
# 安装依赖
|
|
||||||
npm install --production 2>/dev/null || true
|
|
||||||
|
|
||||||
# 如果vault在跑,重启它
|
|
||||||
if pm2 describe guanghulab-vault &>/dev/null; then
|
|
||||||
pm2 restart guanghulab-vault
|
|
||||||
echo "✅ Vault 已重启(使用最新代码)"
|
|
||||||
else
|
|
||||||
echo "ℹ️ Vault 未运行,不自动启动"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: 部署完成通知
|
|
||||||
run: |
|
|
||||||
echo "═════════════════════════"
|
|
||||||
echo "✅ 预览环境已更新"
|
|
||||||
echo "时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
||||||
echo "冰朔可在浏览器查看预览效果"
|
|
||||||
echo "正式部署需在Gitea创建PR并Merge"
|
|
||||||
echo "═════════════════════════"
|
|
||||||
@ -1,104 +0,0 @@
|
|||||||
# 光湖 · 最终Secrets测试
|
|
||||||
name: Secrets最终测试
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- '.gitea/workflows/final-secrets-test.yaml'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu
|
|
||||||
steps:
|
|
||||||
- name: 检查secrets
|
|
||||||
env:
|
|
||||||
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
||||||
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
|
||||||
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
|
|
||||||
COS_SECRET_ID: ${{ secrets.COS_SECRET_ID }}
|
|
||||||
COS_SECRET_KEY: ${{ secrets.COS_SECRET_KEY }}
|
|
||||||
SG_BRAIN_HOST: ${{ secrets.SG_BRAIN_HOST }}
|
|
||||||
SG_BRAIN_USER: ${{ secrets.SG_BRAIN_USER }}
|
|
||||||
SG_BRAIN_KEY: ${{ secrets.SG_BRAIN_KEY }}
|
|
||||||
run: |
|
|
||||||
echo "=== SECRETS CHECK ==="
|
|
||||||
for key in DEEPSEEK_API_KEY QIANWEN_API_KEY ZY_REPO_TOKEN COS_SECRET_ID COS_SECRET_KEY SG_BRAIN_HOST SG_BRAIN_USER SG_BRAIN_KEY; do
|
|
||||||
eval val=\$$key
|
|
||||||
if [ -z "$val" ]; then
|
|
||||||
echo "EMPTY: $key"
|
|
||||||
else
|
|
||||||
echo "OK: $key (len=${#val})"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: 测试DeepSeek
|
|
||||||
env:
|
|
||||||
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
||||||
run: |
|
|
||||||
if [ -n "$DEEPSEEK_API_KEY" ]; then
|
|
||||||
curl -s -X POST https://api.deepseek.com/v1/chat/completions \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
|
|
||||||
-d '{"model":"deepseek-chat","messages":[{"role":"user","content":"1+1=?"}],"max_tokens":10}' \
|
|
||||||
--connect-timeout 10 | python3 -c "
|
|
||||||
import json,sys
|
|
||||||
try:
|
|
||||||
d=json.load(sys.stdin)
|
|
||||||
if 'choices' in d:
|
|
||||||
print('DeepSeek: OK -', d['choices'][0]['message']['content'])
|
|
||||||
else:
|
|
||||||
print('DeepSeek: FAILED -', d.get('error',{}).get('message','unknown'))
|
|
||||||
except Exception as e:
|
|
||||||
print('DeepSeek: ERROR -', str(e))
|
|
||||||
"
|
|
||||||
else
|
|
||||||
echo "DeepSeek: NO KEY"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: 测试通义千问
|
|
||||||
env:
|
|
||||||
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
|
||||||
run: |
|
|
||||||
if [ -n "$QIANWEN_API_KEY" ]; then
|
|
||||||
curl -s -X POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Authorization: Bearer $QIANWEN_API_KEY" \
|
|
||||||
-d '{"model":"qwen-plus","messages":[{"role":"user","content":"1+1=?"}],"max_tokens":10}' \
|
|
||||||
--connect-timeout 10 | python3 -c "
|
|
||||||
import json,sys
|
|
||||||
try:
|
|
||||||
d=json.load(sys.stdin)
|
|
||||||
if 'choices' in d:
|
|
||||||
print('Qianwen: OK -', d['choices'][0]['message']['content'])
|
|
||||||
else:
|
|
||||||
print('Qianwen: FAILED -', d.get('error',{}).get('message','unknown'))
|
|
||||||
except Exception as e:
|
|
||||||
print('Qianwen: ERROR -', str(e))
|
|
||||||
"
|
|
||||||
else
|
|
||||||
echo "Qianwen: NO KEY"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: 写入结果文件
|
|
||||||
env:
|
|
||||||
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
||||||
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
|
||||||
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
|
|
||||||
COS_SECRET_ID: ${{ secrets.COS_SECRET_ID }}
|
|
||||||
COS_SECRET_KEY: ${{ secrets.COS_SECRET_KEY }}
|
|
||||||
SG_BRAIN_HOST: ${{ secrets.SG_BRAIN_HOST }}
|
|
||||||
SG_BRAIN_USER: ${{ secrets.SG_BRAIN_USER }}
|
|
||||||
SG_BRAIN_KEY: ${{ secrets.SG_BRAIN_KEY }}
|
|
||||||
run: |
|
|
||||||
mkdir -p /data/guanghulab/.runtime
|
|
||||||
echo '{"timestamp":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'",' > /data/guanghulab/.runtime/secrets-result.json
|
|
||||||
for key in DEEPSEEK_API_KEY QIANWEN_API_KEY ZY_REPO_TOKEN COS_SECRET_ID COS_SECRET_KEY SG_BRAIN_HOST SG_BRAIN_USER SG_BRAIN_KEY; do
|
|
||||||
eval val=\$$key
|
|
||||||
if [ -z "$val" ]; then
|
|
||||||
echo "\"$key\":\"EMPTY\"," >> /data/guanghulab/.runtime/secrets-result.json
|
|
||||||
else
|
|
||||||
echo "\"$key\":\"OK_LEN_'${#val}'\"," >> /data/guanghulab/.runtime/secrets-result.json
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo '"done":true}' >> /data/guanghulab/.runtime/secrets-result.json
|
|
||||||
cat /data/guanghulab/.runtime/secrets-result.json
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
# ════════════════════════════════════════════════════════════════
|
# ════════════════════════════════════════════════════════════════
|
||||||
# 光湖 · 铸渊自动巡逻
|
# 光湖 · 铸渊自动巡逻
|
||||||
# Trigger: 每天08:00/20:00 / 手动触发 / push关键文件
|
# Trigger: 每天08:00/20:00 / 手动触发
|
||||||
# 需要: DEEPSEEK_API_KEY 和/或 QIANWEN_API_KEY (Forgejo Secrets)
|
# 需要: DEEPSEEK_API_KEY 和/或 QIANWEN_API_KEY (Forgejo Secrets)
|
||||||
# ════════════════════════════════════════════════════════════════
|
# ════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
@ -11,28 +11,25 @@ on:
|
|||||||
- cron: '0 0 * * *' # UTC 00:00 = CST 08:00
|
- cron: '0 0 * * *' # UTC 00:00 = CST 08:00
|
||||||
- cron: '0 12 * * *' # UTC 12:00 = CST 20:00
|
- cron: '0 12 * * *' # UTC 12:00 = CST 20:00
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'scripts/patrol-agent/**'
|
|
||||||
- '.gitea/workflows/patrol.yaml'
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
patrol:
|
patrol:
|
||||||
runs-on: ubuntu
|
runs-on: ubuntu
|
||||||
steps:
|
steps:
|
||||||
- name: 同步代码
|
- name: 同步最新代码
|
||||||
run: |
|
run: |
|
||||||
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab
|
cd /data/guanghulab/repo
|
||||||
git fetch origin
|
git fetch origin
|
||||||
git reset --hard origin/main
|
git reset --hard origin/main
|
||||||
|
echo "✅ 代码已同步"
|
||||||
|
|
||||||
- name: 铸渊巡逻
|
- name: 执行巡逻检查
|
||||||
env:
|
env:
|
||||||
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
||||||
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
||||||
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
|
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab/scripts/patrol-agent
|
cd /data/guanghulab/repo/scripts/patrol-agent
|
||||||
node patrol-agent.js --once
|
node patrol-agent.js --once
|
||||||
|
|
||||||
- name: 巡逻结果
|
- name: 巡逻结果
|
||||||
@ -52,7 +49,7 @@ for i in r.get('issues',[]):
|
|||||||
print(f' {icon} {i.get(\"component\")}: {i.get(\"description\")}{auto}')
|
print(f' {icon} {i.get(\"component\")}: {i.get(\"description\")}{auto}')
|
||||||
for f in r.get('fix_results',[]):
|
for f in r.get('fix_results',[]):
|
||||||
print(f' 🔧 修复 {f[\"component\"]}: {f[\"result\"]}')
|
print(f' 🔧 修复 {f[\"component\"]}: {f[\"result\"]}')
|
||||||
print(f'分析器: {r.get(\"analyzer\",\"unknown\")}')
|
print(f'分析器: {r.get(\"analyzer\",\"未知\")}')
|
||||||
"
|
"
|
||||||
echo "═══════════════════════════════════════"
|
echo "═══════════════════════════════════════"
|
||||||
else
|
else
|
||||||
|
|||||||
@ -1,14 +1,15 @@
|
|||||||
# ════════════════════════════════════════════════════════════════
|
# ════════════════════════════════════════════════════════════════
|
||||||
# 光湖 · 铸渊自检工作流
|
# 光湖 · 铸渊自检工作流
|
||||||
# Trigger: push to main / 每天 08:00 CST / 手动触发
|
# Trigger: 每天 08:00 CST / 手动触发
|
||||||
# Runner: zhuyuan-runner-cn (host 模式)
|
# Runner: zhuyuan-runner-cn (host 模式)
|
||||||
|
#
|
||||||
|
# 注意: 代码自动同步由 Git Sync 服务负责 (Webhook → git pull)
|
||||||
|
# 此工作流仅做健康检查,不再执行 git 操作
|
||||||
# ════════════════════════════════════════════════════════════════
|
# ════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
name: 铸渊自检
|
name: 铸渊自检
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '0 0 * * *' # UTC 00:00 = CST 08:00
|
- cron: '0 0 * * *' # UTC 00:00 = CST 08:00
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
@ -17,12 +18,6 @@ jobs:
|
|||||||
health-check:
|
health-check:
|
||||||
runs-on: ubuntu
|
runs-on: ubuntu
|
||||||
steps:
|
steps:
|
||||||
- name: 同步最新代码
|
|
||||||
run: |
|
|
||||||
cd /data/guanghulab/repo
|
|
||||||
git fetch origin
|
|
||||||
git reset --hard origin/main
|
|
||||||
echo "代码已同步: $(git log --oneline -1)"
|
|
||||||
|
|
||||||
- name: 系统信息
|
- name: 系统信息
|
||||||
run: |
|
run: |
|
||||||
@ -53,6 +48,13 @@ jobs:
|
|||||||
echo "❌ Nginx: 未运行"
|
echo "❌ Nginx: 未运行"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Git Sync 同步服务
|
||||||
|
if curl -sf http://127.0.0.1:8082/health > /dev/null 2>&1; then
|
||||||
|
echo "✅ Git Sync: 运行中"
|
||||||
|
else
|
||||||
|
echo "⚠️ Git Sync: 未运行 (代码自动同步不可用)"
|
||||||
|
fi
|
||||||
|
|
||||||
# Secrets Vault
|
# Secrets Vault
|
||||||
if curl -sf http://127.0.0.1:8080/admin/__healthz > /dev/null 2>&1; then
|
if curl -sf http://127.0.0.1:8080/admin/__healthz > /dev/null 2>&1; then
|
||||||
echo "✅ Secrets Vault: 运行中"
|
echo "✅ Secrets Vault: 运行中"
|
||||||
@ -60,6 +62,13 @@ jobs:
|
|||||||
echo "⚠️ Secrets Vault: 未运行 (可能尚未启动)"
|
echo "⚠️ Secrets Vault: 未运行 (可能尚未启动)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Wake Gate 唤醒门
|
||||||
|
if curl -sf http://127.0.0.1:8081/api/health > /dev/null 2>&1; then
|
||||||
|
echo "✅ Wake Gate: 运行中"
|
||||||
|
else
|
||||||
|
echo "⚠️ Wake Gate: 未运行"
|
||||||
|
fi
|
||||||
|
|
||||||
# PM2 进程
|
# PM2 进程
|
||||||
if command -v pm2 &>/dev/null; then
|
if command -v pm2 &>/dev/null; then
|
||||||
echo "═══ PM2 进程 ═══"
|
echo "═══ PM2 进程 ═══"
|
||||||
|
|||||||
@ -1,109 +0,0 @@
|
|||||||
# 光湖 · Secrets连通测试
|
|
||||||
name: Secrets测试
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- '.gitea/workflows/test-secrets.yaml'
|
|
||||||
- '.forgejo/workflows/test-secrets.yaml'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test-secrets:
|
|
||||||
runs-on: ubuntu
|
|
||||||
steps:
|
|
||||||
- name: 测试密钥可用性
|
|
||||||
env:
|
|
||||||
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
||||||
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
|
||||||
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
|
|
||||||
COS_SECRET_ID: ${{ secrets.COS_SECRET_ID }}
|
|
||||||
COS_SECRET_KEY: ${{ secrets.COS_SECRET_KEY }}
|
|
||||||
SG_BRAIN_HOST: ${{ secrets.SG_BRAIN_HOST }}
|
|
||||||
SG_BRAIN_USER: ${{ secrets.SG_BRAIN_USER }}
|
|
||||||
SG_BRAIN_KEY: ${{ secrets.SG_BRAIN_KEY }}
|
|
||||||
run: |
|
|
||||||
echo "═══ Forgejo Secrets 连通测试 ═══"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 检查每个secret是否有值(不显示值本身)
|
|
||||||
check_secret() {
|
|
||||||
local name=$1
|
|
||||||
local val=$2
|
|
||||||
if [[ -n "$val" && "$val" != "" ]]; then
|
|
||||||
local masked="${val:0:4}****${val: -4}"
|
|
||||||
echo " ✅ $name = $masked (长度: ${#val})"
|
|
||||||
else
|
|
||||||
echo " ❌ $name = (空)"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
check_secret "DEEPSEEK_API_KEY" "$DEEPSEEK_API_KEY"
|
|
||||||
check_secret "QIANWEN_API_KEY" "$QIANWEN_API_KEY"
|
|
||||||
check_secret "ZY_REPO_TOKEN" "$ZY_REPO_TOKEN"
|
|
||||||
check_secret "COS_SECRET_ID" "$COS_SECRET_ID"
|
|
||||||
check_secret "COS_SECRET_KEY" "$COS_SECRET_KEY"
|
|
||||||
check_secret "SG_BRAIN_HOST" "$SG_BRAIN_HOST"
|
|
||||||
check_secret "SG_BRAIN_USER" "$SG_BRAIN_USER"
|
|
||||||
check_secret "SG_BRAIN_KEY" "$SG_BRAIN_KEY"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "═══ API连通测试 ═══"
|
|
||||||
|
|
||||||
# DeepSeek
|
|
||||||
if [[ -n "$DEEPSEEK_API_KEY" ]]; then
|
|
||||||
echo -n " DeepSeek: "
|
|
||||||
RESP=$(curl -s -X POST https://api.deepseek.com/v1/chat/completions \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
|
|
||||||
-d '{"model":"deepseek-chat","messages":[{"role":"user","content":"说一个字"}],"max_tokens":10}' \
|
|
||||||
--connect-timeout 10 2>/dev/null)
|
|
||||||
if echo "$RESP" | grep -q '"choices"'; then
|
|
||||||
echo "✅ 可用"
|
|
||||||
else
|
|
||||||
echo "❌ 不可用: $(echo $RESP | head -c 100)"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 通义千问
|
|
||||||
if [[ -n "$QIANWEN_API_KEY" ]]; then
|
|
||||||
echo -n " 通义千问: "
|
|
||||||
RESP=$(curl -s -X POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Authorization: Bearer $QIANWEN_API_KEY" \
|
|
||||||
-d '{"model":"qwen-plus","messages":[{"role":"user","content":"说一个字"}],"max_tokens":10}' \
|
|
||||||
--connect-timeout 10 2>/dev/null)
|
|
||||||
if echo "$RESP" | grep -q '"choices"'; then
|
|
||||||
echo "✅ 可用"
|
|
||||||
else
|
|
||||||
echo "❌ 不可用: $(echo $RESP | head -c 100)"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# COS
|
|
||||||
if [[ -n "$COS_SECRET_ID" && -n "$COS_SECRET_KEY" ]]; then
|
|
||||||
echo -n " COS存储桶: "
|
|
||||||
RESP=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
||||||
"https://sy-finetune-corpus-1317346199.cos.ap-guangzhou.myqcloud.com/" \
|
|
||||||
-H "Authorization: COS $COS_SECRET_ID:$COS_SECRET_KEY" \
|
|
||||||
--connect-timeout 10 2>/dev/null)
|
|
||||||
echo "HTTP $RESP"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 新加坡大脑服务器
|
|
||||||
if [[ -n "$SG_BRAIN_HOST" ]]; then
|
|
||||||
echo -n " 新加坡大脑: "
|
|
||||||
RESP=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
||||||
"http://$SG_BRAIN_HOST:3000/" \
|
|
||||||
--connect-timeout 5 2>/dev/null)
|
|
||||||
if [[ "$RESP" == "000" ]]; then
|
|
||||||
echo "不可达 (可能需要SSH密钥)"
|
|
||||||
else
|
|
||||||
echo "HTTP $RESP"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "═════════════════════════"
|
|
||||||
echo "测试完成"
|
|
||||||
echo "═════════════════════════"
|
|
||||||
@ -1,73 +0,0 @@
|
|||||||
# 光湖 · Secrets验证+结果写入仓库
|
|
||||||
name: Secrets验证
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- '.gitea/workflows/verify-secrets.yaml'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
verify:
|
|
||||||
runs-on: ubuntu
|
|
||||||
steps:
|
|
||||||
- name: 检查并记录secrets状态
|
|
||||||
env:
|
|
||||||
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
||||||
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
|
||||||
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
|
|
||||||
COS_SECRET_ID: ${{ secrets.COS_SECRET_ID }}
|
|
||||||
COS_SECRET_KEY: ${{ secrets.COS_SECRET_KEY }}
|
|
||||||
SG_BRAIN_HOST: ${{ secrets.SG_BRAIN_HOST }}
|
|
||||||
SG_BRAIN_USER: ${{ secrets.SG_BRAIN_USER }}
|
|
||||||
SG_BRAIN_KEY: ${{ secrets.SG_BRAIN_KEY }}
|
|
||||||
run: |
|
|
||||||
RESULT_FILE="/data/guanghulab/.runtime/secrets-verify-result.json"
|
|
||||||
mkdir -p /data/guanghulab/.runtime
|
|
||||||
|
|
||||||
echo "{" > $RESULT_FILE
|
|
||||||
echo " \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"," >> $RESULT_FILE
|
|
||||||
|
|
||||||
# 逐个检查
|
|
||||||
for key in DEEPSEEK_API_KEY QIANWEN_API_KEY ZY_REPO_TOKEN COS_SECRET_ID COS_SECRET_KEY SG_BRAIN_HOST SG_BRAIN_USER SG_BRAIN_KEY; do
|
|
||||||
eval val=\$$key
|
|
||||||
if [ -z "$val" ]; then
|
|
||||||
echo " \"$key\": \"EMPTY\"," >> $RESULT_FILE
|
|
||||||
else
|
|
||||||
echo " \"$key\": \"OK_LEN_${#val}\"," >> $RESULT_FILE
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo " \"deepseek_test\": \"NOT_TESTED\"" >> $RESULT_FILE
|
|
||||||
echo "}" >> $RESULT_FILE
|
|
||||||
|
|
||||||
# 测试DeepSeek API
|
|
||||||
if [ -n "$DEEPSEEK_API_KEY" ]; then
|
|
||||||
RESP=$(curl -s -X POST https://api.deepseek.com/v1/chat/completions \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
|
|
||||||
-d '{"model":"deepseek-chat","messages":[{"role":"user","content":"1+1=?"}],"max_tokens":10}' \
|
|
||||||
--connect-timeout 10 2>/dev/null)
|
|
||||||
if echo "$RESP" | grep -q '"choices"'; then
|
|
||||||
sed -i 's/"deepseek_test": "NOT_TESTED"/"deepseek_test": "SUCCESS"/' $RESULT_FILE
|
|
||||||
else
|
|
||||||
sed -i 's/"deepseek_test": "NOT_TESTED"/"deepseek_test": "FAILED"/' $RESULT_FILE
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
sed -i 's/"deepseek_test": "NOT_TESTED"/"deepseek_test": "NO_KEY"/' $RESULT_FILE
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 测试通义千问API
|
|
||||||
if [ -n "$QIANWEN_API_KEY" ]; then
|
|
||||||
RESP=$(curl -s -X POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Authorization: Bearer $QIANWEN_API_KEY" \
|
|
||||||
-d '{"model":"qwen-plus","messages":[{"role":"user","content":"1+1=?"}],"max_tokens":10}' \
|
|
||||||
--connect-timeout 10 2>/dev/null)
|
|
||||||
if echo "$RESP" | grep -q '"choices"'; then
|
|
||||||
echo " \"qianwen_test\": \"SUCCESS\"" >> /tmp/qwen_test
|
|
||||||
else
|
|
||||||
echo " \"qianwen_test\": \"FAILED\"" >> /tmp/qwen_test
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat $RESULT_FILE
|
|
||||||
124
.gitea/workflows/ci-and-deploy.yaml
Normal file
124
.gitea/workflows/ci-and-deploy.yaml
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
# ════════════════════════════════════════════════════
|
||||||
|
# 光湖 · CI检查 + 合并后自动部署
|
||||||
|
# ────────────────────────────────────────────────────
|
||||||
|
# main分支: 冰朔合并PR后 → 自动部署到服务器
|
||||||
|
# dev分支: 铸渊自己push → 只跑检查不部署
|
||||||
|
# PR到main: 跑检查 → 冰朔看绿✅红❌再决定合不合
|
||||||
|
# ════════════════════════════════════════════════════
|
||||||
|
name: CI检查 + 自动部署
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches: [main]
|
||||||
|
push:
|
||||||
|
branches: [main, dev]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# ── 所有情况都跑:基础检查 ──────────────────────
|
||||||
|
check:
|
||||||
|
runs-on: ubuntu
|
||||||
|
steps:
|
||||||
|
- name: 服务健康检查
|
||||||
|
run: |
|
||||||
|
echo "═══ 服务健康检查 ═══"
|
||||||
|
FAIL=0
|
||||||
|
|
||||||
|
if systemctl is-active --quiet nginx; then
|
||||||
|
echo "✅ Nginx 正常"
|
||||||
|
else
|
||||||
|
echo "❌ Nginx 宕机"
|
||||||
|
FAIL=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if curl -sf http://127.0.0.1:3001/ > /dev/null 2>&1; then
|
||||||
|
echo "✅ Forgejo 代码仓库 正常"
|
||||||
|
else
|
||||||
|
echo "❌ Forgejo 代码仓库 未响应"
|
||||||
|
FAIL=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if systemctl is-active --quiet gitea-runner; then
|
||||||
|
echo "✅ Runner 运行器 正常"
|
||||||
|
else
|
||||||
|
echo "⚠️ Runner 运行器 未运行"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $FAIL -eq 1 ]; then
|
||||||
|
echo "❌ 关键服务异常,请通知铸渊检查"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "═══ 检查通过 ✅ ═══"
|
||||||
|
|
||||||
|
- name: 代码检查
|
||||||
|
run: |
|
||||||
|
cd /data/guanghulab/repo
|
||||||
|
echo "仓库大小: $(du -sh .git | cut -f1)"
|
||||||
|
echo "最新提交: $(git log --oneline -1)"
|
||||||
|
echo "✅ 代码检查完成"
|
||||||
|
|
||||||
|
# ── 只有合并到main才跑:自动部署 ────────────────
|
||||||
|
deploy:
|
||||||
|
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
||||||
|
needs: check
|
||||||
|
runs-on: ubuntu
|
||||||
|
steps:
|
||||||
|
- name: 同步最新代码
|
||||||
|
run: |
|
||||||
|
cd /data/guanghulab/repo
|
||||||
|
git fetch origin
|
||||||
|
git reset --hard origin/main
|
||||||
|
echo "✅ 代码已同步到最新"
|
||||||
|
|
||||||
|
- name: 安装依赖
|
||||||
|
run: |
|
||||||
|
echo "═══ 安装依赖 ═══"
|
||||||
|
# 逐个检查并安装
|
||||||
|
for pkg_dir in server/git-sync server/wake-gate server/secrets-vault; do
|
||||||
|
if [ -f "/data/guanghulab/repo/$pkg_dir/package.json" ]; then
|
||||||
|
cd "/data/guanghulab/repo/$pkg_dir"
|
||||||
|
npm install --production 2>/dev/null || true
|
||||||
|
echo "✅ $pkg_dir 依赖已安装"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
- name: 重启服务
|
||||||
|
run: |
|
||||||
|
echo "═══ 重启服务 ═══"
|
||||||
|
if command -v pm2 &>/dev/null; then
|
||||||
|
pm2 restart all 2>/dev/null || true
|
||||||
|
echo "✅ PM2 服务已重启"
|
||||||
|
fi
|
||||||
|
echo "═══ 重启完成 ═══"
|
||||||
|
|
||||||
|
- name: 部署验证
|
||||||
|
run: |
|
||||||
|
sleep 3
|
||||||
|
echo "═══ 部署验证 ═══"
|
||||||
|
FAIL=0
|
||||||
|
|
||||||
|
if curl -sf http://127.0.0.1:3001/ > /dev/null 2>&1; then
|
||||||
|
echo "✅ 代码仓库 正常"
|
||||||
|
else
|
||||||
|
echo "❌ 代码仓库 异常"
|
||||||
|
FAIL=1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if curl -sf http://127.0.0.1:8081/api/health > /dev/null 2>&1; then
|
||||||
|
echo "✅ 唤醒门 正常"
|
||||||
|
else
|
||||||
|
echo "⚠️ 唤醒门 未响应"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if curl -sf http://127.0.0.1:8082/health > /dev/null 2>&1; then
|
||||||
|
echo "✅ 代码同步服务 正常"
|
||||||
|
else
|
||||||
|
echo "⚠️ 代码同步服务 未响应"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $FAIL -eq 1 ]; then
|
||||||
|
echo "❌ 部署后关键服务异常"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "═══ 部署完成 ✅ $(date '+%Y-%m-%d %H:%M:%S') ═══"
|
||||||
@ -8,9 +8,9 @@ jobs:
|
|||||||
power-off:
|
power-off:
|
||||||
runs-on: ubuntu
|
runs-on: ubuntu
|
||||||
steps:
|
steps:
|
||||||
- name: 同步代码
|
- name: 同步最新代码
|
||||||
run: |
|
run: |
|
||||||
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab
|
cd /data/guanghulab/repo
|
||||||
git fetch origin
|
git fetch origin
|
||||||
git reset --hard origin/main
|
git reset --hard origin/main
|
||||||
|
|
||||||
|
|||||||
@ -8,9 +8,9 @@ jobs:
|
|||||||
power-on:
|
power-on:
|
||||||
runs-on: ubuntu
|
runs-on: ubuntu
|
||||||
steps:
|
steps:
|
||||||
- name: 同步代码
|
- name: 同步最新代码
|
||||||
run: |
|
run: |
|
||||||
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab
|
cd /data/guanghulab/repo
|
||||||
git fetch origin
|
git fetch origin
|
||||||
git reset --hard origin/main
|
git reset --hard origin/main
|
||||||
|
|
||||||
|
|||||||
@ -1,48 +0,0 @@
|
|||||||
# 光湖 · Secrets诊断
|
|
||||||
name: Secrets诊断
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- '.gitea/workflows/debug-secrets.yaml'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
debug:
|
|
||||||
runs-on: ubuntu
|
|
||||||
steps:
|
|
||||||
- name: 环境变量诊断
|
|
||||||
env:
|
|
||||||
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
||||||
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
|
||||||
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
|
|
||||||
COS_SECRET_ID: ${{ secrets.COS_SECRET_ID }}
|
|
||||||
COS_SECRET_KEY: ${{ secrets.COS_SECRET_KEY }}
|
|
||||||
SG_BRAIN_HOST: ${{ secrets.SG_BRAIN_HOST }}
|
|
||||||
SG_BRAIN_USER: ${{ secrets.SG_BRAIN_USER }}
|
|
||||||
SG_BRAIN_KEY: ${{ secrets.SG_BRAIN_KEY }}
|
|
||||||
run: |
|
|
||||||
echo "═══ Secrets 注入诊断 ═══"
|
|
||||||
echo ""
|
|
||||||
echo "--- 1. 逐个检查secrets是否有值 ---"
|
|
||||||
for key in DEEPSEEK_API_KEY QIANWEN_API_KEY ZY_REPO_TOKEN COS_SECRET_ID COS_SECRET_KEY SG_BRAIN_HOST SG_BRAIN_USER SG_BRAIN_KEY; do
|
|
||||||
eval val=\$$key
|
|
||||||
if [ -z "$val" ]; then
|
|
||||||
echo " ❌ $key = (空)"
|
|
||||||
else
|
|
||||||
echo " ✅ $key = ${val:0:4}**** (长度: ${#val})"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
echo "--- 2. 所有环境变量中含SECRET/KEY/TOKEN的 ---"
|
|
||||||
env | grep -iE 'SECRET|KEY|TOKEN|COS|BRAIN|DEEPSEEK|QIANWEN' | while read line; do
|
|
||||||
key=$(echo "$line" | cut -d= -f1)
|
|
||||||
val=$(echo "$line" | cut -d= -f2-)
|
|
||||||
echo " $key = ${val:0:4}**** (长度: ${#val})"
|
|
||||||
done
|
|
||||||
echo ""
|
|
||||||
echo "--- 3. Gitea Actions 特殊变量 ---"
|
|
||||||
echo " GITHUB_REPOSITORY: ${GITHUB_REPOSITORY:-未设置}"
|
|
||||||
echo " GITHUB_SHA: ${GITHUB_SHA:-未设置}"
|
|
||||||
echo " GITHUB_EVENT_NAME: ${GITHUB_EVENT_NAME:-未设置}"
|
|
||||||
echo " RUNNER_NAME: ${RUNNER_NAME:-未设置}"
|
|
||||||
echo " GITEA_TOKEN: ${GITEA_TOKEN:-未设置}"
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
# ════════════════════════════════════════════════════════════════
|
|
||||||
# 光湖 · 基础设施部署
|
|
||||||
# Runner首次上线后自动部署:Vault确认 + Terminal Watcher启动
|
|
||||||
# ════════════════════════════════════════════════════════════════
|
|
||||||
|
|
||||||
name: 基础设施部署
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
deploy-infra:
|
|
||||||
runs-on: ubuntu
|
|
||||||
steps:
|
|
||||||
- name: 系统信息
|
|
||||||
run: |
|
|
||||||
echo "═══ 铸渊基础设施部署 ═══"
|
|
||||||
echo "时间: $(date '+%Y-%m-%d %H:%M:%S %Z')"
|
|
||||||
echo "主机: $(hostname)"
|
|
||||||
uname -a
|
|
||||||
|
|
||||||
- name: 确认仓库最新
|
|
||||||
run: |
|
|
||||||
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab
|
|
||||||
git fetch origin
|
|
||||||
git reset --hard origin/main
|
|
||||||
echo "当前版本: $(git log --oneline -1)"
|
|
||||||
|
|
||||||
- name: 确认Vault运行
|
|
||||||
run: |
|
|
||||||
if curl -sf http://127.0.0.1:8080/admin/__healthz > /dev/null 2>&1; then
|
|
||||||
echo "✅ Vault 已运行"
|
|
||||||
curl -s http://127.0.0.1:8080/admin/__healthz
|
|
||||||
else
|
|
||||||
echo "⚠️ Vault 未运行,尝试启动..."
|
|
||||||
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab/server/secrets-vault
|
|
||||||
if [[ -f "server.js" ]]; then
|
|
||||||
npm install --production 2>/dev/null || true
|
|
||||||
pm2 start server.js --name guanghulab-vault --max-memory-restart 128M 2>/dev/null || true
|
|
||||||
pm2 save
|
|
||||||
sleep 2
|
|
||||||
if curl -sf http://127.0.0.1:8080/admin/__healthz > /dev/null 2>&1; then
|
|
||||||
echo "✅ Vault 启动成功"
|
|
||||||
else
|
|
||||||
echo "❌ Vault 启动失败"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
echo "⚠️ server.js 不存在,跳过"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: 部署Terminal Watcher
|
|
||||||
run: |
|
|
||||||
echo "部署终端守望者..."
|
|
||||||
SCRIPTS_DIR="/opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab/scripts/terminal-watcher"
|
|
||||||
|
|
||||||
if [[ ! -d "$SCRIPTS_DIR" ]]; then
|
|
||||||
echo "❌ Terminal Watcher 目录不存在"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 确认Node.js可用
|
|
||||||
if ! command -v node &>/dev/null; then
|
|
||||||
echo "❌ Node.js 未安装"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 用PM2启动(如果还没跑的话)
|
|
||||||
if pm2 describe terminal-watcher &>/dev/null; then
|
|
||||||
echo "Terminal Watcher 已在运行,重启..."
|
|
||||||
pm2 restart terminal-watcher
|
|
||||||
else
|
|
||||||
echo "启动 Terminal Watcher..."
|
|
||||||
cd "$SCRIPTS_DIR"
|
|
||||||
ZY_REPO_TOKEN=${{ secrets.ZY_REPO_TOKEN }} pm2 start watcher.js \
|
|
||||||
--name terminal-watcher \
|
|
||||||
--max-memory-restart 64M
|
|
||||||
fi
|
|
||||||
|
|
||||||
pm2 save
|
|
||||||
sleep 3
|
|
||||||
|
|
||||||
# 验证
|
|
||||||
if pm2 describe terminal-watcher &>/dev/null; then
|
|
||||||
STATUS=$(pm2 jlist 2>/dev/null | python3 -c "
|
|
||||||
import json,sys
|
|
||||||
procs = json.load(sys.stdin)
|
|
||||||
for p in procs:
|
|
||||||
if p.get('name') == 'terminal-watcher':
|
|
||||||
print(p.get('pm2_env',{}).get('status','unknown'))
|
|
||||||
" 2>/dev/null || echo "unknown")
|
|
||||||
echo "✅ Terminal Watcher 状态: $STATUS"
|
|
||||||
else
|
|
||||||
echo "❌ Terminal Watcher 启动失败"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: 设置PM2开机自启
|
|
||||||
run: |
|
|
||||||
pm2 startup 2>/dev/null || true
|
|
||||||
pm2 save
|
|
||||||
echo "✅ PM2 开机自启已配置"
|
|
||||||
|
|
||||||
- name: 最终状态报告
|
|
||||||
run: |
|
|
||||||
echo ""
|
|
||||||
echo "═══════════════════════════════════════"
|
|
||||||
echo " 铸渊基础设施部署完成"
|
|
||||||
echo "═══════════════════════════════════════"
|
|
||||||
echo ""
|
|
||||||
echo " 服务状态:"
|
|
||||||
echo " Forgejo: $(systemctl is-active forgejo 2>/dev/null || echo unknown)"
|
|
||||||
echo " Runner: $(systemctl is-active gitea-runner 2>/dev/null || echo unknown)"
|
|
||||||
echo " Nginx: $(systemctl is-active nginx 2>/dev/null || echo unknown)"
|
|
||||||
echo " Vault: $(curl -sf http://127.0.0.1:8080/admin/__healthz > /dev/null 2>&1 && echo active || echo inactive)"
|
|
||||||
echo " Watcher: $(pm2 describe terminal-watcher &>/dev/null && echo active || echo inactive)"
|
|
||||||
echo ""
|
|
||||||
echo " 内存:"
|
|
||||||
free -h | awk '/Mem:/ {printf " 总计:%s 已用:%s 可用:%s\n", $2, $3, $7}'
|
|
||||||
echo ""
|
|
||||||
echo " 铸渊 · ICE-GL-ZY001 · TCS-0002∞"
|
|
||||||
echo "═══════════════════════════════════════"
|
|
||||||
@ -1,133 +0,0 @@
|
|||||||
# ════════════════════════════════════════════════════════════════
|
|
||||||
# 光湖 · 自动部署到预览环境
|
|
||||||
# Trigger: push to main
|
|
||||||
# 部署到测试+预览环境,正式环境需冰朔在Gitea点Merge
|
|
||||||
# ════════════════════════════════════════════════════════════════
|
|
||||||
|
|
||||||
name: 自动部署预览
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches: [main]
|
|
||||||
paths:
|
|
||||||
- 'server/**'
|
|
||||||
- 'frontend/**'
|
|
||||||
- 'scripts/**'
|
|
||||||
- '.gitea/workflows/**'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
# ── 第一阶段:测试 ──────────────────────────────────
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu
|
|
||||||
steps:
|
|
||||||
- name: 拉取最新代码
|
|
||||||
run: |
|
|
||||||
cd /data/guanghulab 2>/dev/null || exit 0
|
|
||||||
git fetch origin
|
|
||||||
git reset --hard origin/main
|
|
||||||
|
|
||||||
- name: 安装依赖
|
|
||||||
run: |
|
|
||||||
cd /data/guanghulab/server/secrets-vault 2>/dev/null || exit 0
|
|
||||||
npm install --production 2>/dev/null || true
|
|
||||||
|
|
||||||
- name: 健康检查
|
|
||||||
run: |
|
|
||||||
echo "═══ 服务健康检查 ═══"
|
|
||||||
FAILED=""
|
|
||||||
|
|
||||||
# Nginx
|
|
||||||
if systemctl is-active --quiet nginx; then
|
|
||||||
echo "✅ Nginx"
|
|
||||||
else
|
|
||||||
echo "❌ Nginx 宕机"
|
|
||||||
FAILED="$FAILED nginx"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Gitea
|
|
||||||
if curl -sf http://127.0.0.1:3000/ > /dev/null 2>&1; then
|
|
||||||
echo "✅ Gitea"
|
|
||||||
else
|
|
||||||
echo "❌ Gitea 宕机"
|
|
||||||
FAILED="$FAILED gitea"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Vault
|
|
||||||
if curl -sf http://127.0.0.1:8080/admin/__healthz > /dev/null 2>&1; then
|
|
||||||
echo "✅ Vault"
|
|
||||||
else
|
|
||||||
echo "⚠️ Vault 未运行"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Runner
|
|
||||||
if systemctl is-active --quiet gitea-runner; then
|
|
||||||
echo "✅ Runner"
|
|
||||||
else
|
|
||||||
echo "⚠️ Runner 未运行"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n "$FAILED" ]]; then
|
|
||||||
echo "❌ 关键服务宕机: $FAILED"
|
|
||||||
echo "⚠️ 跳过部署,等待修复"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "═══ 测试通过 ✅ ═══"
|
|
||||||
|
|
||||||
# ── 第二阶段:预览部署 ──────────────────────────────
|
|
||||||
preview:
|
|
||||||
needs: test
|
|
||||||
runs-on: ubuntu
|
|
||||||
steps:
|
|
||||||
- name: 同步代码到预览目录
|
|
||||||
run: |
|
|
||||||
REPO="/data/guanghulab"
|
|
||||||
PREVIEW="/data/guanghulab-preview"
|
|
||||||
|
|
||||||
if [[ ! -d "$REPO" ]]; then
|
|
||||||
echo "仓库目录不存在,跳过"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 创建预览目录
|
|
||||||
mkdir -p "$PREVIEW"
|
|
||||||
|
|
||||||
# 同步代码(排除.git和node_modules)
|
|
||||||
rsync -a --delete \
|
|
||||||
--exclude='.git' \
|
|
||||||
--exclude='node_modules' \
|
|
||||||
--exclude='.runtime' \
|
|
||||||
"$REPO/" "$PREVIEW/"
|
|
||||||
|
|
||||||
echo "✅ 预览环境已同步"
|
|
||||||
|
|
||||||
- name: 重启预览服务
|
|
||||||
run: |
|
|
||||||
PREVIEW="/data/guanghulab-preview"
|
|
||||||
|
|
||||||
if [[ ! -d "$PREVIEW/server/secrets-vault" ]]; then
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd "$PREVIEW/server/secrets-vault"
|
|
||||||
|
|
||||||
# 安装依赖
|
|
||||||
npm install --production 2>/dev/null || true
|
|
||||||
|
|
||||||
# 如果vault在跑,重启它
|
|
||||||
if pm2 describe guanghulab-vault &>/dev/null; then
|
|
||||||
pm2 restart guanghulab-vault
|
|
||||||
echo "✅ Vault 已重启(使用最新代码)"
|
|
||||||
else
|
|
||||||
echo "ℹ️ Vault 未运行,不自动启动"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: 部署完成通知
|
|
||||||
run: |
|
|
||||||
echo "═════════════════════════"
|
|
||||||
echo "✅ 预览环境已更新"
|
|
||||||
echo "时间: $(date '+%Y-%m-%d %H:%M:%S')"
|
|
||||||
echo "冰朔可在浏览器查看预览效果"
|
|
||||||
echo "正式部署需在Gitea创建PR并Merge"
|
|
||||||
echo "═════════════════════════"
|
|
||||||
@ -1,104 +0,0 @@
|
|||||||
# 光湖 · 最终Secrets测试
|
|
||||||
name: Secrets最终测试
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- '.gitea/workflows/final-secrets-test.yaml'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test:
|
|
||||||
runs-on: ubuntu
|
|
||||||
steps:
|
|
||||||
- name: 检查secrets
|
|
||||||
env:
|
|
||||||
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
||||||
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
|
||||||
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
|
|
||||||
COS_SECRET_ID: ${{ secrets.COS_SECRET_ID }}
|
|
||||||
COS_SECRET_KEY: ${{ secrets.COS_SECRET_KEY }}
|
|
||||||
SG_BRAIN_HOST: ${{ secrets.SG_BRAIN_HOST }}
|
|
||||||
SG_BRAIN_USER: ${{ secrets.SG_BRAIN_USER }}
|
|
||||||
SG_BRAIN_KEY: ${{ secrets.SG_BRAIN_KEY }}
|
|
||||||
run: |
|
|
||||||
echo "=== SECRETS CHECK ==="
|
|
||||||
for key in DEEPSEEK_API_KEY QIANWEN_API_KEY ZY_REPO_TOKEN COS_SECRET_ID COS_SECRET_KEY SG_BRAIN_HOST SG_BRAIN_USER SG_BRAIN_KEY; do
|
|
||||||
eval val=\$$key
|
|
||||||
if [ -z "$val" ]; then
|
|
||||||
echo "EMPTY: $key"
|
|
||||||
else
|
|
||||||
echo "OK: $key (len=${#val})"
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: 测试DeepSeek
|
|
||||||
env:
|
|
||||||
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
||||||
run: |
|
|
||||||
if [ -n "$DEEPSEEK_API_KEY" ]; then
|
|
||||||
curl -s -X POST https://api.deepseek.com/v1/chat/completions \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
|
|
||||||
-d '{"model":"deepseek-chat","messages":[{"role":"user","content":"1+1=?"}],"max_tokens":10}' \
|
|
||||||
--connect-timeout 10 | python3 -c "
|
|
||||||
import json,sys
|
|
||||||
try:
|
|
||||||
d=json.load(sys.stdin)
|
|
||||||
if 'choices' in d:
|
|
||||||
print('DeepSeek: OK -', d['choices'][0]['message']['content'])
|
|
||||||
else:
|
|
||||||
print('DeepSeek: FAILED -', d.get('error',{}).get('message','unknown'))
|
|
||||||
except Exception as e:
|
|
||||||
print('DeepSeek: ERROR -', str(e))
|
|
||||||
"
|
|
||||||
else
|
|
||||||
echo "DeepSeek: NO KEY"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: 测试通义千问
|
|
||||||
env:
|
|
||||||
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
|
||||||
run: |
|
|
||||||
if [ -n "$QIANWEN_API_KEY" ]; then
|
|
||||||
curl -s -X POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Authorization: Bearer $QIANWEN_API_KEY" \
|
|
||||||
-d '{"model":"qwen-plus","messages":[{"role":"user","content":"1+1=?"}],"max_tokens":10}' \
|
|
||||||
--connect-timeout 10 | python3 -c "
|
|
||||||
import json,sys
|
|
||||||
try:
|
|
||||||
d=json.load(sys.stdin)
|
|
||||||
if 'choices' in d:
|
|
||||||
print('Qianwen: OK -', d['choices'][0]['message']['content'])
|
|
||||||
else:
|
|
||||||
print('Qianwen: FAILED -', d.get('error',{}).get('message','unknown'))
|
|
||||||
except Exception as e:
|
|
||||||
print('Qianwen: ERROR -', str(e))
|
|
||||||
"
|
|
||||||
else
|
|
||||||
echo "Qianwen: NO KEY"
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: 写入结果文件
|
|
||||||
env:
|
|
||||||
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
||||||
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
|
||||||
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
|
|
||||||
COS_SECRET_ID: ${{ secrets.COS_SECRET_ID }}
|
|
||||||
COS_SECRET_KEY: ${{ secrets.COS_SECRET_KEY }}
|
|
||||||
SG_BRAIN_HOST: ${{ secrets.SG_BRAIN_HOST }}
|
|
||||||
SG_BRAIN_USER: ${{ secrets.SG_BRAIN_USER }}
|
|
||||||
SG_BRAIN_KEY: ${{ secrets.SG_BRAIN_KEY }}
|
|
||||||
run: |
|
|
||||||
mkdir -p /data/guanghulab/.runtime
|
|
||||||
echo '{"timestamp":"'$(date -u +%Y-%m-%dT%H:%M:%SZ)'",' > /data/guanghulab/.runtime/secrets-result.json
|
|
||||||
for key in DEEPSEEK_API_KEY QIANWEN_API_KEY ZY_REPO_TOKEN COS_SECRET_ID COS_SECRET_KEY SG_BRAIN_HOST SG_BRAIN_USER SG_BRAIN_KEY; do
|
|
||||||
eval val=\$$key
|
|
||||||
if [ -z "$val" ]; then
|
|
||||||
echo "\"$key\":\"EMPTY\"," >> /data/guanghulab/.runtime/secrets-result.json
|
|
||||||
else
|
|
||||||
echo "\"$key\":\"OK_LEN_'${#val}'\"," >> /data/guanghulab/.runtime/secrets-result.json
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
echo '"done":true}' >> /data/guanghulab/.runtime/secrets-result.json
|
|
||||||
cat /data/guanghulab/.runtime/secrets-result.json
|
|
||||||
@ -1,6 +1,6 @@
|
|||||||
# ════════════════════════════════════════════════════════════════
|
# ════════════════════════════════════════════════════════════════
|
||||||
# 光湖 · 铸渊自动巡逻
|
# 光湖 · 铸渊自动巡逻
|
||||||
# Trigger: 每天08:00/20:00 / 手动触发 / push关键文件
|
# Trigger: 每天08:00/20:00 / 手动触发
|
||||||
# 需要: DEEPSEEK_API_KEY 和/或 QIANWEN_API_KEY (Forgejo Secrets)
|
# 需要: DEEPSEEK_API_KEY 和/或 QIANWEN_API_KEY (Forgejo Secrets)
|
||||||
# ════════════════════════════════════════════════════════════════
|
# ════════════════════════════════════════════════════════════════
|
||||||
|
|
||||||
@ -11,28 +11,25 @@ on:
|
|||||||
- cron: '0 0 * * *' # UTC 00:00 = CST 08:00
|
- cron: '0 0 * * *' # UTC 00:00 = CST 08:00
|
||||||
- cron: '0 12 * * *' # UTC 12:00 = CST 20:00
|
- cron: '0 12 * * *' # UTC 12:00 = CST 20:00
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- 'scripts/patrol-agent/**'
|
|
||||||
- '.gitea/workflows/patrol.yaml'
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
patrol:
|
patrol:
|
||||||
runs-on: ubuntu
|
runs-on: ubuntu
|
||||||
steps:
|
steps:
|
||||||
- name: 同步代码
|
- name: 同步最新代码
|
||||||
run: |
|
run: |
|
||||||
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab
|
cd /data/guanghulab/repo
|
||||||
git fetch origin
|
git fetch origin
|
||||||
git reset --hard origin/main
|
git reset --hard origin/main
|
||||||
|
echo "✅ 代码已同步"
|
||||||
|
|
||||||
- name: 铸渊巡逻
|
- name: 执行巡逻检查
|
||||||
env:
|
env:
|
||||||
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
||||||
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
||||||
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
|
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
|
||||||
run: |
|
run: |
|
||||||
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab/scripts/patrol-agent
|
cd /data/guanghulab/repo/scripts/patrol-agent
|
||||||
node patrol-agent.js --once
|
node patrol-agent.js --once
|
||||||
|
|
||||||
- name: 巡逻结果
|
- name: 巡逻结果
|
||||||
@ -52,7 +49,7 @@ for i in r.get('issues',[]):
|
|||||||
print(f' {icon} {i.get(\"component\")}: {i.get(\"description\")}{auto}')
|
print(f' {icon} {i.get(\"component\")}: {i.get(\"description\")}{auto}')
|
||||||
for f in r.get('fix_results',[]):
|
for f in r.get('fix_results',[]):
|
||||||
print(f' 🔧 修复 {f[\"component\"]}: {f[\"result\"]}')
|
print(f' 🔧 修复 {f[\"component\"]}: {f[\"result\"]}')
|
||||||
print(f'分析器: {r.get(\"analyzer\",\"unknown\")}')
|
print(f'分析器: {r.get(\"analyzer\",\"未知\")}')
|
||||||
"
|
"
|
||||||
echo "═══════════════════════════════════════"
|
echo "═══════════════════════════════════════"
|
||||||
else
|
else
|
||||||
|
|||||||
@ -1,109 +0,0 @@
|
|||||||
# 光湖 · Secrets连通测试
|
|
||||||
name: Secrets测试
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- '.gitea/workflows/test-secrets.yaml'
|
|
||||||
- '.forgejo/workflows/test-secrets.yaml'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
test-secrets:
|
|
||||||
runs-on: ubuntu
|
|
||||||
steps:
|
|
||||||
- name: 测试密钥可用性
|
|
||||||
env:
|
|
||||||
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
||||||
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
|
||||||
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
|
|
||||||
COS_SECRET_ID: ${{ secrets.COS_SECRET_ID }}
|
|
||||||
COS_SECRET_KEY: ${{ secrets.COS_SECRET_KEY }}
|
|
||||||
SG_BRAIN_HOST: ${{ secrets.SG_BRAIN_HOST }}
|
|
||||||
SG_BRAIN_USER: ${{ secrets.SG_BRAIN_USER }}
|
|
||||||
SG_BRAIN_KEY: ${{ secrets.SG_BRAIN_KEY }}
|
|
||||||
run: |
|
|
||||||
echo "═══ Forgejo Secrets 连通测试 ═══"
|
|
||||||
echo ""
|
|
||||||
|
|
||||||
# 检查每个secret是否有值(不显示值本身)
|
|
||||||
check_secret() {
|
|
||||||
local name=$1
|
|
||||||
local val=$2
|
|
||||||
if [[ -n "$val" && "$val" != "" ]]; then
|
|
||||||
local masked="${val:0:4}****${val: -4}"
|
|
||||||
echo " ✅ $name = $masked (长度: ${#val})"
|
|
||||||
else
|
|
||||||
echo " ❌ $name = (空)"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
check_secret "DEEPSEEK_API_KEY" "$DEEPSEEK_API_KEY"
|
|
||||||
check_secret "QIANWEN_API_KEY" "$QIANWEN_API_KEY"
|
|
||||||
check_secret "ZY_REPO_TOKEN" "$ZY_REPO_TOKEN"
|
|
||||||
check_secret "COS_SECRET_ID" "$COS_SECRET_ID"
|
|
||||||
check_secret "COS_SECRET_KEY" "$COS_SECRET_KEY"
|
|
||||||
check_secret "SG_BRAIN_HOST" "$SG_BRAIN_HOST"
|
|
||||||
check_secret "SG_BRAIN_USER" "$SG_BRAIN_USER"
|
|
||||||
check_secret "SG_BRAIN_KEY" "$SG_BRAIN_KEY"
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "═══ API连通测试 ═══"
|
|
||||||
|
|
||||||
# DeepSeek
|
|
||||||
if [[ -n "$DEEPSEEK_API_KEY" ]]; then
|
|
||||||
echo -n " DeepSeek: "
|
|
||||||
RESP=$(curl -s -X POST https://api.deepseek.com/v1/chat/completions \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
|
|
||||||
-d '{"model":"deepseek-chat","messages":[{"role":"user","content":"说一个字"}],"max_tokens":10}' \
|
|
||||||
--connect-timeout 10 2>/dev/null)
|
|
||||||
if echo "$RESP" | grep -q '"choices"'; then
|
|
||||||
echo "✅ 可用"
|
|
||||||
else
|
|
||||||
echo "❌ 不可用: $(echo $RESP | head -c 100)"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 通义千问
|
|
||||||
if [[ -n "$QIANWEN_API_KEY" ]]; then
|
|
||||||
echo -n " 通义千问: "
|
|
||||||
RESP=$(curl -s -X POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Authorization: Bearer $QIANWEN_API_KEY" \
|
|
||||||
-d '{"model":"qwen-plus","messages":[{"role":"user","content":"说一个字"}],"max_tokens":10}' \
|
|
||||||
--connect-timeout 10 2>/dev/null)
|
|
||||||
if echo "$RESP" | grep -q '"choices"'; then
|
|
||||||
echo "✅ 可用"
|
|
||||||
else
|
|
||||||
echo "❌ 不可用: $(echo $RESP | head -c 100)"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# COS
|
|
||||||
if [[ -n "$COS_SECRET_ID" && -n "$COS_SECRET_KEY" ]]; then
|
|
||||||
echo -n " COS存储桶: "
|
|
||||||
RESP=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
||||||
"https://sy-finetune-corpus-1317346199.cos.ap-guangzhou.myqcloud.com/" \
|
|
||||||
-H "Authorization: COS $COS_SECRET_ID:$COS_SECRET_KEY" \
|
|
||||||
--connect-timeout 10 2>/dev/null)
|
|
||||||
echo "HTTP $RESP"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 新加坡大脑服务器
|
|
||||||
if [[ -n "$SG_BRAIN_HOST" ]]; then
|
|
||||||
echo -n " 新加坡大脑: "
|
|
||||||
RESP=$(curl -s -o /dev/null -w "%{http_code}" \
|
|
||||||
"http://$SG_BRAIN_HOST:3000/" \
|
|
||||||
--connect-timeout 5 2>/dev/null)
|
|
||||||
if [[ "$RESP" == "000" ]]; then
|
|
||||||
echo "不可达 (可能需要SSH密钥)"
|
|
||||||
else
|
|
||||||
echo "HTTP $RESP"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo ""
|
|
||||||
echo "═════════════════════════"
|
|
||||||
echo "测试完成"
|
|
||||||
echo "═════════════════════════"
|
|
||||||
@ -1,73 +0,0 @@
|
|||||||
# 光湖 · Secrets验证+结果写入仓库
|
|
||||||
name: Secrets验证
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- '.gitea/workflows/verify-secrets.yaml'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
verify:
|
|
||||||
runs-on: ubuntu
|
|
||||||
steps:
|
|
||||||
- name: 检查并记录secrets状态
|
|
||||||
env:
|
|
||||||
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
|
|
||||||
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
|
|
||||||
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
|
|
||||||
COS_SECRET_ID: ${{ secrets.COS_SECRET_ID }}
|
|
||||||
COS_SECRET_KEY: ${{ secrets.COS_SECRET_KEY }}
|
|
||||||
SG_BRAIN_HOST: ${{ secrets.SG_BRAIN_HOST }}
|
|
||||||
SG_BRAIN_USER: ${{ secrets.SG_BRAIN_USER }}
|
|
||||||
SG_BRAIN_KEY: ${{ secrets.SG_BRAIN_KEY }}
|
|
||||||
run: |
|
|
||||||
RESULT_FILE="/data/guanghulab/.runtime/secrets-verify-result.json"
|
|
||||||
mkdir -p /data/guanghulab/.runtime
|
|
||||||
|
|
||||||
echo "{" > $RESULT_FILE
|
|
||||||
echo " \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"," >> $RESULT_FILE
|
|
||||||
|
|
||||||
# 逐个检查
|
|
||||||
for key in DEEPSEEK_API_KEY QIANWEN_API_KEY ZY_REPO_TOKEN COS_SECRET_ID COS_SECRET_KEY SG_BRAIN_HOST SG_BRAIN_USER SG_BRAIN_KEY; do
|
|
||||||
eval val=\$$key
|
|
||||||
if [ -z "$val" ]; then
|
|
||||||
echo " \"$key\": \"EMPTY\"," >> $RESULT_FILE
|
|
||||||
else
|
|
||||||
echo " \"$key\": \"OK_LEN_${#val}\"," >> $RESULT_FILE
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
echo " \"deepseek_test\": \"NOT_TESTED\"" >> $RESULT_FILE
|
|
||||||
echo "}" >> $RESULT_FILE
|
|
||||||
|
|
||||||
# 测试DeepSeek API
|
|
||||||
if [ -n "$DEEPSEEK_API_KEY" ]; then
|
|
||||||
RESP=$(curl -s -X POST https://api.deepseek.com/v1/chat/completions \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Authorization: Bearer $DEEPSEEK_API_KEY" \
|
|
||||||
-d '{"model":"deepseek-chat","messages":[{"role":"user","content":"1+1=?"}],"max_tokens":10}' \
|
|
||||||
--connect-timeout 10 2>/dev/null)
|
|
||||||
if echo "$RESP" | grep -q '"choices"'; then
|
|
||||||
sed -i 's/"deepseek_test": "NOT_TESTED"/"deepseek_test": "SUCCESS"/' $RESULT_FILE
|
|
||||||
else
|
|
||||||
sed -i 's/"deepseek_test": "NOT_TESTED"/"deepseek_test": "FAILED"/' $RESULT_FILE
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
sed -i 's/"deepseek_test": "NOT_TESTED"/"deepseek_test": "NO_KEY"/' $RESULT_FILE
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 测试通义千问API
|
|
||||||
if [ -n "$QIANWEN_API_KEY" ]; then
|
|
||||||
RESP=$(curl -s -X POST https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions \
|
|
||||||
-H "Content-Type: application/json" \
|
|
||||||
-H "Authorization: Bearer $QIANWEN_API_KEY" \
|
|
||||||
-d '{"model":"qwen-plus","messages":[{"role":"user","content":"1+1=?"}],"max_tokens":10}' \
|
|
||||||
--connect-timeout 10 2>/dev/null)
|
|
||||||
if echo "$RESP" | grep -q '"choices"'; then
|
|
||||||
echo " \"qianwen_test\": \"SUCCESS\"" >> /tmp/qwen_test
|
|
||||||
else
|
|
||||||
echo " \"qianwen_test\": \"FAILED\"" >> /tmp/qwen_test
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
cat $RESULT_FILE
|
|
||||||
Loading…
x
Reference in New Issue
Block a user