1+ import { WebhookEvent , WebhookEventMap , WebhookEventName } from "@octokit/webhooks-types" ;
2+
13import { getRequestLog } from "./context.ts" ;
24import { getAndIncrementKV } from "./kv.ts" ;
35import { UrlConfig } from "./types.d.ts" ;
46import { wildcardMatch } from "./util.ts" ;
57
68const COMMON_CI_BOTS = [ "coveralls[bot]" , "netlify[bot]" , "pre-commit-ci[bot]" , "dependabot[bot]" ] ;
79
10+ function isGitHubEvent < T extends WebhookEventName > (
11+ _data : WebhookEvent ,
12+ eventType : string ,
13+ expected : T ,
14+ ) : _data is WebhookEventMap [ T ] {
15+ return eventType === expected ;
16+ }
17+
818export default async function filter (
919 headers : Record < string , string > ,
10- json : any ,
20+ json : WebhookEvent ,
1121 config : UrlConfig ,
1222) : Promise < string | null > {
1323 const event = headers [ "x-github-event" ] || "unknown" ;
24+
25+ if ( ! ( "sender" in json ) ) {
26+ // Discord always requires a sender (most events have this, but a handful of them don't)
27+ return "missing sender" ;
28+ }
1429 const login : string | undefined = json . sender ?. login ?. toLowerCase ( ) ;
1530
1631 // ignore events that Discord won't render anyway
@@ -20,36 +35,36 @@ export default async function filter(
2035
2136 // ignore all PR actions except "opened", "closed", "reopened"
2237 if (
23- event === "pull_request" && json . action &&
38+ isGitHubEvent ( json , event , "pull_request" ) &&
2439 ! [ "opened" , "closed" , "reopened" ] . includes ( json . action )
2540 ) {
2641 return `no-op PR action '${ json . action } '` ;
2742 }
2843
2944 // ignore all issue actions except "opened", "deleted", "closed", "reopened", "transferred"
3045 if (
31- event === "issues" && json . action &&
46+ isGitHubEvent ( json , event , "issues" ) &&
3247 ! [ "opened" , "deleted" , "closed" , "reopened" , "transferred" ] . includes ( json . action )
3348 ) {
3449 return `no-op issue action '${ json . action } '` ;
3550 }
3651
3752 // ignore some PR review actions
38- if ( event === "pull_request_review" ) {
53+ if ( isGitHubEvent ( json , event , "pull_request_review" ) ) {
3954 // ignore edit/dismiss actions
4055 if ( json . action !== "submitted" ) return `no-op PR review action '${ json . action } '` ;
4156
4257 // if comment (not approval or changes requested), ignore empty review body
43- if ( json . review ? .state === "commented" && ! json . review ? .body ) return "empty PR review" ;
58+ if ( json . review . state === "commented" && ! json . review . body ) return "empty PR review" ;
4459 }
4560
4661 // ignore some PR comment events
47- if ( event === "pull_request_review_comment" ) {
62+ if ( isGitHubEvent ( json , event , "pull_request_review_comment" ) ) {
4863 // ignore edit/delete actions
4964 if ( json . action !== "created" ) return `no-op PR comment action '${ json . action } '` ;
5065
5166 // check if more than x comments on a PR review in a short timespan
52- const reviewId : number = json . comment ? .pull_request_review_id ;
67+ const reviewId : number = json . comment . pull_request_review_id ;
5368 if ( config . commentBurstLimit && reviewId ) {
5469 const cacheKey = `${ reviewId } -${ login } ` ;
5570
@@ -66,7 +81,7 @@ export default async function filter(
6681
6782 let refType : "branch" | "tag" | undefined ;
6883 let ref : string | undefined ;
69- if ( event === "push" ) {
84+ if ( isGitHubEvent ( json , event , "push" ) ) {
7085 // ignore branch/tag push
7186 const refMatch = / ^ r e f s \/ ( [ ^ \/ ] + ) \/ ( .+ ) $ / . exec ( json . ref ) ;
7287 if ( refMatch ) {
@@ -75,7 +90,7 @@ export default async function filter(
7590 : ( refMatch [ 1 ] == "tags" ? "tag" : undefined ) ;
7691 ref = refMatch [ 2 ] ;
7792 }
78- } else if ( [ "create" , "delete" ] . includes ( event ) ) {
93+ } else if ( isGitHubEvent ( json , event , "create" ) || isGitHubEvent ( json , event , "delete" ) ) {
7994 // ignore creation/deletion of branch/tag
8095 refType = json . ref_type ;
8196 ref = json . ref ;
0 commit comments