From c6eeec7b3d0c6e24493ba31ba57fe3153537aba4 Mon Sep 17 00:00:00 2001 From: Mathieu Colmon Date: Fri, 21 Jul 2023 19:34:57 +0200 Subject: [PATCH] Big fixes (2) --- src/telegram/agent.ts | 110 +++++++++++++++++++++------------ src/vitest/agent.ts | 72 +++++++-------------- tests/sameStackExample.test.ts | 5 +- 3 files changed, 95 insertions(+), 92 deletions(-) diff --git a/src/telegram/agent.ts b/src/telegram/agent.ts index e98bdb1..95d6944 100644 --- a/src/telegram/agent.ts +++ b/src/telegram/agent.ts @@ -27,6 +27,26 @@ const statusEmojis: { UNKNOWN: '❓', }; +function sendTelegramMessage(text: string) { + console.log(`Sending message to Telegram (size: ${text.length})...`); + + const url = new URL(`https://api.telegram.org/bot${config.key}/sendMessage`); + url.searchParams.set('chat_id', config.chat); + url.searchParams.set('parse_mode', 'markdown'); + url.searchParams.set('text', text); + + return new Promise((cb) => https.get(url, (res) => { + if (res.statusCode !== 200) { + console.error(`Cannot send message to Telegram: ${res.statusCode} (${res.statusMessage})`); + console.error(url); + console.error(text); + process.exit(1); + } + + cb(true); + })); +} + interface TelegramReportOptions { stacks: Stack[]; changes?: Changes; @@ -45,35 +65,39 @@ export async function sendTelegramReport( const report = (stacks .filter((stack) => !changes || changes[stack.id]) - .map((stack) => [ - `${getNewEmoji(stack)}${statusEmojis.FAIL} *[FAIL]* ${pathFormat(stack.path)}`, - '', - `*${stack.error.name}*: \`${stack.error.message}\``, - ` ❯ \`${stack.file.name}:${stack.line}:${stack.column}\``, - '', - (stack.line - ? `${generateCodeSnippet({ - filepath: stack.file.path, - line: stack.line, - column: stack.column, - markdownMode: true, - })}\n` - : null - ), - stack.error.diff?.replace(/\x1B\[\d+m/g, '') ?? null, - '', - (reportUrl - ? `Voir le détail: [report/#file=${stack.file.id}](${reportUrl}/#file=${stack.file.id})` - : null - ), - (notionUrls[stack.id] - ? `Voir l'erreur sur Notion: [notion/${notionUrls[stack.id].id}](${notionUrls[stack.id].url})` - : null - ), - '\n', - ]) - .filter((stack) => stack !== null) - .flat() + .map((stack) => ( + [ + `${getNewEmoji(stack)}${statusEmojis.FAIL} *[FAIL]* ${pathFormat(stack.path)}`, + '', + `*${stack.error.name}*: \`${stack.error.message}\``, + ` ❯ \`${stack.file.name}:${stack.line}:${stack.column}\``, + '', + (stack.line + ? `${generateCodeSnippet({ + filepath: stack.file.path, + line: stack.line, + column: stack.column, + markdownMode: true, + })}\n` + : null + ), + + stack.error.diff?.replace(/\x1B\[\d+m/g, ''), + + (reportUrl + ? `Voir le détail: [report/#file=${stack.file.id}](${reportUrl}/#file=${stack.file.id})` + : null + ), + (notionUrls[stack.id] + ? `Voir l'erreur sur Notion: [notion/${notionUrls[stack.id].id}](${notionUrls[stack.id].url})` + : null + ), + '', + ] + .filter((line) => line !== null) + .flat() + .join('\n') + )) ); for (const change of Object.values(changes ?? {})) { @@ -95,20 +119,26 @@ export async function sendTelegramReport( report.unshift(`======= *${config.namespace}* =======`, ''); - const url = new URL(`https://api.telegram.org/bot${config.key}/sendMessage`); - url.searchParams.set('chat_id', config.chat as string); - url.searchParams.set('parse_mode', 'markdown'); - url.searchParams.set('text', report.join('\n')); + // split in chunks of 4096 chars + const chunks = []; - return new Promise((cb) => https.get(url, (res) => { - if (res.statusCode !== 200) { - console.error(`Cannot send message to Telegram: ${res.statusCode} (${res.statusMessage})`); - console.error(url); - process.exit(1); + let chunk = ''; + for (const line of report) { + if (line === null) continue; + if (line.length >= 4096) { + console.error('Line is too long to be sent to Telegram. Skipping...'); + continue; } + if (chunk.length + line.length >= 4096) { + chunks.push(chunk); + chunk = ''; + } + chunk += `${line}\n`; + } - cb(true); - })); + if (chunk.length > 0) chunks.push(chunk); + + for (const chunk of chunks) await sendTelegramMessage(chunk); } export default available; diff --git a/src/vitest/agent.ts b/src/vitest/agent.ts index d80ba15..3d576dc 100644 --- a/src/vitest/agent.ts +++ b/src/vitest/agent.ts @@ -52,29 +52,6 @@ export interface Stack { }; } -function findEquivalentStack(obj: any) { - const isStackObject = (testObj: any) => { - const keys = Object.keys(testObj); - return ['column', 'line', 'file'].every((key) => keys.includes(key)); - }; - - const seenPaths = new Set(); - - const recurse = (obj: any): any => { - if (isStackObject(obj)) return obj; - - for (const v of Object.values(obj)) { - if (typeof v !== 'object') continue; - if (seenPaths.has(v)) continue; - seenPaths.add(v); - const result = recurse(v); - if (result) return result; - } - } - - return recurse(obj); -} - let stackWaitI = 0; export async function getStacks(files: File[]): Promise { @@ -119,39 +96,32 @@ export async function getStacks(files: File[]): Promise { const max = 5; while ((!error.stacks || !error.stacks.length) && stackWaitI <= max) { - if (stackWaitI >= max) { - console.log('No stacks available for task:\n ', errorInfo.path.join(' > ')); - - console.log(' Finding equivalent stack...'); - const equivalentStack = findEquivalentStack(task); - - if (!equivalentStack) { - console.warn(' No equivalent stack found.'); - stacks.push(errorInfo); - break; - } - - console.log( - ' Equivalent stack found:', - `${equivalentStack.file}:${equivalentStack.line}:${equivalentStack.column}`, - ); - - stacks.push({ - ...errorInfo, - line: equivalentStack.line, - column: equivalentStack.column, - }); - - break; - } - console.log(`Waiting for stacks to be available, ${stackWaitI}/${max}...`); stackWaitI += 1; + await new Promise((resolve) => setTimeout(resolve, 400)); + } - await new Promise((resolve) => setTimeout(resolve, 500)); + const errorStacks = error.stacks ?? []; + + if (!errorStacks.length) { + const stkStr = error.stack ?? error.stackStr; + const startIndex = stkStr.indexOf(errorInfo.file.name); + const endIndex = stkStr.indexOf('\n', startIndex); + const [line, column] = (stkStr + .slice(startIndex, endIndex) + .match(/:(\d+):(\d+)$/)?.slice(1) + ?? [0, 0] + ); + + errorStacks.push({ + line: Number(line), + column: Number(column), + file: errorInfo.file.name, + method: '', + }); } - for (const stack of error.stacks ?? []) { + for (const stack of errorStacks) { stacks.push({ ...errorInfo, line: stack.line, diff --git a/tests/sameStackExample.test.ts b/tests/sameStackExample.test.ts index 3ef1ab3..255673f 100644 --- a/tests/sameStackExample.test.ts +++ b/tests/sameStackExample.test.ts @@ -2,8 +2,11 @@ import { describe, it, expect } from 'vitest'; for (let i = 0; i < 8; i += 1) { describe(`Test nº${i}`, () => { + it('should always fail', () => { + expect([]).toHaveLength(1); + }); it('should randomly fail', () => { expect([]).toHaveLength(Math.round(Math.random())); - }) + }); }); }