guanghulab/skyeye/hibernation/distributor.js

204 lines
6.1 KiB
JavaScript
Raw Normal View History

#!/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);
}