141 lines
4.7 KiB
JavaScript
141 lines
4.7 KiB
JavaScript
/**
|
||
* ━━━ 实时进度上报模块 ━━━
|
||
* 文件位置:scripts/pipeline-reporter.js
|
||
*
|
||
* 每完成一步,在 Issue 评论区发一条新评论,开发者刷新即可看到实时进度。
|
||
*
|
||
* 使用方式(CLI):
|
||
* ISSUE_NUMBER=92 STEP_NUM=2 STEP_NAME="解析内容" STEP_STATUS=ok \
|
||
* STEP_DETAIL="广播编号: BC-M22-007-AW" GITHUB_TOKEN=xxx \
|
||
* node scripts/pipeline-reporter.js
|
||
*
|
||
* 或在 Node.js 中 require:
|
||
* const { reportStep, reportComplete } = require('./pipeline-reporter');
|
||
*/
|
||
|
||
const https = require('https');
|
||
|
||
const OWNER = process.env.GITHUB_REPOSITORY
|
||
? process.env.GITHUB_REPOSITORY.split('/')[0]
|
||
: 'qinfendebingshuo';
|
||
const REPO = process.env.GITHUB_REPOSITORY
|
||
? process.env.GITHUB_REPOSITORY.split('/')[1]
|
||
: 'guanghulab';
|
||
|
||
/**
|
||
* 发送 GitHub API 请求
|
||
*/
|
||
function githubAPI(method, path, data) {
|
||
return new Promise((resolve, reject) => {
|
||
const body = data ? JSON.stringify(data) : null;
|
||
const req = https.request({
|
||
hostname: 'api.github.com',
|
||
path: path,
|
||
method: method,
|
||
headers: {
|
||
'Authorization': `Bearer ${process.env.GITHUB_TOKEN}`,
|
||
'Accept': 'application/vnd.github.v3+json',
|
||
'User-Agent': 'Zhuyuan-Pipeline-Reporter',
|
||
'Content-Type': 'application/json',
|
||
...(body ? { 'Content-Length': Buffer.byteLength(body) } : {})
|
||
}
|
||
}, (res) => {
|
||
let responseBody = '';
|
||
res.on('data', chunk => { responseBody += chunk; });
|
||
res.on('end', () => {
|
||
if (res.statusCode >= 200 && res.statusCode < 300) {
|
||
try { resolve(JSON.parse(responseBody)); }
|
||
catch (e) { console.error('⚠️ JSON parse error:', e.message); resolve(responseBody); }
|
||
} else {
|
||
reject(new Error(`GitHub API ${res.statusCode}: ${responseBody.slice(0, 200)}`));
|
||
}
|
||
});
|
||
});
|
||
req.on('error', reject);
|
||
if (body) req.write(body);
|
||
req.end();
|
||
});
|
||
}
|
||
|
||
/**
|
||
* 每完成一步,在 Issue 评论区发一条新评论
|
||
* @param {number} issueNumber - Issue 编号
|
||
* @param {number} stepNum - 步骤编号(1-8)
|
||
* @param {string} stepName - 步骤名称
|
||
* @param {'ok'|'error'|'skip'} status - 步骤状态
|
||
* @param {string} detail - 详情说明
|
||
*/
|
||
async function reportStep(issueNumber, stepNum, stepName, status, detail) {
|
||
const icon = status === 'ok' ? '✅' : status === 'error' ? '❌' : '⏭️';
|
||
const statusText = status === 'ok' ? '已完成' : status === 'error' ? '失败' : '跳过';
|
||
|
||
const body = [
|
||
`${icon} **步骤 ${stepNum}/8 · ${stepName}** · ${statusText}`,
|
||
'',
|
||
detail,
|
||
'',
|
||
`——铸渊(ICE-GL-ZY001)· ${new Date().toISOString()}`
|
||
].join('\n');
|
||
|
||
await githubAPI('POST', `/repos/${OWNER}/${REPO}/issues/${issueNumber}/comments`, { body });
|
||
}
|
||
|
||
/**
|
||
* 闭环完成时发最终汇总
|
||
* @param {number} issueNumber - Issue 编号
|
||
* @param {boolean} success - 是否全部成功
|
||
* @param {string} summary - 汇总内容
|
||
*/
|
||
async function reportComplete(issueNumber, success, summary) {
|
||
const icon = success ? '🎉' : '⚠️';
|
||
const title = success ? '闭环处理完成' : '闭环处理异常';
|
||
|
||
const body = [
|
||
`## ${icon} ${title}`,
|
||
'',
|
||
summary,
|
||
'',
|
||
success
|
||
? '> 新广播已生成,结果将发送到您的邮箱。'
|
||
: '> 部分步骤异常,已记录日志。冰朔会在下次巡检时处理。',
|
||
'',
|
||
`——铸渊(ICE-GL-ZY001)· ${new Date().toISOString()}`
|
||
].join('\n');
|
||
|
||
await githubAPI('POST', `/repos/${OWNER}/${REPO}/issues/${issueNumber}/comments`, { body });
|
||
}
|
||
|
||
// ━━━ CLI 模式:直接 node scripts/pipeline-reporter.js ━━━
|
||
if (require.main === module) {
|
||
const issueNumber = parseInt(process.env.ISSUE_NUMBER);
|
||
const stepNum = parseInt(process.env.STEP_NUM);
|
||
const stepName = process.env.STEP_NAME || '';
|
||
const status = process.env.STEP_STATUS || 'ok';
|
||
const detail = process.env.STEP_DETAIL || '';
|
||
const isComplete = process.env.REPORT_COMPLETE === 'true';
|
||
const isSuccess = process.env.REPORT_SUCCESS !== 'false';
|
||
|
||
if (!issueNumber) {
|
||
console.error('❌ 缺少 ISSUE_NUMBER');
|
||
process.exit(1);
|
||
}
|
||
|
||
(async () => {
|
||
try {
|
||
if (isComplete) {
|
||
await reportComplete(issueNumber, isSuccess, detail);
|
||
console.log(`📋 闭环汇总已发送 · Issue #${issueNumber}`);
|
||
} else {
|
||
await reportStep(issueNumber, stepNum, stepName, status, detail);
|
||
console.log(`📋 步骤 ${stepNum}/8 · ${stepName} · ${status} 已上报 · Issue #${issueNumber}`);
|
||
}
|
||
} catch (err) {
|
||
console.error(`⚠️ 进度上报失败: ${err.message}`);
|
||
// 上报失败不应阻断管道
|
||
process.exit(0);
|
||
}
|
||
})();
|
||
}
|
||
|
||
module.exports = { reportStep, reportComplete };
|