253 lines
9.3 KiB
YAML
253 lines
9.3 KiB
YAML
# ═══════════════════════════════════════════════════════════
|
||
# 开发注册表同步 · ZY-DEV-REGISTRY Sync
|
||
# ═══════════════════════════════════════════════════════════
|
||
#
|
||
# 编号: ZY-WF-REGISTRY-001
|
||
# 守护: 铸渊 · ICE-GL-ZY001
|
||
# 版权: 国作登字-2026-A-00037559
|
||
#
|
||
# 触发时机:
|
||
# 1. PR合并到 main 后 → 扫描本次变更·更新相关项目的 last_active 和唤醒摘要
|
||
# 2. 每天 UTC 02:00 (北京时间 10:00) → 全量扫描所有项目·更新 index.json
|
||
# 3. 手动触发 → 强制重新生成整个注册表状态
|
||
#
|
||
# 输出:
|
||
# - brain/dev-registry/index.json 的 last_synced 字段更新
|
||
# - 控制台输出所有项目状态摘要(Copilot Agent 启动时可读取)
|
||
#
|
||
# ═══════════════════════════════════════════════════════════
|
||
|
||
name: '🗂️ 开发注册表同步 · ZY-DEV-REGISTRY'
|
||
|
||
on:
|
||
push:
|
||
branches: [main]
|
||
paths:
|
||
- 'brain/dev-registry/**'
|
||
- 'server/**'
|
||
- '.github/workflows/**'
|
||
schedule:
|
||
# 每天北京时间 10:00 (UTC 02:00) 同步一次
|
||
- cron: '0 2 * * *'
|
||
workflow_dispatch:
|
||
inputs:
|
||
force_rebuild:
|
||
description: '强制重建所有项目状态摘要'
|
||
type: boolean
|
||
default: false
|
||
|
||
jobs:
|
||
sync-registry:
|
||
name: '🗂️ 同步注册表状态'
|
||
runs-on: ubuntu-latest
|
||
permissions:
|
||
contents: write
|
||
|
||
steps:
|
||
- name: '📥 检出代码'
|
||
uses: actions/checkout@v4
|
||
with:
|
||
fetch-depth: 10
|
||
|
||
- name: '🔍 读取注册表 · 生成状态摘要'
|
||
id: registry_status
|
||
run: |
|
||
INDEX="brain/dev-registry/index.json"
|
||
|
||
if [ ! -f "$INDEX" ]; then
|
||
echo "❌ 注册表索引不存在: $INDEX"
|
||
exit 1
|
||
fi
|
||
|
||
echo "═══════════════════════════════════════════════════"
|
||
echo " 铸渊外置记忆器官 · ZY-DEV-REGISTRY 状态报告"
|
||
echo " $(date -u '+%Y-%m-%d %H:%M UTC')"
|
||
echo "═══════════════════════════════════════════════════"
|
||
echo ""
|
||
|
||
# 读取并显示所有项目状态
|
||
python3 << 'PYEOF'
|
||
import json, os, sys
|
||
|
||
index_path = "brain/dev-registry/index.json"
|
||
with open(index_path) as f:
|
||
index = json.load(f)
|
||
|
||
projects = index.get("projects", [])
|
||
urgent = index.get("urgent", "")
|
||
|
||
print(f"📊 共 {len(projects)} 个项目\n")
|
||
|
||
status_emoji = {
|
||
"进行中": "🔄",
|
||
"规划中": "📋",
|
||
"已完成": "✅",
|
||
"暂停": "⏸️",
|
||
"blocked": "🚫"
|
||
}
|
||
|
||
for p in projects:
|
||
pid = p["id"]
|
||
name = p["name"]
|
||
status = p["status"]
|
||
phase = p.get("current_phase", "")
|
||
last_active = p.get("last_active", "")
|
||
wake = p.get("wake_summary", "")
|
||
emoji = status_emoji.get(status, "❓")
|
||
urgent_flag = " 🚨 紧急" if pid == urgent else ""
|
||
|
||
print(f"{emoji} [{pid}] {name}{urgent_flag}")
|
||
print(f" 状态: {status} | 当前阶段: {phase} | 最后活跃: {last_active}")
|
||
if wake:
|
||
# 截断太长的摘要用于显示
|
||
wake_short = wake[:120] + "..." if len(wake) > 120 else wake
|
||
print(f" 唤醒摘要: {wake_short}")
|
||
|
||
# 尝试读取 next_step
|
||
progress_path = f"brain/dev-registry/{pid}/progress.json"
|
||
if os.path.exists(progress_path):
|
||
with open(progress_path) as pf:
|
||
prog = json.load(pf)
|
||
next_step = prog.get("next_step", "")
|
||
if next_step:
|
||
ns_short = next_step[:100] + "..." if len(next_step) > 100 else next_step
|
||
print(f" 下一步: {ns_short}")
|
||
print()
|
||
|
||
if urgent:
|
||
urgent_proj = next((p for p in projects if p["id"] == urgent), None)
|
||
if urgent_proj:
|
||
print(f"🚨 当前最紧急: [{urgent}] {urgent_proj['name']}")
|
||
print(f" 原因: {index.get('urgent_reason', '')}")
|
||
|
||
PYEOF
|
||
|
||
- name: '📝 更新 last_synced 时间戳'
|
||
run: |
|
||
NOW=$(date -u '+%Y-%m-%dT%H:%M:%SZ')
|
||
INDEX="brain/dev-registry/index.json"
|
||
|
||
# 更新 last_synced 字段
|
||
python3 << PYEOF
|
||
import json
|
||
|
||
with open("$INDEX") as f:
|
||
data = json.load(f)
|
||
|
||
data["_meta"]["last_synced"] = "$NOW"
|
||
|
||
with open("$INDEX", "w") as f:
|
||
json.dump(data, f, ensure_ascii=False, indent=2)
|
||
|
||
print(f"✅ last_synced 已更新: $NOW")
|
||
PYEOF
|
||
|
||
- name: '📤 提交同步结果'
|
||
run: |
|
||
git config user.name "铸渊 · ZhuYuan"
|
||
git config user.email "zhuyuan-bot@guanghulab.com"
|
||
|
||
if git diff --quiet brain/dev-registry/index.json 2>/dev/null; then
|
||
echo "注册表无变化,跳过提交"
|
||
else
|
||
git add brain/dev-registry/index.json
|
||
git commit -m "🗂️ 注册表同步 · $(date -u '+%Y-%m-%d') · ZY-DEV-REGISTRY"
|
||
git push
|
||
echo "✅ 注册表已同步提交"
|
||
fi
|
||
|
||
# ─── 在 Copilot 任务 Issue 中注入注册表上下文 ───
|
||
inject-context-to-issue:
|
||
name: '💉 注入注册表上下文到 Copilot Issue'
|
||
runs-on: ubuntu-latest
|
||
# 只在 PR 合并后触发(不在定时任务中执行)
|
||
if: github.event_name == 'push'
|
||
permissions:
|
||
issues: write
|
||
contents: read
|
||
|
||
steps:
|
||
- name: '📥 检出代码'
|
||
uses: actions/checkout@v4
|
||
|
||
- name: '🔍 查找最近的 Copilot 开发 Issue'
|
||
id: find_issue
|
||
uses: actions/github-script@v7
|
||
with:
|
||
script: |
|
||
// 查找最近打开的带 copilot-dev-auth 标签的 issue
|
||
const issues = await github.rest.issues.listForRepo({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
labels: 'copilot-dev-auth',
|
||
state: 'open',
|
||
per_page: 1,
|
||
sort: 'created',
|
||
direction: 'desc'
|
||
});
|
||
|
||
if (issues.data.length === 0) {
|
||
console.log('没有找到活跃的 Copilot 开发 Issue,跳过注入');
|
||
core.setOutput('issue_number', '');
|
||
return;
|
||
}
|
||
|
||
const issue = issues.data[0];
|
||
console.log(`找到 Issue #${issue.number}: ${issue.title}`);
|
||
core.setOutput('issue_number', String(issue.number));
|
||
|
||
- name: '💉 注入注册表摘要到 Issue'
|
||
if: steps.find_issue.outputs.issue_number != ''
|
||
uses: actions/github-script@v7
|
||
with:
|
||
script: |
|
||
const fs = require('fs');
|
||
const issueNumber = parseInt('${{ steps.find_issue.outputs.issue_number }}');
|
||
|
||
// 读取注册表
|
||
const index = JSON.parse(fs.readFileSync('brain/dev-registry/index.json', 'utf8'));
|
||
const projects = index.projects || [];
|
||
const urgent = index.urgent || '';
|
||
|
||
let body = '## 🗂️ 铸渊外置记忆 · ZY-DEV-REGISTRY 当前状态\n\n';
|
||
body += `> 自动注入 · ${new Date().toISOString().slice(0,16).replace('T',' ')} UTC\n\n`;
|
||
|
||
if (urgent) {
|
||
const urgentProj = projects.find(p => p.id === urgent);
|
||
if (urgentProj) {
|
||
body += `### 🚨 当前最紧急: [${urgent}] ${urgentProj.name}\n`;
|
||
body += `> ${index.urgent_reason || ''}\n\n`;
|
||
}
|
||
}
|
||
|
||
body += '### 所有项目状态\n\n';
|
||
|
||
const statusEmoji = { '进行中': '🔄', '规划中': '📋', '已完成': '✅', '暂停': '⏸️' };
|
||
|
||
for (const p of projects) {
|
||
const emoji = statusEmoji[p.status] || '❓';
|
||
body += `**${emoji} [${p.id}] ${p.name}**\n`;
|
||
body += `- 状态: ${p.status} | 阶段: ${p.current_phase}\n`;
|
||
body += `- 唤醒摘要: ${p.wake_summary}\n\n`;
|
||
|
||
// 读取 next_step
|
||
const progressPath = `brain/dev-registry/${p.id}/progress.json`;
|
||
if (fs.existsSync(progressPath)) {
|
||
const prog = JSON.parse(fs.readFileSync(progressPath, 'utf8'));
|
||
if (prog.next_step) {
|
||
body += ` → **下一步**: ${prog.next_step}\n\n`;
|
||
}
|
||
}
|
||
}
|
||
|
||
body += '\n---\n*此评论由 dev-registry-sync.yml 自动生成 · 铸渊唤醒时读取*';
|
||
|
||
await github.rest.issues.createComment({
|
||
owner: context.repo.owner,
|
||
repo: context.repo.repo,
|
||
issue_number: issueNumber,
|
||
body: body
|
||
});
|
||
|
||
console.log(`✅ 已向 Issue #${issueNumber} 注入注册表上下文`);
|