diff --git a/src/commands/buildgraph/run.ts b/src/commands/buildgraph/run.ts index 5cf310e..fe68874 100644 --- a/src/commands/buildgraph/run.ts +++ b/src/commands/buildgraph/run.ts @@ -11,7 +11,10 @@ interface AutomationToolLogs { level: string message: string format: string - properties: Record + properties: Record + id?: number + line?: number + lineCount?: number } async function getAutomationToolLogs(enginePath: string) { @@ -25,9 +28,73 @@ async function getAutomationToolLogs(enginePath: string) { return logs } +function generateMarkdownReport(logs: AutomationToolLogs[]): string { + const errorLogs = logs.filter(({ level }) => level === 'Error') + if (errorLogs.length === 0) { + return '# Build Report\n\nNo errors found.' + } + + let markdown = '# Build Error Report\n\n' + + // Group errors by id + const errorGroups = new Map() + + for (const log of errorLogs) { + const groupId = log.id !== undefined ? log.id : 'ungrouped' + if (!errorGroups.has(groupId)) { + errorGroups.set(groupId, []) + } + errorGroups.get(groupId)!.push(log) + } + + markdown += `## Errors (${errorLogs.length})\n\n` + + // Process each group of errors + for (const [groupId, groupLogs] of errorGroups) { + if (groupId !== 'ungrouped') { + markdown += `### Group ID: ${groupId} (${groupLogs.length} errors)\n\n` + } else { + markdown += `### Ungrouped Errors (${groupLogs.length} errors)\n\n` + } + + for (const log of groupLogs) { + markdown += `#### Error: ${log.message}\n` + + if (log.properties && log.properties.file) { + const file = log.properties.file.$text + const line = log.properties.line?.$text || log.line + markdown += `- **File**: ${file}${line ? `:${line}` : ''}\n` + } + + if (log.properties && log.properties.code) { + markdown += `- **Code**: ${log.properties.code.$text}\n` + } + + if (log.properties && log.properties.severity) { + markdown += `- **Severity**: ${log.properties.severity.$text}\n` + } + + markdown += '\n' + } + } + + return markdown +} + +async function writeMarkdownReport(logs: AutomationToolLogs[], outputPath: string): Promise { + const markdown = generateMarkdownReport(logs) + await Deno.writeTextFile(outputPath, markdown) + console.log(`[BUILDGRAPH RUN] Error report generated: ${outputPath}`) +} + export const run = new Command() .description('run buildgraph script') .arguments(' ') + .env( + 'RUNREAL_BUILDGRAPH_REPORT_ERRORS=', + 'Generate a markdown report with errors at the specified path', + { prefix: 'RUNREAL_' }, + ) .stopEarly() .action(async (options, buildGraphScript: string, ...buildGraphArgs: Array) => { const config = Config.getInstance() @@ -37,9 +104,14 @@ export const run = new Command() if (!success) { const logs = await getAutomationToolLogs(enginePath) - for (const message of logs.filter(({ level }) => level === 'Error')) { - console.log(`[BUILDGRAPH RUN] ${message}`) + for (const log of logs.filter(({ level }) => level === 'Error')) { + console.log(`[BUILDGRAPH RUN] ${log.message}`) } + + if (options.buildgraphReportErrors) { + await writeMarkdownReport(logs, options.buildgraphReportErrors) + } + Deno.exit(code) } })