refactor: extract shared feishu alert script + fix error messages + code review fixes

Co-authored-by: qinfendebingshuo <207279273+qinfendebingshuo@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot] 2026-03-11 17:25:53 +00:00
parent d0cc67953b
commit 9fb8197042
6 changed files with 98 additions and 108 deletions

View File

@ -52,32 +52,7 @@ jobs:
FEISHU_APP_ID: ${{ secrets.FEISHU_APP_ID }} FEISHU_APP_ID: ${{ secrets.FEISHU_APP_ID }}
FEISHU_APP_SECRET: ${{ secrets.FEISHU_APP_SECRET }} FEISHU_APP_SECRET: ${{ secrets.FEISHU_APP_SECRET }}
ALERT_CHAT_ID: ${{ secrets.FEISHU_ALERT_CHAT_ID }} ALERT_CHAT_ID: ${{ secrets.FEISHU_ALERT_CHAT_ID }}
run: | run: node scripts/send-feishu-alert.js "push-broadcast" "📡 新广播已推送到飞书文档B请查看飞书广播收件箱。" || true
if [ -z "$ALERT_CHAT_ID" ]; then
echo "⚠️ 未配置 FEISHU_ALERT_CHAT_ID跳过群通知"
exit 0
fi
node -e "
const https = require('https');
function post(url, body) {
return new Promise((resolve, reject) => {
const payload = JSON.stringify(body);
const u = new URL(url);
const req = https.request({ hostname: u.hostname, port: 443, path: u.pathname, method: 'POST',
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) }
}, res => { let d=''; res.on('data', c => d+=c); res.on('end', () => resolve(d)); });
req.on('error', reject); req.write(payload); req.end();
});
}
(async () => {
const tokenRes = JSON.parse(await post('https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal',
{ app_id: process.env.FEISHU_APP_ID, app_secret: process.env.FEISHU_APP_SECRET }));
const token = tokenRes.tenant_access_token;
const payload = JSON.stringify({ text: '📡 新广播已推送到飞书文档B\n\n时间: ' + new Date().toISOString() + '\n请查看飞书广播收件箱。' });
await post('https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id',
JSON.stringify({ receive_id: process.env.ALERT_CHAT_ID, msg_type: 'text', content: payload }));
})().catch(e => console.error(e.message));
"
- name: 🔴 失败告警 → 飞书通知 - name: 🔴 失败告警 → 飞书通知
if: failure() if: failure()
@ -85,29 +60,4 @@ jobs:
FEISHU_APP_ID: ${{ secrets.FEISHU_APP_ID }} FEISHU_APP_ID: ${{ secrets.FEISHU_APP_ID }}
FEISHU_APP_SECRET: ${{ secrets.FEISHU_APP_SECRET }} FEISHU_APP_SECRET: ${{ secrets.FEISHU_APP_SECRET }}
ALERT_CHAT_ID: ${{ secrets.FEISHU_ALERT_CHAT_ID }} ALERT_CHAT_ID: ${{ secrets.FEISHU_ALERT_CHAT_ID }}
run: | run: node scripts/send-feishu-alert.js "push-broadcast"
if [ -z "$ALERT_CHAT_ID" ]; then
echo "⚠️ 未配置 FEISHU_ALERT_CHAT_ID跳过告警"
exit 0
fi
node -e "
const https = require('https');
function post(url, body) {
return new Promise((resolve, reject) => {
const payload = JSON.stringify(body);
const u = new URL(url);
const req = https.request({ hostname: u.hostname, port: 443, path: u.pathname, method: 'POST',
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) }
}, res => { let d=''; res.on('data', c => d+=c); res.on('end', () => resolve(d)); });
req.on('error', reject); req.write(payload); req.end();
});
}
(async () => {
const tokenRes = JSON.parse(await post('https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal',
{ app_id: process.env.FEISHU_APP_ID, app_secret: process.env.FEISHU_APP_SECRET }));
const token = tokenRes.tenant_access_token;
const payload = JSON.stringify({ text: '🔴 GitHub Action 失败告警\n\n工作流: push-broadcast\n时间: ' + new Date().toISOString() + '\n请检查 GitHub Actions 日志。' });
await post('https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id',
JSON.stringify({ receive_id: process.env.ALERT_CHAT_ID, msg_type: 'text', content: payload }));
})().catch(e => console.error(e.message));
"

View File

@ -58,29 +58,4 @@ jobs:
FEISHU_APP_ID: ${{ secrets.FEISHU_APP_ID }} FEISHU_APP_ID: ${{ secrets.FEISHU_APP_ID }}
FEISHU_APP_SECRET: ${{ secrets.FEISHU_APP_SECRET }} FEISHU_APP_SECRET: ${{ secrets.FEISHU_APP_SECRET }}
ALERT_CHAT_ID: ${{ secrets.FEISHU_ALERT_CHAT_ID }} ALERT_CHAT_ID: ${{ secrets.FEISHU_ALERT_CHAT_ID }}
run: | run: node scripts/send-feishu-alert.js "receive-syslog"
if [ -z "$ALERT_CHAT_ID" ]; then
echo "⚠️ 未配置 FEISHU_ALERT_CHAT_ID跳过告警"
exit 0
fi
node -e "
const https = require('https');
function post(url, body) {
return new Promise((resolve, reject) => {
const payload = JSON.stringify(body);
const u = new URL(url);
const req = https.request({ hostname: u.hostname, port: 443, path: u.pathname, method: 'POST',
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) }
}, res => { let d=''; res.on('data', c => d+=c); res.on('end', () => resolve(d)); });
req.on('error', reject); req.write(payload); req.end();
});
}
(async () => {
const tokenRes = JSON.parse(await post('https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal',
{ app_id: process.env.FEISHU_APP_ID, app_secret: process.env.FEISHU_APP_SECRET }));
const token = tokenRes.tenant_access_token;
const payload = JSON.stringify({ text: '🔴 GitHub Action 失败告警\n\n工作流: receive-syslog\n时间: ' + new Date().toISOString() + '\n请检查 GitHub Actions 日志。' });
await post('https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id',
JSON.stringify({ receive_id: process.env.ALERT_CHAT_ID, msg_type: 'text', content: payload }));
})().catch(e => console.error(e.message));
"

View File

@ -46,29 +46,4 @@ jobs:
FEISHU_APP_ID: ${{ secrets.FEISHU_APP_ID }} FEISHU_APP_ID: ${{ secrets.FEISHU_APP_ID }}
FEISHU_APP_SECRET: ${{ secrets.FEISHU_APP_SECRET }} FEISHU_APP_SECRET: ${{ secrets.FEISHU_APP_SECRET }}
ALERT_CHAT_ID: ${{ secrets.FEISHU_ALERT_CHAT_ID }} ALERT_CHAT_ID: ${{ secrets.FEISHU_ALERT_CHAT_ID }}
run: | run: node scripts/send-feishu-alert.js "sync-login-entry"
if [ -z "$ALERT_CHAT_ID" ]; then
echo "⚠️ 未配置 FEISHU_ALERT_CHAT_ID跳过告警"
exit 0
fi
node -e "
const https = require('https');
function post(url, body) {
return new Promise((resolve, reject) => {
const payload = JSON.stringify(body);
const u = new URL(url);
const req = https.request({ hostname: u.hostname, port: 443, path: u.pathname, method: 'POST',
headers: { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) }
}, res => { let d=''; res.on('data', c => d+=c); res.on('end', () => resolve(d)); });
req.on('error', reject); req.write(payload); req.end();
});
}
(async () => {
const tokenRes = JSON.parse(await post('https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal',
{ app_id: process.env.FEISHU_APP_ID, app_secret: process.env.FEISHU_APP_SECRET }));
const token = tokenRes.tenant_access_token;
const payload = JSON.stringify({ text: '🔴 GitHub Action 失败告警\n\n工作流: sync-login-entry\n时间: ' + new Date().toISOString() + '\n请检查 GitHub Actions 日志。' });
await post('https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id',
JSON.stringify({ receive_id: process.env.ALERT_CHAT_ID, msg_type: 'text', content: payload }));
})().catch(e => console.error(e.message));
"

View File

@ -133,7 +133,7 @@ async function callModel(messages, options = {}) {
const model = options.model || process.env.MODEL_NAME || DEFAULT_MODEL; const model = options.model || process.env.MODEL_NAME || DEFAULT_MODEL;
if (!apiKey) { if (!apiKey) {
return '⚠️ AI 模型未配置(缺少 MODEL_API_KEY,请联系管理员。'; return '⚠️ AI 服务暂时不可用,请联系管理员。';
} }
const url = new URL(apiBase + '/chat/completions'); const url = new URL(apiBase + '/chat/completions');
@ -163,10 +163,10 @@ async function callModel(messages, options = {}) {
// 尝试降级模型 // 尝试降级模型
if (result.statusCode === 429 || result.statusCode >= 500) { if (result.statusCode === 429 || result.statusCode >= 500) {
return '⚠️ AI 模型暂时不可用HTTP ' + result.statusCode + ',请稍后重试。'; return '⚠️ AI 模型暂时不可用,请稍后重试。';
} }
return '⚠️ AI 模型调用异常: ' + (result.data.error?.message || JSON.stringify(result.data)); return '⚠️ AI 模型调用异常,请稍后重试或联系管理员。';
} catch (e) { } catch (e) {
return '⚠️ AI 模型调用失败: ' + e.message; return '⚠️ AI 模型调用失败: ' + e.message;
} }

View File

@ -107,7 +107,9 @@ function main() {
d.total_interactions++; d.total_interactions++;
if (r.type === 'syslog_collaboration') d.syslog_count++; if (r.type === 'syslog_collaboration') d.syslog_count++;
if (r.type === 'collaboration') d.chat_count++; if (r.type === 'collaboration') d.chat_count++;
d.last_active_at = r.timestamp; if (!d.last_active_at || r.timestamp > d.last_active_at) {
d.last_active_at = r.timestamp;
}
if (r.channel) d.channels_used.add(r.channel); if (r.channel) d.channels_used.add(r.channel);
if (r.broadcast_id && r.broadcast_id !== 'UNKNOWN') d.broadcasts_referenced.add(r.broadcast_id); if (r.broadcast_id && r.broadcast_id !== 'UNKNOWN') d.broadcasts_referenced.add(r.broadcast_id);
} }

View File

@ -0,0 +1,88 @@
// scripts/send-feishu-alert.js
// 铸渊 · 飞书告警通知脚本(供 GitHub Actions 工作流调用)
//
// 用法: node scripts/send-feishu-alert.js "工作流名称" "告警内容"
//
// 环境变量:
// FEISHU_APP_ID 飞书应用 App ID
// FEISHU_APP_SECRET 飞书应用 App Secret
// ALERT_CHAT_ID 飞书群 chat_id
'use strict';
const https = require('https');
function httpsPost(url, body) {
return new Promise((resolve, reject) => {
const payload = JSON.stringify(body);
const u = new URL(url);
const req = https.request({
hostname: u.hostname,
port: 443,
path: u.pathname + u.search,
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(payload),
},
}, res => {
let d = '';
res.on('data', c => d += c);
res.on('end', () => resolve(d));
});
req.on('error', reject);
req.write(payload);
req.end();
});
}
async function main() {
const appId = process.env.FEISHU_APP_ID;
const appSecret = process.env.FEISHU_APP_SECRET;
const chatId = process.env.ALERT_CHAT_ID;
const workflow = process.argv[2] || 'unknown';
const detail = process.argv[3] || '';
if (!chatId) {
console.log('⚠️ 未配置 ALERT_CHAT_ID跳过告警');
process.exit(0);
}
if (!appId || !appSecret) {
console.log('⚠️ 未配置飞书 App 凭据,跳过告警');
process.exit(0);
}
// 获取飞书 token
const tokenRes = JSON.parse(await httpsPost(
'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal',
{ app_id: appId, app_secret: appSecret }
));
const token = tokenRes.tenant_access_token;
if (!token) {
console.error('❌ 获取飞书 token 失败');
process.exit(1);
}
// 发送消息
const text = '🔴 GitHub Action 失败告警\n\n' +
'工作流: ' + workflow + '\n' +
'时间: ' + new Date().toISOString() + '\n' +
(detail ? '详情: ' + detail + '\n' : '') +
'请检查 GitHub Actions 日志。';
await httpsPost(
'https://open.feishu.cn/open-apis/im/v1/messages?receive_id_type=chat_id',
{
receive_id: chatId,
msg_type: 'text',
content: JSON.stringify({ text }),
}
);
console.log('✅ 告警已发送到飞书群');
}
main().catch(e => {
console.error('❌ 告警发送失败:', e.message);
process.exit(1);
});