import { Octokit } from 'octokit'; import { ComplianceReport, Violation } from '../types'; export class GitHubNotifier { private octokit: Octokit; constructor( private token: string, private repo: string, private labels: string[] ) { this.octokit = new Octokit({ auth: token }); } async createIssues(report: ComplianceReport): Promise { const [owner, repoName] = this.repo.split('/'); // Group violations by type and severity const criticalViolations = report.violations.filter(v => v.severity === 'critical'); if (criticalViolations.length > 0) { await this.createIssue(owner, repoName, report, criticalViolations); } } private async createIssue( owner: string, repo: string, report: ComplianceReport, violations: Violation[] ): Promise { const title = `[Design Compliance] ${violations.length} violations in ${report.fileName}`; let body = `## 🚨 Design Compliance Violations\n\n`; body += `**File:** ${report.fileName}\n`; body += `**Date:** ${new Date(report.timestamp).toLocaleString()}\n`; body += `**Total Violations:** ${violations.length}\n\n`; body += `### Violations\n\n`; for (const v of violations) { body += `#### ${this.getSeverityEmoji(v.severity)} ${v.type.toUpperCase()}\n\n`; body += `**Message:** ${v.message}\n`; body += `**Node:** ${v.node.name} (${v.node.type})\n`; if (v.frame) body += `**Frame:** ${v.frame}\n`; if (v.page) body += `**Page:** ${v.page}\n`; if (v.expected) body += `**Expected:** \`${JSON.stringify(v.expected)}\`\n`; if (v.actual !== undefined) body += `**Actual:** \`${JSON.stringify(v.actual)}\`\n`; body += `\n`; } body += `\n---\n`; body += `_This issue was automatically created by Design Compliance Bot_`; try { await this.octokit.rest.issues.create({ owner, repo, title, body, labels: this.labels, }); } catch (error) { console.error('Failed to create GitHub issue:', error); } } private getSeverityEmoji(severity: string): string { switch (severity) { case 'critical': return '🔴'; case 'warning': return '🟡'; case 'info': return '🔵'; default: return '⚪'; } } }