Context
dismissLatestBotApproval in src/github/pr-actions.ts:130-161 finds the bot's own most recent APPROVE
review so it can be dismissed. It matches the bot's login with a case-sensitive ===:
const botLogin = `${env.GITHUB_APP_SLUG}[bot]`;
...
for (const review of batch) {
if (review.user?.login === botLogin && review.state === "APPROVED") latestApprovalId = review.id;
}
(src/github/pr-actions.ts:135 and :143.)
Every other bot-login comparison in this same subsystem normalizes case before comparing:
isLoopOverBotComment in src/github/comments.ts:104-106:
function isLoopOverBotComment(comment: IssueComment, botLogin: string): boolean {
return comment.user?.type === "Bot" && comment.user.login?.toLowerCase() === botLogin.toLowerCase();
}
src/github/self-authored.ts:23-29 (normalizeGitHubSlug) lowercases the app slug before every
appSlugMatches comparison, and :36-40 (isBotActor) lowercases the actor login too.
If GitHub ever returns the bot's login with different casing than env.GITHUB_APP_SLUG produces (or the app
slug itself is configured with different casing than GitHub's canonical form), dismissLatestBotApproval
silently finds no match and returns { dismissed: false } — a quiet no-op with no error, not a crash, so it
would be easy to miss in practice: a stale bot approval would simply never get dismissed for a review-evasion
or re-review flow that expects it to be.
test/unit/github-pr-actions.test.ts:544-608 (the three dismissLatestBotApproval tests) only ever use a
review.user.login of "gittensory[bot]" against the default test-env GITHUB_APP_SLUG of "gittensory"
(test/helpers/d1.ts:85) — always matching case, so this gap is currently untested as well as unfixed.
Requirements
dismissLatestBotApproval in src/github/pr-actions.ts MUST compare the review author's login to the
expected bot login case-insensitively, matching the .toLowerCase() comparison pattern already used by
isLoopOverBotComment in src/github/comments.ts:104-106.
- The fix must be scoped to the login comparison only (
src/github/pr-actions.ts:143, and the derivation of
botLogin at :135 if needed to support it) — no other behavior of dismissLatestBotApproval (pagination,
the "latest across pages" selection, the best-effort try/catch, the dismissal write) may change.
Deliverables
Test Coverage Requirements
This change touches src/github/pr-actions.ts and test/unit/github-pr-actions.test.ts, both under this
repo's src/** Codecov patch gate (99%+ patch coverage, hard gate). The new case-insensitive comparison
branch must be exercised by the new mismatched-case test so the patch is fully covered.
Expected Outcome
dismissLatestBotApproval finds and dismisses the bot's own latest APPROVE review regardless of the login
casing GitHub returns or GITHUB_APP_SLUG is configured with, matching the case-insensitivity already
guaranteed for every other bot-login check in this subsystem (comments.ts, self-authored.ts), instead of
silently degrading to a no-op on a casing mismatch.
Links & Resources
src/github/pr-actions.ts:130-161 (dismissLatestBotApproval, the function to fix)
src/github/comments.ts:104-106 (isLoopOverBotComment, the case-insensitive pattern to mirror)
src/github/self-authored.ts:23-29, :36-40 (normalizeGitHubSlug / isBotActor, further precedent for lowercasing bot logins before comparison)
test/unit/github-pr-actions.test.ts:544-608 (the existing dismissLatestBotApproval test block to extend)
test/helpers/d1.ts:85 (default GITHUB_APP_SLUG test fixture value)
Context
dismissLatestBotApprovalinsrc/github/pr-actions.ts:130-161finds the bot's own most recent APPROVEreview so it can be dismissed. It matches the bot's login with a case-sensitive
===:(
src/github/pr-actions.ts:135and:143.)Every other bot-login comparison in this same subsystem normalizes case before comparing:
isLoopOverBotCommentinsrc/github/comments.ts:104-106:src/github/self-authored.ts:23-29(normalizeGitHubSlug) lowercases the app slug before everyappSlugMatchescomparison, and:36-40(isBotActor) lowercases the actor login too.If GitHub ever returns the bot's login with different casing than
env.GITHUB_APP_SLUGproduces (or the appslug itself is configured with different casing than GitHub's canonical form),
dismissLatestBotApprovalsilently finds no match and returns
{ dismissed: false }— a quiet no-op with no error, not a crash, so itwould be easy to miss in practice: a stale bot approval would simply never get dismissed for a review-evasion
or re-review flow that expects it to be.
test/unit/github-pr-actions.test.ts:544-608(the threedismissLatestBotApprovaltests) only ever use areview.user.loginof"gittensory[bot]"against the default test-envGITHUB_APP_SLUGof"gittensory"(
test/helpers/d1.ts:85) — always matching case, so this gap is currently untested as well as unfixed.Requirements
dismissLatestBotApprovalinsrc/github/pr-actions.tsMUST compare the review author's login to theexpected bot login case-insensitively, matching the
.toLowerCase()comparison pattern already used byisLoopOverBotCommentinsrc/github/comments.ts:104-106.src/github/pr-actions.ts:143, and the derivation ofbotLoginat:135if needed to support it) — no other behavior ofdismissLatestBotApproval(pagination,the "latest across pages" selection, the best-effort try/catch, the dismissal write) may change.
Deliverables
dismissLatestBotApprovalinsrc/github/pr-actions.tsmatchesreview.user?.loginagainst theexpected bot login case-insensitively.
test/unit/github-pr-actions.test.tsextended with a case where a review'suser.loginuses differentcasing than
env.GITHUB_APP_SLUGproduces (e.g."Gittensory[bot]"against the defaultGITHUB_APP_SLUG: "gittensory"fromtest/helpers/d1.ts:85), asserting the mismatched-case APPROVEreview is still found and dismissed — mirroring the structure of the existing
"dismisses the bot's own LATEST approve review..."test attest/unit/github-pr-actions.test.ts:544-566.Test Coverage Requirements
This change touches
src/github/pr-actions.tsandtest/unit/github-pr-actions.test.ts, both under thisrepo's
src/**Codecov patch gate (99%+ patch coverage, hard gate). The new case-insensitive comparisonbranch must be exercised by the new mismatched-case test so the patch is fully covered.
Expected Outcome
dismissLatestBotApprovalfinds and dismisses the bot's own latest APPROVE review regardless of the logincasing GitHub returns or
GITHUB_APP_SLUGis configured with, matching the case-insensitivity alreadyguaranteed for every other bot-login check in this subsystem (
comments.ts,self-authored.ts), instead ofsilently degrading to a no-op on a casing mismatch.
Links & Resources
src/github/pr-actions.ts:130-161(dismissLatestBotApproval, the function to fix)src/github/comments.ts:104-106(isLoopOverBotComment, the case-insensitive pattern to mirror)src/github/self-authored.ts:23-29,:36-40(normalizeGitHubSlug/isBotActor, further precedent for lowercasing bot logins before comparison)test/unit/github-pr-actions.test.ts:544-608(the existingdismissLatestBotApprovaltest block to extend)test/helpers/d1.ts:85(defaultGITHUB_APP_SLUGtest fixture value)