* feat: add GitHub issue tracker workflow with Feishu notifications * fix: add missing environment variable for Claude translator in GitHub issue tracker workflow * fix: update environment variable for Claude translator in GitHub issue tracker workflow * Add quiet hours handling and scheduled processing for GitHub issue notifications - Implement quiet hours detection (00:00-08:30 Beijing Time) with delayed notifications - Add scheduled workflow to process pending issues daily at 08:30 Beijing Time - Create new script to batch process and summarize multiple pending issues with Claude * Replace custom Node.js script with Claude Code Action for issue processing - Migrate from custom JavaScript implementation to Claude Code Action for AI-powered issue summarization and processing - Simplify workflow by leveraging Claude's built-in GitHub API integration and tool usage capabilities - Maintain same functionality: fetch pending issues, generate Chinese summaries, send Feishu notifications, and clean up labels - Update Claude action reference from version pin to main branch for latest features * Remove GitHub issue comment functionality - Delete automated AI summary comments on issues after processing - Remove documentation for manual issue commenting workflow - Keep Feishu notification system intact while streamlining issue interactions * feat: add GitHub issue tracker workflow with Feishu notifications * feat: add GitHub issue tracker workflow with Feishu notifications * fix: add missing environment variable for Claude translator in GitHub issue tracker workflow * fix: update environment variable for Claude translator in GitHub issue tracker workflow * Add quiet hours handling and scheduled processing for GitHub issue notifications - Implement quiet hours detection (00:00-08:30 Beijing Time) with delayed notifications - Add scheduled workflow to process pending issues daily at 08:30 Beijing Time - Create new script to batch process and summarize multiple pending issues with Claude * Replace custom Node.js script with Claude Code Action for issue processing - Migrate from custom JavaScript implementation to Claude Code Action for AI-powered issue summarization and processing - Simplify workflow by leveraging Claude's built-in GitHub API integration and tool usage capabilities - Maintain same functionality: fetch pending issues, generate Chinese summaries, send Feishu notifications, and clean up labels - Update Claude action reference from version pin to main branch for latest features * Remove GitHub issue comment functionality - Delete automated AI summary comments on issues after processing - Remove documentation for manual issue commenting workflow - Keep Feishu notification system intact while streamlining issue interactions * Add OIDC token permissions and GitHub token to Claude workflow - Add `id-token: write` permission for OIDC authentication in both jobs - Pass `github_token` to Claude action for proper GitHub API access - Maintain existing issue write and contents read permissions fix: add GitHub issue tracker workflow with Feishu notifications * feat: add GitHub issue tracker workflow with Feishu notifications * fix: add missing environment variable for Claude translator in GitHub issue tracker workflow * fix: update environment variable for Claude translator in GitHub issue tracker workflow * Add quiet hours handling and scheduled processing for GitHub issue notifications - Implement quiet hours detection (00:00-08:30 Beijing Time) with delayed notifications - Add scheduled workflow to process pending issues daily at 08:30 Beijing Time - Create new script to batch process and summarize multiple pending issues with Claude * Replace custom Node.js script with Claude Code Action for issue processing - Migrate from custom JavaScript implementation to Claude Code Action for AI-powered issue summarization and processing - Simplify workflow by leveraging Claude's built-in GitHub API integration and tool usage capabilities - Maintain same functionality: fetch pending issues, generate Chinese summaries, send Feishu notifications, and clean up labels - Update Claude action reference from version pin to main branch for latest features * Remove GitHub issue comment functionality - Delete automated AI summary comments on issues after processing - Remove documentation for manual issue commenting workflow - Keep Feishu notification system intact while streamlining issue interactions * Add OIDC token permissions and GitHub token to Claude workflow - Add `id-token: write` permission for OIDC authentication in both jobs - Pass `github_token` to Claude action for proper GitHub API access - Maintain existing issue write and contents read permissions * Enhance GitHub issue automation workflow with Claude integration - Refactor Claude action to handle issue analysis, Feishu notification, and comment creation in single step - Add tool permissions for Bash commands and custom notification script execution - Update prompt with detailed task instructions including summary generation and automated actions - Remove separate notification step by integrating all operations into Claude action workflow * fix * 删除AI总结评论的添加步骤和注意事项
229 lines
5.4 KiB
JavaScript
229 lines
5.4 KiB
JavaScript
/**
|
|
* Feishu (Lark) Webhook Notification Script
|
|
* Sends GitHub issue summaries to Feishu with signature verification
|
|
*/
|
|
|
|
const crypto = require('crypto')
|
|
const https = require('https')
|
|
|
|
/**
|
|
* Generate Feishu webhook signature
|
|
* @param {string} secret - Feishu webhook secret
|
|
* @param {number} timestamp - Unix timestamp in seconds
|
|
* @returns {string} Base64 encoded signature
|
|
*/
|
|
function generateSignature(secret, timestamp) {
|
|
const stringToSign = `${timestamp}\n${secret}`
|
|
const hmac = crypto.createHmac('sha256', stringToSign)
|
|
return hmac.digest('base64')
|
|
}
|
|
|
|
/**
|
|
* Send message to Feishu webhook
|
|
* @param {string} webhookUrl - Feishu webhook URL
|
|
* @param {string} secret - Feishu webhook secret
|
|
* @param {object} content - Message content
|
|
* @returns {Promise<void>}
|
|
*/
|
|
function sendToFeishu(webhookUrl, secret, content) {
|
|
return new Promise((resolve, reject) => {
|
|
const timestamp = Math.floor(Date.now() / 1000)
|
|
const sign = generateSignature(secret, timestamp)
|
|
|
|
const payload = JSON.stringify({
|
|
timestamp: timestamp.toString(),
|
|
sign: sign,
|
|
msg_type: 'interactive',
|
|
card: content
|
|
})
|
|
|
|
const url = new URL(webhookUrl)
|
|
const options = {
|
|
hostname: url.hostname,
|
|
path: url.pathname + url.search,
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'Content-Length': Buffer.byteLength(payload)
|
|
}
|
|
}
|
|
|
|
const req = https.request(options, (res) => {
|
|
let data = ''
|
|
res.on('data', (chunk) => {
|
|
data += chunk
|
|
})
|
|
res.on('end', () => {
|
|
if (res.statusCode >= 200 && res.statusCode < 300) {
|
|
console.log('✅ Successfully sent to Feishu:', data)
|
|
resolve()
|
|
} else {
|
|
reject(new Error(`Feishu API error: ${res.statusCode} - ${data}`))
|
|
}
|
|
})
|
|
})
|
|
|
|
req.on('error', (error) => {
|
|
reject(error)
|
|
})
|
|
|
|
req.write(payload)
|
|
req.end()
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Create Feishu card message from issue data
|
|
* @param {object} issueData - GitHub issue data
|
|
* @returns {object} Feishu card content
|
|
*/
|
|
function createIssueCard(issueData) {
|
|
const { issueUrl, issueNumber, issueTitle, issueSummary, issueAuthor, labels } = issueData
|
|
|
|
// Build labels section if labels exist
|
|
const labelElements =
|
|
labels && labels.length > 0
|
|
? labels.map((label) => ({
|
|
tag: 'markdown',
|
|
content: `\`${label}\``
|
|
}))
|
|
: []
|
|
|
|
return {
|
|
elements: [
|
|
{
|
|
tag: 'div',
|
|
text: {
|
|
tag: 'lark_md',
|
|
content: `**🐛 New GitHub Issue #${issueNumber}**`
|
|
}
|
|
},
|
|
{
|
|
tag: 'hr'
|
|
},
|
|
{
|
|
tag: 'div',
|
|
text: {
|
|
tag: 'lark_md',
|
|
content: `**📝 Title:** ${issueTitle}`
|
|
}
|
|
},
|
|
{
|
|
tag: 'div',
|
|
text: {
|
|
tag: 'lark_md',
|
|
content: `**👤 Author:** ${issueAuthor}`
|
|
}
|
|
},
|
|
...(labelElements.length > 0
|
|
? [
|
|
{
|
|
tag: 'div',
|
|
text: {
|
|
tag: 'lark_md',
|
|
content: `**🏷️ Labels:** ${labels.join(', ')}`
|
|
}
|
|
}
|
|
]
|
|
: []),
|
|
{
|
|
tag: 'hr'
|
|
},
|
|
{
|
|
tag: 'div',
|
|
text: {
|
|
tag: 'lark_md',
|
|
content: `**📋 Summary:**\n${issueSummary}`
|
|
}
|
|
},
|
|
{
|
|
tag: 'hr'
|
|
},
|
|
{
|
|
tag: 'action',
|
|
actions: [
|
|
{
|
|
tag: 'button',
|
|
text: {
|
|
tag: 'plain_text',
|
|
content: '🔗 View Issue'
|
|
},
|
|
type: 'primary',
|
|
url: issueUrl
|
|
}
|
|
]
|
|
}
|
|
],
|
|
header: {
|
|
template: 'blue',
|
|
title: {
|
|
tag: 'plain_text',
|
|
content: '🆕 Cherry Studio - New Issue'
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Main function
|
|
*/
|
|
async function main() {
|
|
try {
|
|
// Get environment variables
|
|
const webhookUrl = process.env.FEISHU_WEBHOOK_URL
|
|
const secret = process.env.FEISHU_WEBHOOK_SECRET
|
|
const issueUrl = process.env.ISSUE_URL
|
|
const issueNumber = process.env.ISSUE_NUMBER
|
|
const issueTitle = process.env.ISSUE_TITLE
|
|
const issueSummary = process.env.ISSUE_SUMMARY
|
|
const issueAuthor = process.env.ISSUE_AUTHOR
|
|
const labelsStr = process.env.ISSUE_LABELS || ''
|
|
|
|
// Validate required environment variables
|
|
if (!webhookUrl) {
|
|
throw new Error('FEISHU_WEBHOOK_URL environment variable is required')
|
|
}
|
|
if (!secret) {
|
|
throw new Error('FEISHU_WEBHOOK_SECRET environment variable is required')
|
|
}
|
|
if (!issueUrl || !issueNumber || !issueTitle || !issueSummary) {
|
|
throw new Error('Issue data environment variables are required')
|
|
}
|
|
|
|
// Parse labels
|
|
const labels = labelsStr
|
|
? labelsStr
|
|
.split(',')
|
|
.map((l) => l.trim())
|
|
.filter(Boolean)
|
|
: []
|
|
|
|
// Create issue data object
|
|
const issueData = {
|
|
issueUrl,
|
|
issueNumber,
|
|
issueTitle,
|
|
issueSummary,
|
|
issueAuthor: issueAuthor || 'Unknown',
|
|
labels
|
|
}
|
|
|
|
// Create card content
|
|
const card = createIssueCard(issueData)
|
|
|
|
console.log('📤 Sending notification to Feishu...')
|
|
console.log(`Issue #${issueNumber}: ${issueTitle}`)
|
|
|
|
// Send to Feishu
|
|
await sendToFeishu(webhookUrl, secret, card)
|
|
|
|
console.log('✅ Notification sent successfully!')
|
|
} catch (error) {
|
|
console.error('❌ Error:', error.message)
|
|
process.exit(1)
|
|
}
|
|
}
|
|
|
|
// Run main function
|
|
main()
|