From 0347d58f712d111cc8be1bb7dbf3ffd80c19775f Mon Sep 17 00:00:00 2001 From: Gabriel Brown Date: Sat, 11 Jul 2026 15:37:51 -0400 Subject: [PATCH] chore: fix eslint errors introduced in phase 4 backend --- .../backend/convex/githubWebhookVerify.ts | 2 +- packages/backend/convex/maintenanceDedup.ts | 3 ++ .../backend/tests/unit/github-head.test.ts | 38 +++++++++---------- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/packages/backend/convex/githubWebhookVerify.ts b/packages/backend/convex/githubWebhookVerify.ts index 175ffac..02c9150 100644 --- a/packages/backend/convex/githubWebhookVerify.ts +++ b/packages/backend/convex/githubWebhookVerify.ts @@ -17,7 +17,7 @@ export const verifyGithubSignature = async ( rawBody: string, signatureHeader: string | null, ): Promise => { - if (!signatureHeader || !signatureHeader.startsWith('sha256=')) return false; + if (!signatureHeader?.startsWith('sha256=')) return false; // Web Crypto's importKey throws on a zero-length HMAC key; guard so the // verifier never throws on attacker-controlled input (returns false instead). if (!secret) return false; diff --git a/packages/backend/convex/maintenanceDedup.ts b/packages/backend/convex/maintenanceDedup.ts index e8ba281..c9c7922 100644 --- a/packages/backend/convex/maintenanceDedup.ts +++ b/packages/backend/convex/maintenanceDedup.ts @@ -16,6 +16,9 @@ export const maintenanceDedupKey = (input: { }): string | null => { const head = input.headSha?.trim(); if (!head) return null; + // Intentional `||`: an empty/whitespace merge base must collapse to the + // 'nobase' sentinel, which `??` would not do (it keeps the empty string). + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing const base = input.mergeBaseSha?.trim() || 'nobase'; return `${base}:${head}`; }; diff --git a/packages/backend/tests/unit/github-head.test.ts b/packages/backend/tests/unit/github-head.test.ts index 4f7b8c4..4cff1c4 100644 --- a/packages/backend/tests/unit/github-head.test.ts +++ b/packages/backend/tests/unit/github-head.test.ts @@ -8,9 +8,9 @@ import { describe('resolveBranchHead', () => { it('returns the branch tip sha from the branch ref', async () => { - const getBranch = vi.fn(async () => ({ - data: { commit: { sha: 'deadbeef' } }, - })); + const getBranch = vi.fn(() => + Promise.resolve({ data: { commit: { sha: 'deadbeef' } } }), + ); const octokit = { rest: { repos: { getBranch } }, } as unknown as Octokit; @@ -45,24 +45,22 @@ describe('compareAcrossForkNetwork', () => { makeCommit(i === 49 ? 'LAST_COMMIT_NOT_TIP' : `c${100 + i}`), ); - const compareCommitsWithBasehead = vi.fn( - async ({ page }: { page?: number }) => { - const commits = page === 2 ? page2 : page1; - return { - data: { - total_commits: 150, - ahead_by: 150, - merge_base_commit: { sha: 'MERGE_BASE' }, - base_commit: { sha: 'BASE' }, - html_url: 'https://github.com/o/r/compare/base...head', - commits, - }, - }; - }, + const compareCommitsWithBasehead = vi.fn(({ page }: { page?: number }) => { + const commits = page === 2 ? page2 : page1; + return Promise.resolve({ + data: { + total_commits: 150, + ahead_by: 150, + merge_base_commit: { sha: 'MERGE_BASE' }, + base_commit: { sha: 'BASE' }, + html_url: 'https://github.com/o/r/compare/base...head', + commits, + }, + }); + }); + const getBranch = vi.fn(() => + Promise.resolve({ data: { commit: { sha: 'TIP' } } }), ); - const getBranch = vi.fn(async () => ({ - data: { commit: { sha: 'TIP' } }, - })); const octokit = { rest: { repos: { compareCommitsWithBasehead, getBranch } }, } as unknown as Octokit;