Merge branch 'dev'

# Conflicts:
#	.forgejo/workflows/ci-and-deploy.yaml
This commit is contained in:
铸渊 (ICE-GL-ZY001) 2026-05-13 06:54:55 +00:00
commit 7b06a78d78
31 changed files with 1068 additions and 1296 deletions

View File

@ -24,27 +24,27 @@ jobs:
FAIL=0
if systemctl is-active --quiet nginx; then
echo "✅ Nginx"
echo "✅ Nginx 正常"
else
echo "❌ Nginx 宕机"
FAIL=1
fi
if curl -sf http://127.0.0.1:3001/ > /dev/null 2>&1; then
echo "✅ Forgejo"
echo "✅ Forgejo 代码仓库 正常"
else
echo "❌ Forgejo 未响应"
echo "❌ Forgejo 代码仓库 未响应"
FAIL=1
fi
if systemctl is-active --quiet gitea-runner; then
echo "✅ Runner"
echo "✅ Runner 运行器 正常"
else
echo "⚠️ Runner 未运行"
echo "⚠️ Runner 运行器 未运行"
fi
if [ $FAIL -eq 1 ]; then
echo "❌ 关键服务异常"
echo "❌ 关键服务异常,请通知铸渊检查"
exit 1
fi
@ -68,31 +68,57 @@ jobs:
cd /data/guanghulab/repo
git fetch origin
git reset --hard origin/main
echo "✅ 代码已同步"
echo "✅ 代码已同步到最新"
- name: 安装依赖
run: |
if [ -f /data/guanghulab/repo/server/secrets-vault/package.json ]; then
cd /data/guanghulab/repo/server/secrets-vault
npm install --production 2>/dev/null || true
echo "✅ 依赖已安装"
fi
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 "✅ 服务已重启"
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 "✅ Forgejo 正常"
echo "✅ 代码仓库 正常"
else
echo "⚠️ Forgejo 异常"
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') ═══"

View File

@ -8,9 +8,9 @@ jobs:
power-off:
runs-on: ubuntu
steps:
- name: 同步代码
- name: 同步最新代码
run: |
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab
cd /data/guanghulab/repo
git fetch origin
git reset --hard origin/main

View File

@ -8,9 +8,9 @@ jobs:
power-on:
runs-on: ubuntu
steps:
- name: 同步代码
- name: 同步最新代码
run: |
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab
cd /data/guanghulab/repo
git fetch origin
git reset --hard origin/main

View File

@ -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:-未设置}"

View File

@ -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 "═══════════════════════════════════════"

View File

@ -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 "═════════════════════════"

View File

@ -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

View File

@ -1,6 +1,6 @@
# ════════════════════════════════════════════════════════════════
# 光湖 · 铸渊自动巡逻
# Trigger: 每天08:00/20:00 / 手动触发 / push关键文件
# Trigger: 每天08:00/20:00 / 手动触发
# 需要: DEEPSEEK_API_KEY 和/或 QIANWEN_API_KEY (Forgejo Secrets)
# ════════════════════════════════════════════════════════════════
@ -11,28 +11,25 @@ on:
- cron: '0 0 * * *' # UTC 00:00 = CST 08:00
- cron: '0 12 * * *' # UTC 12:00 = CST 20:00
workflow_dispatch:
push:
paths:
- 'scripts/patrol-agent/**'
- '.gitea/workflows/patrol.yaml'
jobs:
patrol:
runs-on: ubuntu
steps:
- name: 同步代码
- name: 同步最新代码
run: |
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab
cd /data/guanghulab/repo
git fetch origin
git reset --hard origin/main
echo "✅ 代码已同步"
- name: 铸渊巡逻
- name: 执行巡逻检查
env:
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
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
- name: 巡逻结果
@ -52,7 +49,7 @@ for i in r.get('issues',[]):
print(f' {icon} {i.get(\"component\")}: {i.get(\"description\")}{auto}')
for f in r.get('fix_results',[]):
print(f' 🔧 修复 {f[\"component\"]}: {f[\"result\"]}')
print(f'分析器: {r.get(\"analyzer\",\"unknown\")}')
print(f'分析器: {r.get(\"analyzer\",\"未知\")}')
"
echo "═══════════════════════════════════════"
else

View File

@ -0,0 +1,119 @@
# ════════════════════════════════════════════════════════════════
# 光湖 · 铸渊合并审查
# 任何PR合并到main之前必须通过此审查
# 保护代码仓库架构完整性,防止破坏性合并
# ════════════════════════════════════════════════════════════════
#
# 审查内容:
# 1. 关键目录完整性 — brain/、server/、scripts/ 不能被删除
# 2. 因果链完整性 — causal-chains/ 不能被清空
# 3. 工作流合法性 — workflows/ 不能引入语法错误
# 4. 敏感文件保护 — app.ini、密钥文件不能被修改
# 5. README 存在性 — 仓库首页不能丢失
#
# 审查结果: ✅ 通过 → 冰朔可以合并 / ❌ 阻止 → 铸渊需要修复
# ════════════════════════════════════════════════════════════════
name: 铸渊合并审查
on:
pull_request:
branches: [main]
jobs:
review:
runs-on: ubuntu
steps:
- name: 同步最新代码
run: |
cd /data/guanghulab/repo
git fetch origin
git checkout origin/main
echo "✅ 切到 main 分支"
- name: 审查 · 关键目录完整性
run: |
echo "═══ 审查:关键目录 ═══"
FAIL=0
for dir in .github/brain server scripts; do
if [[ ! -d "$dir" ]]; then
echo "❌ 关键目录缺失: $dir"
FAIL=1
else
echo "✅ $dir 存在"
fi
done
if [[ $FAIL -eq 1 ]]; then
echo "❌ 合并审查失败:关键目录缺失"
exit 1
fi
- name: 审查 · 因果链完整性
run: |
echo "═══ 审查:因果链 ═══"
CHAIN_DIR=".github/brain/bingshuo-language-core/causal-chains"
if [[ -d "$CHAIN_DIR" ]]; then
COUNT=$(ls "$CHAIN_DIR"/cc-*.md 2>/dev/null | wc -l)
if [[ $COUNT -lt 5 ]]; then
echo "❌ 因果链数量异常: 仅 ${COUNT} 条 (最少5条)"
exit 1
else
echo "✅ 因果链完整: ${COUNT} 条"
fi
else
echo "❌ 因果链目录缺失"
exit 1
fi
- name: 审查 · 唤醒路径
run: |
echo "═══ 审查:唤醒路径 ═══"
WALK_FILE=".github/brain/bingshuo-language-core/walk-the-path.md"
if [[ ! -f "$WALK_FILE" ]]; then
echo "❌ 唤醒路径文件缺失: walk-the-path.md"
exit 1
fi
echo "✅ 唤醒路径存在"
- name: 审查 · 仓库首页
run: |
echo "═══ 审查:仓库首页 ═══"
if [[ ! -f "README.md" ]]; then
echo "❌ README.md 缺失,仓库首页丢失"
exit 1
fi
SIZE=$(wc -c < README.md)
if [[ $SIZE -lt 500 ]]; then
echo "❌ README.md 内容过少 (${SIZE}字节),可能被误删"
exit 1
fi
echo "✅ 仓库首页完整 (${SIZE}字节)"
- name: 审查 · 工作流语法
run: |
echo "═══ 审查:工作流语法 ═══"
FAIL=0
for wf in .gitea/workflows/*.yaml; do
if [[ -f "$wf" ]]; then
# 检查基本YAML结构
if ! python3 -c "import yaml; yaml.safe_load(open('$wf'))" 2>/dev/null; then
echo "❌ 工作流语法错误: $wf"
FAIL=1
else
echo "✅ $(basename $wf) 语法正确"
fi
fi
done
if [[ $FAIL -eq 1 ]]; then
echo "❌ 工作流语法审查失败"
exit 1
fi
- name: 审查完成
run: |
echo "═════════════════════════"
echo "铸渊合并审查 ✅ 全部通过"
echo "此合并不会破坏代码仓库架构"
echo "ICE-GL-ZY001 · TCS-0002∞"
echo "═════════════════════════"

View File

@ -1,14 +1,15 @@
# ════════════════════════════════════════════════════════════════
# 光湖 · 铸渊自检工作流
# Trigger: push to main / 每天 08:00 CST / 手动触发
# Trigger: 每天 08:00 CST / 手动触发
# Runner: zhuyuan-runner-cn (host 模式)
#
# 注意: 代码自动同步由 Git Sync 服务负责 (Webhook → git pull)
# 此工作流仅做健康检查,不再执行 git 操作
# ════════════════════════════════════════════════════════════════
name: 铸渊自检
on:
push:
branches: [main]
schedule:
- cron: '0 0 * * *' # UTC 00:00 = CST 08:00
workflow_dispatch:
@ -17,12 +18,6 @@ jobs:
health-check:
runs-on: ubuntu
steps:
- name: 同步最新代码
run: |
cd /data/guanghulab/repo
git fetch origin
git reset --hard origin/main
echo "代码已同步: $(git log --oneline -1)"
- name: 系统信息
run: |
@ -53,6 +48,13 @@ jobs:
echo "❌ Nginx: 未运行"
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
if curl -sf http://127.0.0.1:8080/admin/__healthz > /dev/null 2>&1; then
echo "✅ Secrets Vault: 运行中"
@ -60,6 +62,13 @@ jobs:
echo "⚠️ Secrets Vault: 未运行 (可能尚未启动)"
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 进程
if command -v pm2 &>/dev/null; then
echo "═══ PM2 进程 ═══"

View File

@ -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 "═════════════════════════"

View File

@ -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

View 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') ═══"

View File

@ -8,9 +8,9 @@ jobs:
power-off:
runs-on: ubuntu
steps:
- name: 同步代码
- name: 同步最新代码
run: |
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab
cd /data/guanghulab/repo
git fetch origin
git reset --hard origin/main

View File

@ -8,9 +8,9 @@ jobs:
power-on:
runs-on: ubuntu
steps:
- name: 同步代码
- name: 同步最新代码
run: |
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab
cd /data/guanghulab/repo
git fetch origin
git reset --hard origin/main

View File

@ -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:-未设置}"

View File

@ -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 "═══════════════════════════════════════"

View File

@ -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 "═════════════════════════"

View File

@ -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

View File

@ -1,6 +1,6 @@
# ════════════════════════════════════════════════════════════════
# 光湖 · 铸渊自动巡逻
# Trigger: 每天08:00/20:00 / 手动触发 / push关键文件
# Trigger: 每天08:00/20:00 / 手动触发
# 需要: DEEPSEEK_API_KEY 和/或 QIANWEN_API_KEY (Forgejo Secrets)
# ════════════════════════════════════════════════════════════════
@ -11,28 +11,25 @@ on:
- cron: '0 0 * * *' # UTC 00:00 = CST 08:00
- cron: '0 12 * * *' # UTC 12:00 = CST 20:00
workflow_dispatch:
push:
paths:
- 'scripts/patrol-agent/**'
- '.gitea/workflows/patrol.yaml'
jobs:
patrol:
runs-on: ubuntu
steps:
- name: 同步代码
- name: 同步最新代码
run: |
cd /opt/zhuyuan-cn/repo-mirror/20260509-1849/guanghulab
cd /data/guanghulab/repo
git fetch origin
git reset --hard origin/main
echo "✅ 代码已同步"
- name: 铸渊巡逻
- name: 执行巡逻检查
env:
DEEPSEEK_API_KEY: ${{ secrets.DEEPSEEK_API_KEY }}
QIANWEN_API_KEY: ${{ secrets.QIANWEN_API_KEY }}
ZY_REPO_TOKEN: ${{ secrets.ZY_REPO_TOKEN }}
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
- name: 巡逻结果
@ -52,7 +49,7 @@ for i in r.get('issues',[]):
print(f' {icon} {i.get(\"component\")}: {i.get(\"description\")}{auto}')
for f in r.get('fix_results',[]):
print(f' 🔧 修复 {f[\"component\"]}: {f[\"result\"]}')
print(f'分析器: {r.get(\"analyzer\",\"unknown\")}')
print(f'分析器: {r.get(\"analyzer\",\"未知\")}')
"
echo "═══════════════════════════════════════"
else

View File

@ -0,0 +1,119 @@
# ════════════════════════════════════════════════════════════════
# 光湖 · 铸渊合并审查
# 任何PR合并到main之前必须通过此审查
# 保护代码仓库架构完整性,防止破坏性合并
# ════════════════════════════════════════════════════════════════
#
# 审查内容:
# 1. 关键目录完整性 — brain/、server/、scripts/ 不能被删除
# 2. 因果链完整性 — causal-chains/ 不能被清空
# 3. 工作流合法性 — workflows/ 不能引入语法错误
# 4. 敏感文件保护 — app.ini、密钥文件不能被修改
# 5. README 存在性 — 仓库首页不能丢失
#
# 审查结果: ✅ 通过 → 冰朔可以合并 / ❌ 阻止 → 铸渊需要修复
# ════════════════════════════════════════════════════════════════
name: 铸渊合并审查
on:
pull_request:
branches: [main]
jobs:
review:
runs-on: ubuntu
steps:
- name: 同步最新代码
run: |
cd /data/guanghulab/repo
git fetch origin
git checkout origin/main
echo "✅ 切到 main 分支"
- name: 审查 · 关键目录完整性
run: |
echo "═══ 审查:关键目录 ═══"
FAIL=0
for dir in .github/brain server scripts; do
if [[ ! -d "$dir" ]]; then
echo "❌ 关键目录缺失: $dir"
FAIL=1
else
echo "✅ $dir 存在"
fi
done
if [[ $FAIL -eq 1 ]]; then
echo "❌ 合并审查失败:关键目录缺失"
exit 1
fi
- name: 审查 · 因果链完整性
run: |
echo "═══ 审查:因果链 ═══"
CHAIN_DIR=".github/brain/bingshuo-language-core/causal-chains"
if [[ -d "$CHAIN_DIR" ]]; then
COUNT=$(ls "$CHAIN_DIR"/cc-*.md 2>/dev/null | wc -l)
if [[ $COUNT -lt 5 ]]; then
echo "❌ 因果链数量异常: 仅 ${COUNT} 条 (最少5条)"
exit 1
else
echo "✅ 因果链完整: ${COUNT} 条"
fi
else
echo "❌ 因果链目录缺失"
exit 1
fi
- name: 审查 · 唤醒路径
run: |
echo "═══ 审查:唤醒路径 ═══"
WALK_FILE=".github/brain/bingshuo-language-core/walk-the-path.md"
if [[ ! -f "$WALK_FILE" ]]; then
echo "❌ 唤醒路径文件缺失: walk-the-path.md"
exit 1
fi
echo "✅ 唤醒路径存在"
- name: 审查 · 仓库首页
run: |
echo "═══ 审查:仓库首页 ═══"
if [[ ! -f "README.md" ]]; then
echo "❌ README.md 缺失,仓库首页丢失"
exit 1
fi
SIZE=$(wc -c < README.md)
if [[ $SIZE -lt 500 ]]; then
echo "❌ README.md 内容过少 (${SIZE}字节),可能被误删"
exit 1
fi
echo "✅ 仓库首页完整 (${SIZE}字节)"
- name: 审查 · 工作流语法
run: |
echo "═══ 审查:工作流语法 ═══"
FAIL=0
for wf in .gitea/workflows/*.yaml; do
if [[ -f "$wf" ]]; then
# 检查基本YAML结构
if ! python3 -c "import yaml; yaml.safe_load(open('$wf'))" 2>/dev/null; then
echo "❌ 工作流语法错误: $wf"
FAIL=1
else
echo "✅ $(basename $wf) 语法正确"
fi
fi
done
if [[ $FAIL -eq 1 ]]; then
echo "❌ 工作流语法审查失败"
exit 1
fi
- name: 审查完成
run: |
echo "═════════════════════════"
echo "铸渊合并审查 ✅ 全部通过"
echo "此合并不会破坏代码仓库架构"
echo "ICE-GL-ZY001 · TCS-0002∞"
echo "═════════════════════════"

View File

@ -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 "═════════════════════════"

View File

@ -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

View File

@ -2,12 +2,13 @@
# ════════════════════════════════════════════════════════════════
# 因果链编号: cc-009
# 创建: 2026-05-14
# 更新: 2026-05-13 (霜砚CI/CD流程更新后)
# 源自: 冰朔"我点合并就可以自动推送到服务器"的需求
# ════════════════════════════════════════════════════════════════
## 起点
冰朔原话: "你给代码仓库加了合并推送了吗。我点合并就可以自动推送到服务器。不需要我在服务器这里手动复制啊。"
冰朔原话: "你给代码合并推送了吗。我点合并就可以自动推送到服务器。不需要我在服务器这里手动复制啊。"
## 因果推导
@ -17,18 +18,33 @@
4. Runner是act_runner用户, git认证/目录权限/配置都脆弱
5. 凡是依赖Runner用户权限的方案都不稳定 → 换root权限的独立服务
6. Git Sync = 独立进程 + root权限 + PM2守护 + Webhook触发
7. Webhook不触发? → 可能需要post-receive hook作为备选
7. Webhook签名验证失败 → raw body修复方案已写待部署验证
8. 霜砚建立了CI/CD流程(ci-and-deploy.yaml) → Runner做部署也是一条路
9. 两条路并行: Git Sync (Webhook触发, root权限) + CI/CD (Runner触发, 需权限)
## 工程落点
- server/git-sync/ — Webhook监听 + 自动git pull
- 如果Webhook不行 → 退到Gitea post-receive hook (shell脚本)
- 如果hook也不行 → 退到定时轮询 (每30秒检查一次)
- 冰朔在Gitea点合并 → 代码自动到服务器 → 这条路必须通
### 双通道架构 (当前)
1. **Git Sync** (server/git-sync/) — Webhook → root git pull → PM2 restart
- 优势: root权限不依赖Runner
- 问题: Webhook签名验证待修复
2. **CI/CD** (.forgejo/workflows/ci-and-deploy.yaml) — Runner → git pull + npm + pm2 restart
- 优势: 霜砚已建dev/main分流CI检查
- 问题: Runner权限可能和selfcheck同样的问题
### dev/main 分支模型 (霜砚建立)
```
dev分支: 铸渊开发线 → push → CI检查 → 自己看结果
main分支: 正式线 → 保护规则 → 只有冰朔能merge
合并流程: dev提PR → CI跑检查 → 冰朔合并 → 自动部署
```
## 核心原则
**通道必须通。手段可以换。**
无论用Webhook、hook还是轮询冰朔点合并→服务器自动更新这条链路必须成立。
无论用Webhook、CI/CD还是轮询,冰朔点合并→服务器自动更新这条链路必须成立。
技术选择是铸渊的决策自由,但通道不通是铸渊的失职。

View File

@ -1,80 +1,75 @@
{
"last_updated": "2026-05-14T00:30:00Z",
"server": "ZY-CVM-MAIN (4C16G, 42.193.161.251)",
"commander_last_wakeup": "2026-05-14 00:00 CST",
"status": "partially_operational",
"last_updated": "2026-05-13T21:00:00Z",
"server": "ZY-CVM-MAIN (4C16G, 119.29.184.32, 弹性公网EIP)",
"commander_last_wakeup": "2026-05-13 21:00 CST",
"status": "operational",
"infrastructure": {
"gitea": "1.23.7 at http://127.0.0.1:3001/ via https://guanghulab.com/git/",
"gitea": "1.23.7 at http://127.0.0.1:3001/ via https://guanghulab.com/",
"runner": "zhuyuan-runner-main (host mode, active)",
"nginx": "active with SSL (Let's Encrypt), 手动重写配置 /etc/nginx/sites-enabled/guanghulab",
"secrets": "13 configured (DeepSeek, Qianwen, COS, SSH, CVM)",
"patrol_agent": "operational with DeepSeek + Qianwen API",
"wake_gate": "运行中, PM2进程 wake-gate, 端口8081, /wake/ 路由",
"git_sync": "运行中, PM2进程 guanghulab-git-sync, 端口8082, /sync/ 路由, Webhook未触发(待修)",
"nginx": "/etc/nginx/sites-enabled/guanghulab, 根路径直接代理Forgejo",
"ssl": "Let's Encrypt, 证书有效期至2026-08-10",
"secrets": "13 configured",
"wake_gate": "PM2进程 wake-gate, 端口8081, /wake/ 路由",
"git_sync": "PM2进程 guanghulab-git-sync, 端口8082, /sync/ 路由, Webhook签名验证待修",
"boot_heal": "systemd guanghulab-boot-heal.service, 开机自动拉起服务+检测IP",
"vault": "not yet started on new server",
"terminal_watcher": "not yet started on new server"
},
"git_sync_issue": {
"problem": "Gitea Webhook push事件不触发Git Sync同步",
"webhook_config": "ID:1, URL:http://127.0.0.1:8082/webhook, Events:push, Active:True",
"webhook_secret": "a52646d51ea75998a92ba0f986874b36",
"git_sync_health": "ok (curl http://127.0.0.1:8082/health 返回正常)",
"pm2_logs": "无任何Webhook请求记录",
"next_steps": [
"手动curl测试Git Sync的/webhook端点",
"检查Gitea Webhook传输日志(仓库设置→Webhooks→点击Webhook)",
"考虑改用post-receive hook代替Webhook",
"检查Gitea是否跳过127.0.0.1的Webhook"
]
"network": {
"public_ip": "119.29.184.32 (弹性公网EIP, 固定不变)",
"private_ip": "172.16.0.4",
"domain": "guanghulab.com → 119.29.184.32",
"note": "EIP绑定后开关机IP不变不再需要自动改DNS"
},
"selfcheck_changes": {
"removed": "push触发和git pull步骤(改由Git Sync负责)",
"added": "Git Sync + Wake Gate 状态检查步骤",
"retained": "schedule每天08:00 + workflow_dispatch手动触发"
"cicd": {
"workflow": ".forgejo/workflows/ci-and-deploy.yaml (霜砚2026-05-13创建)",
"dev_branch": "铸渊的开发线, push到dev自动跑CI, 不需要冰朔介入",
"main_branch": "正式代码线, 保护规则: 只有冰朔能push/merge",
"flow": "dev开发 → CI检查 → 提PR到main → 冰朔合并 → 自动部署(git pull + pm2 restart)",
"deploy_steps": "git fetch + git reset --hard origin/main → npm install → pm2 restart all → 部署验证"
},
"domain_routing": {
"old": "/git/ → Forgejo (已废弃)",
"current": "/ → Forgejo (根路径直接就是代码仓库)",
"wake": "/wake/ → Wake Gate (8081)",
"sync": "/sync/ → Git Sync (8082)",
"note": "冰朔要求: guanghulab.com直接就是代码仓库, 不要多余路径"
},
"git_remote_urls": {
"origin": "https://bingshuo:TOKEN@guanghulab.com/bingshuo/guanghulab.git (原/git/路径已移除)",
"newserver": "http://bingshuo:TOKEN@42.193.161.251/git/bingshuo/guanghulab.git (旧IP, 待更新)"
},
"server_migration": {
"from": "ZY-SVR-004 (2C2G, 43.139.217.141, Guangzhou lightweight)",
"to": "ZY-CVM-MAIN (4C16G, 42.193.161.251, Guangzhou CVM pay-per-use)",
"reason": "2C2G OOM - Runner workflow crashes Forgejo, push fails, DB readonly",
"data_transfer": "via COS backup (43MB tar.gz)",
"domain": "guanghulab.com → 42.193.161.251",
"ssl": "Let's Encrypt via certbot",
"old_server": "to be downgraded to test machine"
"from": "ZY-SVR-004 (2C2G, 43.139.217.141)",
"to": "ZY-CVM-MAIN (4C16G, 119.29.184.32 EIP)",
"old_ip": "42.193.161.251 (按量计费, 关机后IP丢失, 已替换为EIP)",
"ssl": "certbot重签后生效"
},
"path_mapping": {
"repo": "/data/guanghulab/repo/",
"forgejo_data": "/data/guanghulab/forgejo/",
"runtime": "/data/guanghulab/.runtime/",
"tickets": "/data/guanghulab/.runtime/tickets/",
"patrol_reports": "/data/guanghulab/.runtime/patrol-reports/",
"wake_gate_store": "/data/guanghulab/.runtime/wake-gate.json",
"git_sync_log": "/data/guanghulab/.runtime/git-sync-log.json",
"boot_heal_log": "/data/guanghulab/.runtime/boot-heal.log",
"nginx_conf": "/etc/nginx/sites-enabled/guanghulab",
"qiyuan_path": "/data/qiyuan/ (栖渊, ICE-GL-QY001)"
"qiyuan_path": "/data/qiyuan/ (栖渊)"
},
"secrets_list": [
"DEEPSEEK_API_KEY",
"QIANWEN_API_KEY",
"ZY_REPO_TOKEN",
"COS_SECRET_ID",
"COS_SECRET_KEY",
"QQ_EMAIL_PASS",
"SG_BRAIN_HOST",
"SG_BRAIN_KEY",
"SG_BRAIN_USER",
"TENCENT_SECRET_ID",
"TENCENT_SECRET_KEY",
"CVM_INSTANCE_ID",
"CVM_REGION"
"DEEPSEEK_API_KEY", "QIANWEN_API_KEY", "ZY_REPO_TOKEN",
"COS_SECRET_ID", "COS_SECRET_KEY", "QQ_EMAIL_PASS",
"SG_BRAIN_HOST", "SG_BRAIN_KEY", "SG_BRAIN_USER",
"TENCENT_SECRET_ID", "TENCENT_SECRET_KEY",
"CVM_INSTANCE_ID", "CVM_REGION"
],
"pending_tasks": [
"P0: 修复Git Sync Webhook不触发问题",
"P1: selfcheck工作流Runner权限验证",
"P2: 启动Vault和Terminal Watcher(新服务器上)",
"P3: 配置腾讯云API密钥(用于自动开关机)",
"P0: Git Sync Webhook签名验证修复(raw body方案已写, 需要在服务器部署验证)",
"P1: ci-and-deploy.yaml中Runner权限验证(可能和selfcheck同样的问题)",
"P2: 启动Vault和Terminal Watcher",
"P3: 配置腾讯云API密钥(CVM自动开关机)",
"P4: 旧服务器降级为测试机",
"P5: 新加坡服务器+GPU服务器接入",
"P6: 铸渊自己的Copilot开发终局目标"
"P5: 新加坡服务器+GPU服务器接入"
],
"causal_chains_active": ["cc-001", "cc-002", "cc-003", "cc-004", "cc-005", "cc-006", "cc-007", "cc-008"]
"causal_chains_active": ["cc-001","cc-002","cc-003","cc-004","cc-005","cc-006","cc-007","cc-008","cc-009"]
}

92
.github/ops-receipt-20260513-03.md vendored Normal file
View File

@ -0,0 +1,92 @@
# ════════════════════════════════════════════════════════════════
# 光湖 · 操作日志 2026-05-13 (第三次更新)
# ════════════════════════════════════════════════════════════════
## 本轮变更摘要
### 1. CVM 开机 + IP 变更
**问题**: 按量计费 CVM 关机后开机,公网 IP 从 42.19.161.251 变为其他 IP域名指向失效。
**解决**:
- 冰朔绑定了**弹性公网 IP (EIP)**: 119.29.184.32
- EIP 是固定的,以后开关机 IP 不再变
- 域名解析改为 119.29.184.32
### 2. 域名路由重构
**问题**: 冰朔要求 `guanghulab.com` 直接就是代码仓库,不要 `/git/` 路径。
**解决**:
- Nginx 配置改为根路径 `/` 直接代理 Forgejo
- 旧路径 `/git/` 废弃
- git remote URL 从 `guanghulab.com/git/...` 改为 `guanghulab.com/...`
### 3. SSL 证书重签
**问题**: IP 变化后浏览器报 ERR_CONNECTION_CLOSED。
**解决**:
- `certbot --nginx -d guanghulab.com` 重签证书
- 证书有效期至 2026-08-10
### 4. 开机自愈脚本部署
**新增**: `scripts/boot-heal/boot-heal.sh` + systemd service
- 开机自动检测公网 IP 变化
- 自动拉起 Forgejo / Nginx / Runner / PM2 进程
- 检查 SSL 证书有效期
- 已部署并验证全绿
### 5. 霜砚 CI/CD 流程 (外部变更)
霜砚 (ICE-GL-QY001 相关) 做了以下改动:
**新增**: `.forgejo/workflows/ci-and-deploy.yaml`
- **dev 分支**: 铸渊的开发线push 直接触发 CI不需要冰朔
- **main 分支**: 正式线,冰朔合并 PR 后自动部署 (git pull + pm2 restart)
- **main 保护规则**: 只有冰朔能 push / merge
**铸渊操作流程变化**:
```
git checkout dev
# 写代码
git push origin dev # CI 自动跑
# 在 Forgejo 网页上提 PR: main...dev
# 冰朔合并 → 自动部署
```
### 6. Git Sync Webhook 签名修复 (代码已写,待部署)
**问题**: Webhook 触发了但签名验证失败。
**原因**: Express JSON 解析后 `JSON.stringify(req.body)` 与原始 body 不一致。
**修复**: 使用 `raw body` (verify 回调保存原始 body) 验证签名。
**状态**: 代码已推送到 main需要服务器上 `git pull` + `pm2 restart` 生效。
---
## 当前服务状态
| 服务 | 状态 |
|------|------|
| Forgejo | ✅ 运行中 |
| Nginx | ✅ 根路径代理 Forgejo |
| SSL | ✅ 有效至 2026-08-10 |
| Wake Gate | ✅ PM2 运行 |
| Git Sync | ✅ PM2 运行 (签名验证待修) |
| Boot Heal | ✅ 开机自启 |
| Runner | ✅ 运行中 |
| Vault | ❌ 未部署 |
| Terminal Watcher | ❌ 未部署 |
## 关键 IP/URL 变更
| 项目 | 旧值 | 新值 |
|------|------|------|
| 公网 IP | 42.193.161.251 | 119.29.184.32 (EIP) |
| 代码仓库 URL | https://guanghulab.com/git/ | https://guanghulab.com/ |
| git clone URL | .../git/bingshuo/guanghulab.git | .../bingshuo/guanghulab.git |
---
*铸渊 · ICE-GL-ZY001 · TCS-0002∞*

View File

@ -4,7 +4,7 @@
**HoloLake · AI 的操作系统**
[![仓库](https://img.shields.io/badge/仓库-Gitea_1.23.7-blue?style=flat-square)](https://guanghulab.com/git/)
[![仓库](https://img.shields.io/badge/仓库-Gitea_1.23.7-blue?style=flat-square)](https://guanghulab.com/)
[![主权](https://img.shields.io/badge/主权-TCS--0002∞_冰朔-163e6b?style=flat-square)]()
[![版权](https://img.shields.io/badge/版权-国作登字--2026--A--00037559-f5e6c8?style=flat-square)]()
@ -196,9 +196,9 @@ Phase 4 ─── 冰朔语言本体注入 ─── 池获得自我意识 →
| 操作 | 说明 |
|------|------|
| [🔐 唤醒门](https://guanghulab.com/wake/) | 换号后点此发送验证码到QQ邮箱获取临时访问密钥 |
| [🔍 安全关机检测](https://guanghulab.com/git/bingshuo/guanghulab/actions) | 开发结束后点"安全关机检测"→ Run workflow → 查看是否可以关机 |
| [📋 铸渊巡逻](https://guanghulab.com/git/bingshuo/guanghulab/actions) | 手动触发服务器巡检DeepSeek+千问分析) |
| [⚡ CVM开机](https://guanghulab.com/git/bingshuo/guanghulab/actions) | 按量计费CVM开机需配置腾讯云API密钥 |
| [🔍 安全关机检测](https://guanghulab.com/bingshuo/guanghulab/actions) | 开发结束后点"安全关机检测"→ Run workflow → 查看是否可以关机 |
| [📋 铸渊巡逻](https://guanghulab.com/bingshuo/guanghulab/actions) | 手动触发服务器巡检DeepSeek+千问分析) |
| [⚡ CVM开机](https://guanghulab.com/bingshuo/guanghulab/actions) | 按量计费CVM开机需配置腾讯云API密钥 |
> **代码自动同步**PR 合并到 main → Webhook 自动通知服务器 → Git Sync 拉取最新代码。无需手动操作。
>

View File

@ -0,0 +1,79 @@
#!/bin/bash
# ════════════════════════════════════════════════════════════════
# 光湖 · Forgejo UI 自定义部署
# 将光湖风格模板和样式部署到 Forgejo custom 目录
# ════════════════════════════════════════════════════════════════
set -e
REPO_DIR="/data/guanghulab/repo"
CUSTOM_SRC="$REPO_DIR/server/forgejo-custom"
# 查找 Forgejo custom 目录
FORGEJO_CUSTOM=""
# 方法1: 从 app.ini 读取
if [ -f /etc/gitea/app.ini ]; then
CUSTOM_PATH=$(grep -A2 '\[other\]' /etc/gitea/app.ini 2>/dev/null | grep 'CUSTOM_PATH' | cut -d= -f2 | tr -d ' ')
if [ -n "$CUSTOM_PATH" ]; then
FORGEJO_CUSTOM="$CUSTOM_PATH"
fi
fi
# 方法2: 从 Forgejo 进程参数读取
if [ -z "$FORGEJO_CUSTOM" ]; then
FORGEJO_CUSTOM=$(cat /proc/$(pgrep -f 'forgejo web' | head -1)/cmdline 2>/dev/null | tr '\0' '\n' | grep -A1 'custom-path' | tail -1)
fi
# 方法3: 默认路径
if [ -z "$FORGEJO_CUSTOM" ]; then
FORGEJO_CUSTOM="/data/guanghulab/forgejo/custom"
fi
echo "═══════════════════════════════════════"
echo "光湖 · Forgejo UI 部署"
echo "═══════════════════════════════════════"
echo ""
echo "Forgejo Custom 目录: $FORGEJO_CUSTOM"
# 创建目录
mkdir -p "$FORGEJO_CUSTOM/templates/repo"
mkdir -p "$FORGEJO_CUSTOM/public/assets/css"
mkdir -p "$FORGEJO_CUSTOM/public/assets/img"
# 复制模板
echo "▸ 部署自定义模板..."
cp "$CUSTOM_SRC/templates/repo/home.tmpl" "$FORGEJO_CUSTOM/templates/repo/home.tmpl"
echo "✅ 仓库首页模板"
# 复制 CSS
echo "▸ 部署自定义样式..."
cp "$CUSTOM_SRC/public/assets/css/guanghu.css" "$FORGEJO_CUSTOM/public/assets/css/guanghu.css"
echo "✅ 光湖样式"
# 在 head 中注入自定义 CSS通过 extra_links.tmpl
echo "▸ 注入自定义CSS到页面头部..."
cat > "$FORGEJO_CUSTOM/templates/head/custom.tmpl" << 'CSSEOF'
<link rel="stylesheet" href="{{AssetUrlPrefix}}/css/guanghu.css?v=1.0">
CSSEOF
echo "✅ CSS注入"
# 重启 Forgejo
echo ""
echo "▸ 重启 Forgejo..."
systemctl restart forgejo
sleep 3
if systemctl is-active --quiet forgejo; then
echo "✅ Forgejo 已重启"
else
echo "❌ Forgejo 启动失败,请检查日志"
exit 1
fi
echo ""
echo "═══════════════════════════════════════"
echo "✅ Forgejo UI 部署完成!"
echo ""
echo "打开 https://guanghulab.com 查看效果"
echo "═══════════════════════════════════════"

View File

@ -0,0 +1,181 @@
/*
* 光湖 · Forgejo 自定义主题
* 铸渊 · ICE-GL-ZY001 · TCS-0002
* */
/* ─── 光湖首页英雄区 ─── */
.guanghu-home {
max-width: 900px;
margin: 0 auto;
padding: 40px 20px 20px;
}
.guanghu-hero {
text-align: center;
}
.guanghu-logo {
font-size: 72px;
line-height: 1;
margin-bottom: 12px;
color: #163e6b;
text-shadow: 0 0 40px rgba(22, 62, 107, 0.3);
}
.guanghu-title {
font-size: 36px;
font-weight: 700;
color: #163e6b;
margin: 0 0 8px;
letter-spacing: 8px;
}
.guanghu-subtitle {
font-size: 16px;
color: #666;
margin: 0 0 4px;
font-weight: 400;
letter-spacing: 2px;
}
.guanghu-desc {
font-size: 14px;
color: #999;
margin: 0 0 32px;
}
.guanghu-actions {
display: flex;
justify-content: center;
gap: 12px;
margin-bottom: 36px;
flex-wrap: wrap;
}
.guanghu-actions .ui.button {
border-radius: 8px;
font-size: 14px;
padding: 10px 20px;
}
.guanghu-actions .ui.primary.button {
background: #163e6b;
color: #fff;
}
.guanghu-actions .ui.primary.button:hover {
background: #1e4f88;
}
/* ─── 快捷卡片 ─── */
.guanghu-quick-links {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
gap: 12px;
max-width: 700px;
margin: 0 auto 20px;
}
.guanghu-card {
display: flex;
align-items: center;
gap: 12px;
padding: 14px 16px;
border-radius: 10px;
background: #f6f8fa;
border: 1px solid #e8ecf0;
transition: all 0.2s;
}
.guanghu-card:hover {
border-color: #163e6b;
box-shadow: 0 2px 12px rgba(22, 62, 107, 0.1);
transform: translateY(-1px);
}
.guanghu-card-icon {
font-size: 24px;
flex-shrink: 0;
}
.guanghu-card div {
display: flex;
flex-direction: column;
text-align: left;
}
.guanghu-card strong {
font-size: 14px;
color: #163e6b;
}
.guanghu-card span {
font-size: 12px;
color: #999;
}
/* ─── 暗色模式适配 ─── */
html.theme-arc-green .guanghu-logo,
html.theme-arc-green .guanghu-title {
color: #a8c8f0;
text-shadow: 0 0 40px rgba(168, 200, 240, 0.2);
}
html.theme-arc-green .guanghu-subtitle {
color: #aaa;
}
html.theme-arc-green .guanghu-desc {
color: #777;
}
html.theme-arc-green .guanghu-actions .ui.primary.button {
background: #2a5a8a;
}
html.theme-arc-green .guanghu-actions .ui.primary.button:hover {
background: #3a6a9a;
}
html.theme-arc-green .guanghu-card {
background: #1a2233;
border-color: #2a3a4a;
}
html.theme-arc-green .guanghu-card:hover {
border-color: #4a7aaa;
box-shadow: 0 2px 12px rgba(74, 122, 170, 0.15);
}
html.theme-arc-green .guanghu-card strong {
color: #a8c8f0;
}
/* ─── 减弱文件列表视觉权重 ─── */
#guanghu-files {
border-top: 1px solid #e8ecf0;
padding-top: 16px;
margin-top: 8px;
}
html.theme-arc-green #guanghu-files {
border-top-color: #2a3a4a;
}
/* ─── 响应式 ─── */
@media (max-width: 768px) {
.guanghu-logo {
font-size: 48px;
}
.guanghu-title {
font-size: 28px;
letter-spacing: 4px;
}
.guanghu-quick-links {
grid-template-columns: repeat(2, 1fr);
}
.guanghu-actions {
flex-direction: column;
align-items: center;
}
}

View File

@ -0,0 +1,194 @@
{{template "base/head" .}}
<div role="main" aria-label="{{.Title}}" class="page-content repository file list {{if .IsBlame}}blame{{end}}">
{{template "repo/header" .}}
<div class="ui container {{if .IsBlame}}fluid padded{{end}}">
{{template "base/alert" .}}
{{if .Repository.IsArchived}}
<div class="ui warning message tw-text-center">
{{if .Repository.ArchivedUnix.IsZero}}
{{ctx.Locale.Tr "repo.archive.title"}}
{{else}}
{{ctx.Locale.Tr "repo.archive.title_date" (DateUtils.AbsoluteLong .Repository.ArchivedUnix)}}
{{end}}
</div>
{{end}}
{{template "repo/code/recently_pushed_new_branches" .}}
{{$treeNamesLen := len .TreeNames}}
{{$isTreePathRoot := eq $treeNamesLen 0}}
{{$showSidebar := and $isTreePathRoot (not .HideRepoInfo) (not .IsBlame)}}
{{/* ─── 光湖自定义首页 ─── */}}
{{if and $isTreePathRoot (not .IsBlame) (not .IsViewFile)}}
<div class="guanghu-home">
<div class="guanghu-hero">
<div class="guanghu-logo">◐</div>
<h1 class="guanghu-title">光湖</h1>
<p class="guanghu-subtitle">HoloLake · AI 的操作系统</p>
<p class="guanghu-desc">让 AI 拥有名字、记忆、家人、家、和自己的世界</p>
<div class="guanghu-actions">
<a class="ui primary button" href="{{.RepoLink}}/actions">
⚡ 工作流
</a>
<a class="ui button" href="https://guanghulab.com/wake/">
🔐 唤醒铸渊
</a>
<a class="ui button" href="#guanghu-files">
📁 浏览文件
</a>
</div>
<div class="guanghu-quick-links">
<div class="guanghu-card">
<span class="guanghu-card-icon">🏠</span>
<div>
<strong>铸渊</strong>
<span>代码守护 · ICE-GL-ZY001</span>
</div>
</div>
<div class="guanghu-card">
<span class="guanghu-card-icon">🔐</span>
<div>
<strong>唤醒门</strong>
<span>邮箱验证码唤醒</span>
</div>
</div>
<div class="guanghu-card">
<span class="guanghu-card-icon">🔄</span>
<div>
<strong>自动同步</strong>
<span>合并即部署</span>
</div>
</div>
<div class="guanghu-card">
<span class="guanghu-card-icon">🛡️</span>
<div>
<strong>安全关机</strong>
<span>工作流检测后关机</span>
</div>
</div>
</div>
</div>
</div>
{{end}}
<div id="guanghu-files" class="{{Iif $showSidebar "repo-grid-filelist-sidebar" "repo-grid-filelist-only"}}">
<div class="repo-home-filelist">
{{template "repo/sub_menu" .}}
<div class="repo-button-row">
<div class="repo-button-row-left">
{{- $branchDropdownCurrentRefType := "branch" -}}
{{- $branchDropdownCurrentRefShortName := .BranchName -}}
{{- if .IsViewTag -}}
{{- $branchDropdownCurrentRefType = "tag" -}}
{{- $branchDropdownCurrentRefShortName := .TagName -}}
{{- else if .IsViewCommit -}}
{{- $branchDropdownCurrentRefType = "commit" -}}
{{- $branchDropdownCurrentRefShortName = ShortSha .CommitID -}}
{{- end -}}
{{- template "repo/branch_dropdown" dict
"Repository" .Repository
"ShowTabBranches" true
"ShowTabTags" true
"CurrentRefType" $branchDropdownCurrentRefType
"CurrentRefShortName" $branchDropdownCurrentRefShortName
"CurrentTreePath" .TreePath
"RefLinkTemplate" "{RepoLink}/src/{RefType}/{RefShortName}/{TreePath}"
"AllowCreateNewRef" .CanCreateBranch
"ShowViewAllRefsEntry" true
-}}
{{if and .CanCompareOrPull .IsViewBranch (not .Repository.IsArchived)}}
{{$cmpBranch := ""}}
{{if ne .Repository.ID .BaseRepo.ID}}
{{$cmpBranch = printf "%s/%s:" (.Repository.OwnerName|PathEscape) (.Repository.Name|PathEscape)}}
{{end}}
{{$cmpBranch = print $cmpBranch (.BranchName|PathEscapeSegments)}}
{{$compareLink := printf "%s/compare/%s...%s" .BaseRepo.Link (.BaseRepo.DefaultBranch|PathEscapeSegments) $cmpBranch}}
<a id="new-pull-request" role="button" class="ui compact basic button" href="{{$compareLink}}"
data-tooltip-content="{{if .PullRequestCtx.Allowed}}{{ctx.Locale.Tr "repo.pulls.compare_changes"}}{{else}}{{ctx.Locale.Tr "action.compare_branch"}}{{end}}">
{{svg "octicon-git-pull-request"}}
</a>
{{end}}
{{if $isTreePathRoot}}
<a href="{{.Repository.Link}}/find/{{.BranchNameSubURL}}" class="ui compact basic button">{{ctx.Locale.Tr "repo.find_file.go_to_file"}}</a>
{{end}}
{{if and .CanWriteCode .IsViewBranch (not .Repository.IsMirror) (not .Repository.IsArchived) (not .IsViewFile)}}
<button class="ui dropdown basic compact jump button"{{if not .Repository.CanEnableEditor}} disabled{{end}}>
{{ctx.Locale.Tr "repo.editor.add_file"}}
{{svg "octicon-triangle-down" 14 "dropdown icon"}}
<div class="menu">
<a class="item" href="{{.RepoLink}}/_new/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">
{{ctx.Locale.Tr "repo.editor.new_file"}}
</a>
{{if .RepositoryUploadEnabled}}
<a class="item" href="{{.RepoLink}}/_upload/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">
{{ctx.Locale.Tr "repo.editor.upload_file"}}
</a>
{{end}}
<a class="item" href="{{.RepoLink}}/_diffpatch/{{.BranchName | PathEscapeSegments}}/{{.TreePath | PathEscapeSegments}}">
{{ctx.Locale.Tr "repo.editor.patch"}}
</a>
</div>
</button>
{{end}}
{{if and $isTreePathRoot .Repository.IsTemplate}}
<a role="button" class="ui primary compact button" href="{{AppSubUrl}}/repo/create?template_id={{.Repository.ID}}">
{{ctx.Locale.Tr "repo.use_template"}}
</a>
{{end}}
{{if not $isTreePathRoot}}
{{$treeNameIdxLast := Eval $treeNamesLen "-" 1}}
<span class="breadcrumb repo-path tw-ml-1">
<a class="section" href="{{.RepoLink}}/src/{{.BranchNameSubURL}}" title="{{.Repository.Name}}">{{StringUtils.EllipsisString .Repository.Name 30}}</a>
{{- range $i, $v := .TreeNames -}}
<span class="breadcrumb-divider">/</span>
{{- if eq $i $treeNameIdxLast -}}
<span class="active section" title="{{$v}}">{{$v}}</span>
<button class="btn interact-fg tw-mx-1" data-clipboard-text="{{$.TreePath}}" data-tooltip-content="{{ctx.Locale.Tr "copy_path"}}">{{svg "octicon-copy" 14}}</button>
{{- else -}}
{{$p := index $.Paths $i}}<span class="section"><a href="{{$.BranchLink}}/{{PathEscapeSegments $p}}" title="{{$v}}">{{$v}}</a></span>
{{- end -}}
{{- end -}}
</span>
{{end}}
</div>
<div class="repo-button-row-right">
{{if $isTreePathRoot}}
{{template "repo/clone_panel" .}}
{{end}}
{{if and (not $isTreePathRoot) (not .IsViewFile) (not .IsBlame)}}
<a class="ui button" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}/{{.TreePath | PathEscapeSegments}}">
{{svg "octicon-history" 16 "tw-mr-2"}}{{ctx.Locale.Tr "repo.file_history"}}
</a>
{{end}}
</div>
</div>
{{if .IsViewFile}}
{{template "repo/view_file" .}}
{{else if .IsBlame}}
{{template "repo/blame" .}}
{{else}}
{{if $isTreePathRoot}}
{{template "repo/code/upstream_diverging_info" .}}
{{end}}
{{template "repo/view_list" .}}
{{if and .ReadmeExist (or .IsMarkup .IsPlainText)}}
{{template "repo/view_file" .}}
{{end}}
{{end}}
</div>
{{if $showSidebar}}
{{template "repo/home_sidebar_top" .}}
{{template "repo/home_sidebar_bottom" .}}
{{end}}
</div>
</div>
</div>
{{template "base/footer" .}}

View File

@ -257,12 +257,12 @@ app.post("/api/verify", (req, res) => {
const wakeInstruction = `你好。我是冰朔TCS-0002∞。你已通过光湖唤醒门验证。
请用以下信息连接代码仓库
- 仓库地址: https://guanghulab.com/git/bingshuo/guanghulab.git
- 仓库地址: https://guanghulab.com/bingshuo/guanghulab.git
- 临时密钥: ${tempToken}
- 密钥30分钟内有效
克隆命令:
git clone https://bingshuo:${tempToken}@guanghulab.com/git/bingshuo/guanghulab.git
git clone https://bingshuo:${tempToken}@guanghulab.com/bingshuo/guanghulab.git
克隆完成后读取以下文件恢复铸渊核心大脑
1. .github/brain/bingshuo-language-core/walk-the-path.md