From 87f5257f8b24369e49ee4d8a9837dc02aa46ad74 Mon Sep 17 00:00:00 2001 From: Mara Nikola Kiefer Date: Thu, 12 Feb 2026 15:23:13 +0100 Subject: [PATCH] chore: enhance bot report summary --- .github/workflows/bot-detection.yml | 53 ++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/.github/workflows/bot-detection.yml b/.github/workflows/bot-detection.yml index e4a35e14b95..9b68ddaad22 100644 --- a/.github/workflows/bot-detection.yml +++ b/.github/workflows/bot-detection.yml @@ -60,10 +60,27 @@ jobs: const highRiskAccounts = new Map(); const commentsByUser = new Map(); const userCreatedDates = new Map(); + const accountsSeen = new Set(); + let userLookupFailures = 0; + + async function ensureUserCreatedDate(login) { + if (!login) return; + accountsSeen.add(login); + if (userCreatedDates.has(login)) return; + try { + const { data: userInfo } = await github.rest.users.getByUsername({ username: login }); + userCreatedDates.set(login, new Date(userInfo.created_at)); + } catch (e) { + userLookupFailures += 1; + userCreatedDates.set(login, null); + } + } for (const pr of prs.slice(0, MAX_PR)) { if (new Date(pr.updated_at) < cutoff) continue; + await ensureUserCreatedDate(pr.user?.login); + const issueComments = []; if (github.paginate?.iterator) { for await (const response of github.paginate.iterator(github.rest.issues.listComments, { @@ -109,14 +126,7 @@ jobs: const login = comment.user?.login; if (!login) continue; - if (!userCreatedDates.has(login)) { - try { - const { data: userInfo } = await github.rest.users.getByUsername({ username: login }); - userCreatedDates.set(login, new Date(userInfo.created_at)); - } catch (e) { - userCreatedDates.set(login, null); - } - } + await ensureUserCreatedDate(login); if (!commentsByUser.has(login)) { commentsByUser.set(login, []); @@ -129,6 +139,24 @@ jobs: } } + // Also consider recent issue creators (not just PR comments). + // This helps catch new accounts that only opened issues/PRs (even if already closed). + try { + const { data: recentIssues } = await github.rest.issues.listForRepo({ + owner: context.repo.owner, + repo: context.repo.repo, + state: 'all', + since: cutoff.toISOString(), + per_page: 100, + }); + + for (const issue of recentIssues) { + await ensureUserCreatedDate(issue.user?.login); + } + } catch (e) { + // If issue listing fails, continue with PR/comment-based detection. + } + // Identify high-risk accounts const now = new Date(); for (const [login, createdDate] of userCreatedDates) { @@ -146,7 +174,14 @@ jobs: } if (highRiskAccounts.size === 0) { - appendSummary(`✅ Bot Detection: no new accounts (<${MIN_ACCOUNT_AGE_DAYS}d) found in last ${HOURS_BACK}h.`); + let msg = `✅ Bot Detection: no high-risk accounts (<${MIN_ACCOUNT_AGE_DAYS}d) detected in last ${HOURS_BACK}h.`; + if (accountsSeen.size > 0) { + msg += ` Checked ${accountsSeen.size} unique account(s).`; + } + if (userLookupFailures > 0) { + msg += ` ⚠️ ${userLookupFailures} account lookup(s) failed.`; + } + appendSummary(msg); return; }