guanghulab/skyeye/hibernation/distributor.js
Guanghu Domestic Migration d1e47f4565
Some checks are pending
自动更新代码和重启 / update-and-restart (push) Waiting to run
CI检查 + 自动部署 / check (push) Waiting to run
CI检查 + 自动部署 / deploy (push) Blocked by required conditions
重启聊天服务 / restart (push) Waiting to run
chore: import sanitized domestic snapshot for REPO-002
Source snapshot: ca48d3ddf926d79aa138306164169baf764bb829
2026-07-17 15:54:41 +08:00

204 lines
6.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

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

#!/usr/bin/env node
/**
* skyeye/hibernation/distributor.js
* ═══════════════════════════════════════════════
* 🔺 Sovereign: TCS-0002∞ | Root: SYS-GLW-0001
* 📜 Copyright: 国作登字-2026-A-00037559
* ═══════════════════════════════════════════════
*
* 📦 分布式升级传播引擎
* 读取升级包中的 soldier_upgrade_manifest
* 通过 repository_dispatch 向子仓库分发升级指令。
*
* 用法:
* node distributor.js [--pack=path/to/upgrade-pack.json]
*
* 环境变量:
* GITHUB_TOKEN - 用于 API 调用
*/
'use strict';
const fs = require('fs');
const path = require('path');
const https = require('https');
const UPGRADE_DIR = path.join(__dirname, 'upgrade-packs');
const DIST_DIR = path.join(__dirname, 'distribution-reports');
// ━━━ 工具函数 ━━━
function getTimestamp() {
return new Date().toISOString();
}
function getDateStr() {
return new Date().toISOString().slice(0, 10).replace(/-/g, '');
}
function loadJSON(filePath) {
try {
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
} catch (e) {
return null;
}
}
function saveJSON(filePath, data) {
const dir = path.dirname(filePath);
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n', 'utf8');
}
// ━━━ GitHub API dispatch ━━━
function dispatchUpgrade(owner, repo, manifest) {
return new Promise((resolve, reject) => {
const token = process.env.GITHUB_TOKEN || process.env.HUB_TOKEN;
if (!token) {
console.log(` ⚠️ 无 GITHUB_TOKEN跳过 dispatch 到 ${owner}/${repo}`);
resolve({ target: `${owner}/${repo}`, status: 'skipped', reason: 'no_token' });
return;
}
const payload = JSON.stringify({
event_type: 'skyeye-upgrade',
client_payload: {
template_version: manifest.template_version,
changes: manifest.changes,
issued_by: 'skyeye-weekly-hibernation',
issued_at: getTimestamp()
}
});
const options = {
hostname: 'api.github.com',
port: 443,
path: `/repos/${owner}/${repo}/dispatches`,
method: 'POST',
headers: {
'Authorization': `token ${token}`,
'Accept': 'application/vnd.github.v3+json',
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(payload),
'User-Agent': 'skyeye-distributor'
}
};
const req = https.request(options, (res) => {
let body = '';
res.on('data', (chunk) => body += chunk);
res.on('end', () => {
if (res.statusCode === 204 || res.statusCode === 200) {
resolve({
target: `${owner}/${repo}`,
status: 'dispatched',
dispatched_at: getTimestamp()
});
} else {
resolve({
target: `${owner}/${repo}`,
status: 'failed',
http_status: res.statusCode,
error: body
});
}
});
});
req.on('error', (e) => {
resolve({
target: `${owner}/${repo}`,
status: 'failed',
error: e.message
});
});
req.write(payload);
req.end();
});
}
// ━━━ 主流程 ━━━
async function distributeUpgrades(manifest) {
const results = [];
const owner = 'qinfendebingshuo';
for (const target of manifest.targets) {
console.log(` 📡 分发升级到: ${owner}/${target}`);
const result = await dispatchUpgrade(owner, target, manifest);
results.push(result);
console.log(`${result.status}`);
}
return {
total: manifest.targets.length,
success: results.filter(r => r.status === 'dispatched').length,
failed: results.filter(r => r.status === 'failed').length,
skipped: results.filter(r => r.status === 'skipped').length,
details: results
};
}
async function run() {
console.log('═══════════════════════════════════════════════');
console.log('📦 分布式升级传播引擎');
console.log('═══════════════════════════════════════════════');
const args = process.argv.slice(2);
const packArg = args.find(a => a.startsWith('--pack='));
// 查找升级包
let upgradePack = null;
if (packArg) {
const packPath = packArg.split('=')[1];
upgradePack = loadJSON(packPath);
} else {
// 查找最新升级包
if (fs.existsSync(UPGRADE_DIR)) {
const packFiles = fs.readdirSync(UPGRADE_DIR)
.filter(f => f.startsWith('upgrade-pack-') && f.endsWith('.json'))
.sort();
if (packFiles.length > 0) {
upgradePack = loadJSON(path.join(UPGRADE_DIR, packFiles[packFiles.length - 1]));
}
}
}
if (!upgradePack || !upgradePack.soldier_upgrade_manifest) {
console.log('⚠️ 未找到升级包或无 soldier_upgrade_manifest跳过分发');
return { status: 'skipped', reason: 'no_manifest' };
}
const manifest = upgradePack.soldier_upgrade_manifest;
console.log(`📋 升级模板版本: ${manifest.template_version}`);
console.log(`🎯 目标子仓库: ${manifest.targets.length}`);
console.log('');
const result = await distributeUpgrades(manifest);
// 写入分发报告
const report = {
report_id: `DIST-REPORT-${getDateStr()}`,
upgrade_pack_id: upgradePack.upgrade_pack_id,
timestamp: getTimestamp(),
template_version: manifest.template_version,
distribution: result
};
const reportPath = path.join(DIST_DIR, `dist-report-${getDateStr()}.json`);
saveJSON(reportPath, report);
console.log('');
console.log(`📋 分发报告: ${reportPath}`);
console.log(`✅ 成功: ${result.success} / 失败: ${result.failed} / 跳过: ${result.skipped}`);
return report;
}
module.exports = { distributeUpgrades, run };
if (require.main === module) {
run().catch(console.error);
}