fix: gate Forgejo review/comment triggers on @claude mention
Previously, all pull_request_comment events on Forgejo triggered the full Claude pipeline unconditionally — both in the workflow if-condition and in trigger.ts. This wasted CI resources and API credits on reviews without @claude mentions (e.g. plain "LGTM" reviews). Workflow: add @claude check via contains() on comment.body and review.body. Trigger validation: replace blind auto-trigger with payload-aware check that inspects available body fields, falling back only when no body exists. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
d9c22ffe50
commit
71fb686885
2 files changed
+24
-18
No files matched your search
@@ -24,7 +24,8 @@ jobs:
|
||||
# despite action being 'labeled'). Let all through; trigger.ts validates.
|
||||
if: >-
|
||||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review_comment' || github.event_name == 'pull_request_comment') ||
|
||||
(github.event_name == 'pull_request_review_comment' || github.event_name == 'pull_request_comment') &&
|
||||
(contains(github.event.comment.body, '@claude') || contains(github.event.review.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
||||
(github.event_name == 'issues')
|
||||
runs-on: grunt
|
||||
|
||||
@@ -123,32 +123,37 @@ export function checkContainsTrigger(context: ParsedGitHubContext): boolean {
|
||||
isIssueCommentEvent(context) ||
|
||||
isPullRequestReviewCommentEvent(context)
|
||||
) {
|
||||
// Forgejo's pull_request_review_comment payload does NOT include a
|
||||
// top-level `comment` object (it's undefined). On Forgejo, the
|
||||
// workflow `if:` already gates on event name alone, so always trigger
|
||||
// here — the actual comment data is fetched via REST in the data
|
||||
// fetcher, and non-matching comments won't produce useful output.
|
||||
if (
|
||||
isPullRequestReviewCommentEvent(context) &&
|
||||
detectPlatform() === "forgejo"
|
||||
) {
|
||||
console.log(
|
||||
"Forgejo pull_request_review_comment: triggering (payload lacks comment body)",
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Forgejo sends both review comments and full reviews as
|
||||
// `pull_request_comment`, which normalizes to `pull_request_review_comment`.
|
||||
// The payload may have `comment.body`, `review.body`, both, or neither.
|
||||
// Try all available body fields before giving up.
|
||||
const payload = context.payload as Record<string, any>;
|
||||
const commentBody = isIssueCommentEvent(context)
|
||||
? context.payload.comment.body
|
||||
: context.payload.comment.body;
|
||||
: (payload.comment?.body ?? payload.review?.body ?? "");
|
||||
|
||||
// Check for exact match with word boundaries or punctuation
|
||||
const regex = new RegExp(
|
||||
`(^|\\s)${escapeRegExp(triggerPhrase)}([\\s.,!?;:]|$)`,
|
||||
);
|
||||
if (regex.test(commentBody)) {
|
||||
if (commentBody && regex.test(commentBody)) {
|
||||
console.log(`Comment contains exact trigger phrase '${triggerPhrase}'`);
|
||||
return true;
|
||||
}
|
||||
|
||||
// On Forgejo, if no body was found in the payload at all, still trigger —
|
||||
// the actual comment data will be fetched via REST in the data fetcher.
|
||||
// This handles edge cases where Forgejo strips body from the webhook payload.
|
||||
if (
|
||||
isPullRequestReviewCommentEvent(context) &&
|
||||
detectPlatform() === "forgejo" &&
|
||||
!commentBody
|
||||
) {
|
||||
console.log(
|
||||
"Forgejo pull_request_review_comment: no body in payload, triggering (data fetched via REST)",
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`No trigger was met for ${triggerPhrase}`);
|
||||
|
||||
Reference in new issue
Block a user