@sentry/junior-github 0.181.0 → 0.182.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,825 +0,0 @@
1
- // src/webhooks/resource-events.ts
2
- import { z } from "zod";
3
-
4
- // src/resource-events/deployment.ts
5
- var GITHUB_DEPLOYMENT_EVENTS = [
6
- "deployment.created",
7
- "deployment.queued",
8
- "deployment.pending",
9
- "deployment.in_progress",
10
- "deployment.succeeded",
11
- "deployment.failed",
12
- "deployment.error"
13
- ];
14
- var GITHUB_DEPLOYMENT_SUGGESTED_EVENTS = [
15
- "deployment.succeeded",
16
- "deployment.failed",
17
- "deployment.error"
18
- ];
19
- function gitHubDeploymentSourceResource(input) {
20
- const commitSha = input.commitSha.toLowerCase();
21
- const environment = input.environment?.trim();
22
- const repo = input.repo.toLowerCase();
23
- return {
24
- label: `GitHub deployment for ${repo} at ${commitSha.slice(0, 12)}`,
25
- namespace: "github",
26
- identifier: environment ? `deployment-source:${repo}:${encodeURIComponent(environment.toLowerCase())}:${commitSha}` : `deployment-source:${repo}:${commitSha}`
27
- };
28
- }
29
- function gitHubDeploymentSourceSubscribable(input) {
30
- if (!process.env.GITHUB_WEBHOOK_SECRET?.trim()) return void 0;
31
- return {
32
- ...gitHubDeploymentSourceResource(input),
33
- suggestedEvents: GITHUB_DEPLOYMENT_SUGGESTED_EVENTS,
34
- supportedEvents: [...GITHUB_DEPLOYMENT_EVENTS],
35
- type: "deployment_source"
36
- };
37
- }
38
-
39
- // src/resource-events/issue.ts
40
- var GITHUB_ISSUE_EVENTS = [
41
- "issue.comment.created",
42
- "issue.opened",
43
- "issue.closed",
44
- "issue.reopened"
45
- ];
46
- var GITHUB_ISSUE_SUGGESTED_EVENTS = [
47
- "issue.comment.created",
48
- "issue.closed",
49
- "issue.reopened"
50
- ];
51
- function gitHubIssueResource(input) {
52
- return {
53
- label: `GitHub issue ${input.repo}#${input.number}`,
54
- namespace: "github",
55
- identifier: `${input.repo.toLowerCase()}#${input.number}`
56
- };
57
- }
58
- function gitHubIssueSubscribable(input) {
59
- if (!process.env.GITHUB_WEBHOOK_SECRET?.trim()) return void 0;
60
- return {
61
- ...gitHubIssueResource(input),
62
- suggestedEvents: GITHUB_ISSUE_SUGGESTED_EVENTS,
63
- supportedEvents: GITHUB_ISSUE_EVENTS,
64
- type: "issue"
65
- };
66
- }
67
-
68
- // src/resource-events/pull-request.ts
69
- var GITHUB_PULL_REQUEST_EVENTS = [
70
- "pull_request.checks.failed",
71
- "pull_request.checks.recovered",
72
- "pull_request.comment.created",
73
- "pull_request.opened",
74
- "pull_request.ready_for_review",
75
- "pull_request.review.approved",
76
- "pull_request.review.changes_requested",
77
- "pull_request.review.commented",
78
- "pull_request.review_comment.created",
79
- "pull_request.merged",
80
- "pull_request.closed_unmerged"
81
- ];
82
- var GITHUB_PULL_REQUEST_SUGGESTED_EVENTS = [
83
- "pull_request.checks.failed",
84
- "pull_request.comment.created",
85
- "pull_request.ready_for_review",
86
- "pull_request.review.changes_requested",
87
- "pull_request.review.commented",
88
- "pull_request.review_comment.created",
89
- "pull_request.merged",
90
- "pull_request.closed_unmerged"
91
- ];
92
- function gitHubPullRequestResource(input) {
93
- return {
94
- label: `GitHub PR ${input.repo}#${input.number}`,
95
- namespace: "github",
96
- identifier: `${input.repo.toLowerCase()}#${input.number}`
97
- };
98
- }
99
- function gitHubPullRequestSubscribable(input) {
100
- if (!process.env.GITHUB_WEBHOOK_SECRET?.trim()) return void 0;
101
- const omitted = new Set(input.omitSuggestedEvents ?? []);
102
- const suggestedEvents = GITHUB_PULL_REQUEST_SUGGESTED_EVENTS.filter(
103
- (eventType) => !omitted.has(eventType)
104
- );
105
- return {
106
- ...gitHubPullRequestResource(input),
107
- ...suggestedEvents.length > 0 ? { suggestedEvents: [...suggestedEvents] } : void 0,
108
- supportedEvents: [...GITHUB_PULL_REQUEST_EVENTS],
109
- type: "pull_request"
110
- };
111
- }
112
-
113
- // src/resource-events/release.ts
114
- var GITHUB_RELEASE_EVENTS = ["release.published"];
115
- var GITHUB_RELEASE_SUGGESTED_EVENTS = ["release.published"];
116
- function gitHubReleaseSourceResource(input) {
117
- const repo = input.repo.toLowerCase();
118
- const tag = input.tag?.trim();
119
- return {
120
- label: `GitHub release for ${repo}`,
121
- namespace: "github",
122
- identifier: tag ? `release-source:${repo}:${encodeURIComponent(tag)}` : `release-source:${repo}`
123
- };
124
- }
125
- function gitHubReleaseSourceSubscribable(input) {
126
- if (!process.env.GITHUB_WEBHOOK_SECRET?.trim()) return void 0;
127
- return {
128
- ...gitHubReleaseSourceResource(input),
129
- suggestedEvents: GITHUB_RELEASE_SUGGESTED_EVENTS,
130
- supportedEvents: [...GITHUB_RELEASE_EVENTS],
131
- type: "release_source"
132
- };
133
- }
134
-
135
- // src/resource-events/repository.ts
136
- function gitHubRepositoryResource(input) {
137
- return {
138
- label: `GitHub repository ${input.repo}`,
139
- namespace: "github",
140
- identifier: input.repo.toLowerCase()
141
- };
142
- }
143
- function gitHubRepositorySubscribable(input) {
144
- if (!process.env.GITHUB_WEBHOOK_SECRET?.trim()) return void 0;
145
- return {
146
- ...gitHubRepositoryResource(input),
147
- suggestedEvents: [
148
- "issue.opened",
149
- "pull_request.opened",
150
- ...GITHUB_ISSUE_SUGGESTED_EVENTS,
151
- ...GITHUB_PULL_REQUEST_SUGGESTED_EVENTS
152
- ],
153
- supportedEvents: [...GITHUB_ISSUE_EVENTS, ...GITHUB_PULL_REQUEST_EVENTS],
154
- type: "repository"
155
- };
156
- }
157
-
158
- // src/webhooks/resource-events.ts
159
- function gitHubEventKey(deliveryId, eventType) {
160
- return `github:${deliveryId}:${eventType}`;
161
- }
162
- function pullRequestTargets(event, repo) {
163
- const { terminal: _terminal, ...repositoryEvent } = event;
164
- return [
165
- event,
166
- {
167
- ...repositoryEvent,
168
- identifier: gitHubRepositoryResource({ repo }).identifier
169
- }
170
- ];
171
- }
172
- var repositorySchema = z.object({ full_name: z.string().min(1) }).passthrough();
173
- var deploymentSchema = z.object({
174
- created_at: z.string().optional(),
175
- environment: z.string().min(1),
176
- id: z.number(),
177
- sha: z.string().regex(/^[0-9a-f]{40}$/i)
178
- }).passthrough();
179
- var deploymentWebhookSchema = z.object({
180
- action: z.string(),
181
- deployment: deploymentSchema,
182
- repository: repositorySchema
183
- }).passthrough();
184
- var canonicalDeploymentEventSchema = z.object({
185
- action: z.string(),
186
- commitSha: z.string().regex(/^[0-9a-f]{40}$/i),
187
- createdAt: z.string().optional(),
188
- deploymentId: z.number(),
189
- environment: z.string().min(1),
190
- repo: z.string().min(1)
191
- }).strict();
192
- function parseDeploymentEvent(body) {
193
- const parsed = deploymentWebhookSchema.safeParse(body);
194
- if (!parsed.success) return void 0;
195
- return canonicalDeploymentEventSchema.parse({
196
- action: parsed.data.action,
197
- commitSha: parsed.data.deployment.sha,
198
- createdAt: parsed.data.deployment.created_at,
199
- deploymentId: parsed.data.deployment.id,
200
- environment: parsed.data.deployment.environment,
201
- repo: parsed.data.repository.full_name
202
- });
203
- }
204
- function normalizeDeploymentEvent(deliveryId, body) {
205
- const parsed = parseDeploymentEvent(body);
206
- if (!parsed || parsed.action !== "created") return [];
207
- const eventType = "deployment.created";
208
- return deploymentSourceTargets(parsed).map(({ resource }) => ({
209
- eventKey: gitHubEventKey(deliveryId, eventType),
210
- eventType,
211
- occurredAtMs: providerTime(parsed.createdAt) ?? Date.now(),
212
- identifier: resource.identifier,
213
- trustedSummary: `${resource.label} was created (deployment ${parsed.deploymentId}).`
214
- }));
215
- }
216
- var deploymentStatusWebhookSchema = z.object({
217
- action: z.string(),
218
- deployment: deploymentSchema,
219
- deployment_status: z.object({
220
- created_at: z.string().optional(),
221
- description: z.string().optional().nullable(),
222
- state: z.string()
223
- }).passthrough(),
224
- repository: repositorySchema
225
- }).passthrough();
226
- var canonicalDeploymentStatusEventSchema = canonicalDeploymentEventSchema.extend({
227
- description: z.string().optional().nullable(),
228
- state: z.string(),
229
- statusCreatedAt: z.string().optional()
230
- }).strict();
231
- function parseDeploymentStatusEvent(body) {
232
- const parsed = deploymentStatusWebhookSchema.safeParse(body);
233
- if (!parsed.success) return void 0;
234
- return canonicalDeploymentStatusEventSchema.parse({
235
- action: parsed.data.action,
236
- commitSha: parsed.data.deployment.sha,
237
- createdAt: parsed.data.deployment.created_at,
238
- deploymentId: parsed.data.deployment.id,
239
- description: parsed.data.deployment_status.description,
240
- environment: parsed.data.deployment.environment,
241
- repo: parsed.data.repository.full_name,
242
- state: parsed.data.deployment_status.state,
243
- statusCreatedAt: parsed.data.deployment_status.created_at
244
- });
245
- }
246
- function deploymentStatusEventType(state) {
247
- switch (state) {
248
- case "queued":
249
- case "pending":
250
- case "in_progress":
251
- return `deployment.${state}`;
252
- case "success":
253
- return "deployment.succeeded";
254
- case "failure":
255
- return "deployment.failed";
256
- case "error":
257
- return "deployment.error";
258
- default:
259
- return void 0;
260
- }
261
- }
262
- function normalizeDeploymentStatusEvent(deliveryId, body) {
263
- const parsed = parseDeploymentStatusEvent(body);
264
- if (!parsed || parsed.action !== "created") return [];
265
- const eventType = deploymentStatusEventType(parsed.state);
266
- if (!eventType) return [];
267
- const outcome = eventType === "deployment.succeeded" ? "succeeded" : eventType === "deployment.failed" ? "failed" : eventType === "deployment.error" ? "reported an error" : eventType === "deployment.in_progress" ? "started" : `is ${parsed.state}`;
268
- const terminal = eventType === "deployment.succeeded" || eventType === "deployment.failed" || eventType === "deployment.error";
269
- return deploymentSourceTargets(parsed).map(
270
- ({ completeOnTerminalEvent, resource }) => ({
271
- eventKey: gitHubEventKey(deliveryId, eventType),
272
- eventType,
273
- occurredAtMs: providerTime(parsed.statusCreatedAt) ?? Date.now(),
274
- identifier: resource.identifier,
275
- ...terminal && completeOnTerminalEvent ? { terminal: true } : void 0,
276
- trustedSummary: `${resource.label} ${outcome} (deployment ${parsed.deploymentId}).`,
277
- untrustedText: parsed.description ?? void 0
278
- })
279
- );
280
- }
281
- function deploymentSourceTargets(input) {
282
- return [
283
- {
284
- completeOnTerminalEvent: true,
285
- resource: gitHubDeploymentSourceResource(input)
286
- },
287
- {
288
- completeOnTerminalEvent: false,
289
- resource: gitHubDeploymentSourceResource({
290
- commitSha: input.commitSha,
291
- repo: input.repo
292
- })
293
- }
294
- ];
295
- }
296
- var checkSuiteWebhookSchema = z.object({
297
- action: z.string(),
298
- check_suite: z.object({
299
- app: z.object({
300
- name: z.string().optional().nullable(),
301
- slug: z.string().optional().nullable()
302
- }).optional().nullable(),
303
- conclusion: z.string().optional().nullable(),
304
- head_sha: z.string().optional(),
305
- id: z.number().optional(),
306
- latest_check_runs_count: z.number().optional().nullable(),
307
- pull_requests: z.array(z.object({ number: z.number() }))
308
- }),
309
- repository: repositorySchema
310
- });
311
- var FAILING_CHECK_CONCLUSIONS = /* @__PURE__ */ new Set([
312
- "failure",
313
- "timed_out",
314
- "cancelled",
315
- "action_required",
316
- "startup_failure"
317
- ]);
318
- function buildCheckSuiteUrl(args) {
319
- return `https://github.com/${args.repo}/commit/${args.headSha}/checks?check_suite_id=${args.checkSuiteId}`;
320
- }
321
- function oneLineLabel(value, maxLength = 80) {
322
- return value.replace(/[\r\n]+/g, " ").replace(/\s+/g, " ").trim().slice(0, maxLength);
323
- }
324
- function buildCheckSuiteResourceEvent(args) {
325
- const resource = gitHubPullRequestResource({
326
- number: args.pullRequestNumber,
327
- repo: args.repo
328
- });
329
- const shortSha = args.headSha?.slice(0, 12);
330
- const failingChecks = (args.failingChecks ?? []).slice(0, 12);
331
- const failingCount = failingChecks.length;
332
- const trustedSummary = args.eventType === "pull_request.checks.failed" ? `${resource.label} checks failed${failingCount > 0 ? ` (${failingCount})` : ""}${shortSha ? ` for ${shortSha}` : ""}.` : `${resource.label} check suite recovered${shortSha ? ` for ${shortSha}` : ""}.`;
333
- const data = {
334
- repo: args.repo,
335
- pullRequest: args.pullRequestNumber,
336
- scope: "check_suite",
337
- suiteConclusion: args.suiteConclusion
338
- };
339
- if (args.headSha) data.headSha = args.headSha;
340
- if (args.checkSuiteId !== void 0) data.checkSuiteId = args.checkSuiteId;
341
- if (args.checkSuiteId !== void 0 && args.headSha) {
342
- data.checkSuiteUrl = buildCheckSuiteUrl({
343
- checkSuiteId: args.checkSuiteId,
344
- headSha: args.headSha,
345
- repo: args.repo
346
- });
347
- }
348
- if (args.appName) data.appName = oneLineLabel(args.appName, 120);
349
- if (args.latestCheckRunsCount !== void 0) {
350
- data.latestCheckRunsCount = args.latestCheckRunsCount;
351
- }
352
- if (args.eventType === "pull_request.checks.failed" && failingCount > 0) {
353
- data.failingChecks = failingChecks.map((check) => ({
354
- conclusion: check.conclusion,
355
- ...check.htmlUrl ? { htmlUrl: check.htmlUrl } : void 0,
356
- checkRunId: check.checkRunId
357
- }));
358
- }
359
- const untrustedParts = args.eventType === "pull_request.checks.failed" ? failingChecks.map((check) => {
360
- const name = oneLineLabel(check.name);
361
- if (!name) return void 0;
362
- return check.htmlUrl ? `${name}: ${check.htmlUrl}` : name;
363
- }).filter((part) => part !== void 0) : [];
364
- const untrustedText = untrustedParts.length > 0 ? [`Failed checks:`, ...untrustedParts.map((part) => `- ${part}`)].join(
365
- "\n"
366
- ) : void 0;
367
- return {
368
- eventKey: gitHubEventKey(
369
- args.deliveryId,
370
- `${args.eventType}:${args.pullRequestNumber}`
371
- ),
372
- eventType: args.eventType,
373
- occurredAtMs: Date.now(),
374
- identifier: resource.identifier,
375
- trustedSummary,
376
- data,
377
- ...untrustedText ? { untrustedText } : void 0
378
- };
379
- }
380
- function selectFailingChecks(checkRuns, options) {
381
- if (!Array.isArray(checkRuns)) return [];
382
- const failing = [];
383
- for (const run of checkRuns) {
384
- if (!run || typeof run !== "object" || Array.isArray(run)) continue;
385
- const record = run;
386
- if (options?.checkSuiteId !== void 0) {
387
- const suite = record.check_suite;
388
- const suiteId = suite && typeof suite === "object" && !Array.isArray(suite) && typeof suite.id === "number" ? suite.id : void 0;
389
- if (suiteId !== void 0 && suiteId !== options.checkSuiteId) continue;
390
- }
391
- const conclusion = typeof record.conclusion === "string" ? record.conclusion : void 0;
392
- const name = typeof record.name === "string" ? record.name.trim() : "";
393
- const checkRunId = typeof record.id === "number" && Number.isSafeInteger(record.id) ? record.id : void 0;
394
- if (!conclusion || !FAILING_CHECK_CONCLUSIONS.has(conclusion)) continue;
395
- if (!name || checkRunId === void 0) continue;
396
- const htmlUrl = typeof record.html_url === "string" && record.html_url.length > 0 ? record.html_url : void 0;
397
- failing.push({
398
- checkRunId,
399
- conclusion,
400
- ...htmlUrl ? { htmlUrl } : void 0,
401
- name
402
- });
403
- }
404
- return failing.slice(0, 12);
405
- }
406
- function normalizeCheckSuiteEvents(deliveryId, body, options) {
407
- const parsed = checkSuiteWebhookSchema.safeParse(body);
408
- if (!parsed.success || parsed.data.action !== "completed") return [];
409
- const conclusion = parsed.data.check_suite.conclusion;
410
- if (!conclusion) return [];
411
- const eventType = conclusion === "failure" || conclusion === "timed_out" ? "pull_request.checks.failed" : conclusion === "success" ? "pull_request.checks.recovered" : void 0;
412
- if (!eventType) return [];
413
- const suite = parsed.data.check_suite;
414
- const appName = suite.app?.name?.trim() || suite.app?.slug?.trim() || void 0;
415
- const headSha = typeof suite.head_sha === "string" && /^[0-9a-f]{7,40}$/i.test(suite.head_sha) ? suite.head_sha : void 0;
416
- return suite.pull_requests.flatMap((pullRequest) => {
417
- const repo = parsed.data.repository.full_name;
418
- return pullRequestTargets(
419
- buildCheckSuiteResourceEvent({
420
- appName,
421
- checkSuiteId: suite.id,
422
- deliveryId,
423
- eventType,
424
- failingChecks: eventType === "pull_request.checks.failed" ? options?.failingChecks : void 0,
425
- headSha,
426
- latestCheckRunsCount: typeof suite.latest_check_runs_count === "number" ? suite.latest_check_runs_count : void 0,
427
- pullRequestNumber: pullRequest.number,
428
- repo,
429
- suiteConclusion: conclusion
430
- }),
431
- repo
432
- );
433
- });
434
- }
435
- var issueCommentWebhookSchema = z.object({
436
- action: z.string(),
437
- comment: z.object({
438
- body: z.string(),
439
- user: z.object({ login: z.string().optional() }).optional()
440
- }),
441
- issue: z.object({
442
- number: z.number(),
443
- pull_request: z.object({ url: z.string().min(1) }).optional()
444
- }),
445
- repository: repositorySchema
446
- });
447
- function normalizeIssueCommentEvents(deliveryId, body) {
448
- const parsed = issueCommentWebhookSchema.safeParse(body);
449
- if (!parsed.success || parsed.data.action !== "created") return [];
450
- const input = {
451
- number: parsed.data.issue.number,
452
- repo: parsed.data.repository.full_name
453
- };
454
- const author = parsed.data.comment.user?.login;
455
- if (parsed.data.issue.pull_request) {
456
- const eventType = "pull_request.comment.created";
457
- const resource = gitHubPullRequestResource(input);
458
- return pullRequestTargets(
459
- {
460
- eventKey: gitHubEventKey(deliveryId, eventType),
461
- eventType,
462
- occurredAtMs: Date.now(),
463
- identifier: resource.identifier,
464
- trustedSummary: `${resource.label} received a comment${author ? ` from ${author}` : ""}.`,
465
- untrustedText: parsed.data.comment.body
466
- },
467
- input.repo
468
- );
469
- }
470
- const issue = gitHubIssueResource(input);
471
- const repository = gitHubRepositoryResource(input);
472
- return [
473
- {
474
- eventKey: gitHubEventKey(deliveryId, "issue.comment.created"),
475
- eventType: "issue.comment.created",
476
- occurredAtMs: Date.now(),
477
- identifier: issue.identifier,
478
- trustedSummary: `${issue.label} received a comment${author ? ` from ${author}` : ""}.`,
479
- untrustedText: parsed.data.comment.body
480
- },
481
- {
482
- eventKey: gitHubEventKey(deliveryId, "issue.comment.created"),
483
- eventType: "issue.comment.created",
484
- occurredAtMs: Date.now(),
485
- identifier: repository.identifier,
486
- trustedSummary: `${issue.label} received a comment${author ? ` from ${author}` : ""}.`,
487
- untrustedText: parsed.data.comment.body
488
- }
489
- ];
490
- }
491
- var issueWebhookSchema = z.object({
492
- action: z.string(),
493
- issue: z.object({
494
- body: z.string().optional().nullable(),
495
- closed_at: z.string().optional().nullable(),
496
- created_at: z.string().optional(),
497
- number: z.number(),
498
- title: z.string().optional(),
499
- updated_at: z.string().optional()
500
- }),
501
- repository: repositorySchema
502
- });
503
- function issueEventText(issue) {
504
- const parts = [
505
- issue.title ? `Title: ${issue.title}` : void 0,
506
- issue.body?.trim() || void 0
507
- ].filter((part) => part !== void 0);
508
- return parts.length > 0 ? parts.join("\n\n") : void 0;
509
- }
510
- function normalizeIssueEvents(deliveryId, body) {
511
- const parsed = issueWebhookSchema.safeParse(body);
512
- if (!parsed.success) return [];
513
- const state = parsed.data.action === "opened" ? "opened" : parsed.data.action === "closed" ? "closed" : parsed.data.action === "reopened" ? "reopened" : void 0;
514
- if (!state) return [];
515
- const input = {
516
- number: parsed.data.issue.number,
517
- repo: parsed.data.repository.full_name
518
- };
519
- const issue = gitHubIssueResource(input);
520
- const repository = gitHubRepositoryResource(input);
521
- const occurredAtMs = providerTime(
522
- state === "opened" ? parsed.data.issue.created_at : state === "closed" ? parsed.data.issue.closed_at : parsed.data.issue.updated_at
523
- ) ?? Date.now();
524
- const untrustedText = issueEventText(parsed.data.issue);
525
- return [
526
- {
527
- eventKey: gitHubEventKey(deliveryId, `issue.${state}`),
528
- eventType: `issue.${state}`,
529
- occurredAtMs,
530
- identifier: issue.identifier,
531
- trustedSummary: `${issue.label} was ${state}.`,
532
- ...untrustedText ? { untrustedText } : void 0
533
- },
534
- {
535
- eventKey: gitHubEventKey(deliveryId, `issue.${state}`),
536
- eventType: `issue.${state}`,
537
- occurredAtMs,
538
- identifier: repository.identifier,
539
- trustedSummary: `${issue.label} was ${state}.`,
540
- ...untrustedText ? { untrustedText } : void 0
541
- }
542
- ];
543
- }
544
- var pullRequestReviewCommentWebhookSchema = z.object({
545
- action: z.string(),
546
- comment: z.object({
547
- body: z.string(),
548
- user: z.object({ login: z.string().optional() }).optional()
549
- }),
550
- pull_request: z.object({ number: z.number() }),
551
- repository: repositorySchema
552
- });
553
- function normalizePullRequestReviewCommentEvent(deliveryId, body) {
554
- const parsed = pullRequestReviewCommentWebhookSchema.safeParse(body);
555
- if (!parsed.success || parsed.data.action !== "created") return [];
556
- const eventType = "pull_request.review_comment.created";
557
- const repo = parsed.data.repository.full_name;
558
- const resource = gitHubPullRequestResource({
559
- number: parsed.data.pull_request.number,
560
- repo
561
- });
562
- const author = parsed.data.comment.user?.login;
563
- return pullRequestTargets(
564
- {
565
- eventKey: gitHubEventKey(deliveryId, eventType),
566
- eventType,
567
- occurredAtMs: Date.now(),
568
- identifier: resource.identifier,
569
- trustedSummary: `${resource.label} received an inline review comment${author ? ` from ${author}` : ""}.`,
570
- untrustedText: parsed.data.comment.body
571
- },
572
- repo
573
- );
574
- }
575
- var pullRequestReviewWebhookSchema = z.object({
576
- action: z.string(),
577
- pull_request: z.object({ number: z.number() }),
578
- repository: repositorySchema,
579
- review: z.object({
580
- body: z.string().optional().nullable(),
581
- state: z.string(),
582
- user: z.object({ login: z.string().optional() }).optional()
583
- })
584
- });
585
- function normalizePullRequestReviewEvent(deliveryId, body) {
586
- const parsed = pullRequestReviewWebhookSchema.safeParse(body);
587
- if (!parsed.success || parsed.data.action !== "submitted") return [];
588
- const reviewState = parsed.data.review.state.toUpperCase();
589
- const eventType = reviewState === "APPROVED" ? "pull_request.review.approved" : reviewState === "CHANGES_REQUESTED" ? "pull_request.review.changes_requested" : reviewState === "COMMENTED" ? "pull_request.review.commented" : void 0;
590
- if (!eventType) return [];
591
- const repo = parsed.data.repository.full_name;
592
- const resource = gitHubPullRequestResource({
593
- number: parsed.data.pull_request.number,
594
- repo
595
- });
596
- const reviewer = parsed.data.review.user?.login;
597
- return pullRequestTargets(
598
- {
599
- eventKey: gitHubEventKey(deliveryId, eventType),
600
- eventType,
601
- occurredAtMs: Date.now(),
602
- identifier: resource.identifier,
603
- trustedSummary: eventType === "pull_request.review.approved" ? `${resource.label} was approved${reviewer ? ` by ${reviewer}` : ""}.` : eventType === "pull_request.review.changes_requested" ? `${resource.label} received requested changes${reviewer ? ` from ${reviewer}` : ""}.` : `${resource.label} received a review comment${reviewer ? ` from ${reviewer}` : ""}.`,
604
- untrustedText: parsed.data.review.body ?? void 0
605
- },
606
- repo
607
- );
608
- }
609
- var pullRequestWebhookSchema = z.object({
610
- action: z.string(),
611
- pull_request: z.object({
612
- body: z.string().optional().nullable(),
613
- closed_at: z.string().optional().nullable(),
614
- created_at: z.string().optional(),
615
- draft: z.boolean().optional(),
616
- merged: z.boolean().optional(),
617
- merged_at: z.string().optional().nullable(),
618
- number: z.number(),
619
- title: z.string().optional(),
620
- updated_at: z.string().optional()
621
- }),
622
- repository: repositorySchema
623
- });
624
- function providerTime(value) {
625
- if (!value) return void 0;
626
- const parsed = Date.parse(value);
627
- return Number.isFinite(parsed) ? parsed : void 0;
628
- }
629
- function pullRequestEventText(pullRequest) {
630
- const parts = [
631
- pullRequest.title ? `Title: ${pullRequest.title}` : void 0,
632
- pullRequest.body?.trim() || void 0
633
- ].filter((part) => part !== void 0);
634
- return parts.length > 0 ? parts.join("\n\n") : void 0;
635
- }
636
- function pullRequestLifecycleEvents(input) {
637
- return pullRequestTargets(
638
- {
639
- eventKey: gitHubEventKey(input.deliveryId, input.eventType),
640
- eventType: input.eventType,
641
- occurredAtMs: input.occurredAtMs,
642
- identifier: input.resource.identifier,
643
- ...input.terminal ? { terminal: true } : void 0,
644
- trustedSummary: input.trustedSummary,
645
- ...input.untrustedText ? { untrustedText: input.untrustedText } : void 0
646
- },
647
- input.repo
648
- );
649
- }
650
- function normalizePullRequestEvent(deliveryId, body) {
651
- const parsed = pullRequestWebhookSchema.safeParse(body);
652
- if (!parsed.success) return [];
653
- const repo = parsed.data.repository.full_name;
654
- const resource = gitHubPullRequestResource({
655
- number: parsed.data.pull_request.number,
656
- repo
657
- });
658
- const untrustedText = pullRequestEventText(parsed.data.pull_request);
659
- if (parsed.data.action === "opened") {
660
- const openedAtMs = providerTime(parsed.data.pull_request.created_at) ?? Date.now();
661
- const events = pullRequestLifecycleEvents({
662
- deliveryId,
663
- eventType: "pull_request.opened",
664
- occurredAtMs: openedAtMs,
665
- repo,
666
- resource,
667
- trustedSummary: `${resource.label} was opened.`,
668
- untrustedText
669
- });
670
- if (parsed.data.pull_request.draft !== true) {
671
- events.push(
672
- ...pullRequestLifecycleEvents({
673
- deliveryId,
674
- eventType: "pull_request.ready_for_review",
675
- occurredAtMs: openedAtMs,
676
- repo,
677
- resource,
678
- trustedSummary: `${resource.label} is ready for review.`,
679
- untrustedText
680
- })
681
- );
682
- }
683
- return events;
684
- }
685
- if (parsed.data.action === "ready_for_review") {
686
- return pullRequestLifecycleEvents({
687
- deliveryId,
688
- eventType: "pull_request.ready_for_review",
689
- occurredAtMs: providerTime(parsed.data.pull_request.updated_at) ?? Date.now(),
690
- repo,
691
- resource,
692
- trustedSummary: `${resource.label} is ready for review.`,
693
- untrustedText
694
- });
695
- }
696
- if (parsed.data.action !== "closed") return [];
697
- const eventType = parsed.data.pull_request.merged ? "pull_request.merged" : "pull_request.closed_unmerged";
698
- return pullRequestLifecycleEvents({
699
- deliveryId,
700
- eventType,
701
- occurredAtMs: providerTime(
702
- parsed.data.pull_request.merged ? parsed.data.pull_request.merged_at : parsed.data.pull_request.closed_at
703
- ) ?? Date.now(),
704
- repo,
705
- resource,
706
- terminal: true,
707
- trustedSummary: eventType === "pull_request.merged" ? `${resource.label} was merged.` : `${resource.label} was closed without being merged.`
708
- });
709
- }
710
- var releaseWebhookSchema = z.object({
711
- action: z.string(),
712
- release: z.object({
713
- body: z.string().optional().nullable(),
714
- draft: z.boolean().optional(),
715
- id: z.number(),
716
- name: z.string().optional().nullable(),
717
- prerelease: z.boolean().optional(),
718
- published_at: z.string().optional().nullable(),
719
- tag_name: z.string().min(1)
720
- }).passthrough(),
721
- repository: repositorySchema
722
- }).passthrough();
723
- function releaseSourceTargets(input) {
724
- return [
725
- {
726
- completeOnTerminalEvent: true,
727
- resource: gitHubReleaseSourceResource(input)
728
- },
729
- {
730
- completeOnTerminalEvent: false,
731
- resource: gitHubReleaseSourceResource({ repo: input.repo })
732
- }
733
- ];
734
- }
735
- function normalizeReleaseEvent(deliveryId, body) {
736
- const parsed = releaseWebhookSchema.safeParse(body);
737
- if (!parsed.success || parsed.data.action !== "published") return [];
738
- if (parsed.data.release.draft) return [];
739
- const eventType = "release.published";
740
- const repo = parsed.data.repository.full_name;
741
- const tag = parsed.data.release.tag_name;
742
- const untrustedParts = [
743
- tag ? `Tag: ${tag}` : void 0,
744
- parsed.data.release.name?.trim() ? `Name: ${parsed.data.release.name.trim()}` : void 0,
745
- parsed.data.release.body?.trim() || void 0
746
- ].filter((part) => part !== void 0);
747
- const untrustedText = untrustedParts.length > 0 ? untrustedParts.join("\n\n") : void 0;
748
- return releaseSourceTargets({ repo, tag }).map(
749
- ({ completeOnTerminalEvent, resource }) => ({
750
- eventKey: gitHubEventKey(deliveryId, eventType),
751
- eventType,
752
- occurredAtMs: providerTime(parsed.data.release.published_at) ?? Date.now(),
753
- identifier: resource.identifier,
754
- ...completeOnTerminalEvent ? { terminal: true } : void 0,
755
- trustedSummary: `${resource.label} was published (release ${parsed.data.release.id}).`,
756
- ...untrustedText ? { untrustedText } : void 0
757
- })
758
- );
759
- }
760
- function parseCheckSuiteEnrichmentTarget(body) {
761
- const parsed = checkSuiteWebhookSchema.safeParse(body);
762
- if (!parsed.success || parsed.data.action !== "completed") return void 0;
763
- const conclusion = parsed.data.check_suite.conclusion;
764
- if (conclusion !== "failure" && conclusion !== "timed_out") return void 0;
765
- const headSha = parsed.data.check_suite.head_sha;
766
- const checkSuiteId = parsed.data.check_suite.id;
767
- if (typeof headSha !== "string" || !/^[0-9a-f]{7,40}$/i.test(headSha) || typeof checkSuiteId !== "number") {
768
- return void 0;
769
- }
770
- const [owner, repoName, ...extra] = parsed.data.repository.full_name.split("/");
771
- if (!owner || !repoName || extra.length > 0) return void 0;
772
- return { checkSuiteId, headSha, owner, repoName };
773
- }
774
- function normalizeGitHubResourceEvents(args) {
775
- switch (args.eventName) {
776
- case "deployment": {
777
- return normalizeDeploymentEvent(args.deliveryId, args.body);
778
- }
779
- case "deployment_status": {
780
- return normalizeDeploymentStatusEvent(args.deliveryId, args.body);
781
- }
782
- case "pull_request": {
783
- return normalizePullRequestEvent(args.deliveryId, args.body);
784
- }
785
- case "issues": {
786
- return normalizeIssueEvents(args.deliveryId, args.body);
787
- }
788
- case "pull_request_review": {
789
- return normalizePullRequestReviewEvent(args.deliveryId, args.body);
790
- }
791
- case "issue_comment": {
792
- return normalizeIssueCommentEvents(args.deliveryId, args.body);
793
- }
794
- case "pull_request_review_comment": {
795
- return normalizePullRequestReviewCommentEvent(args.deliveryId, args.body);
796
- }
797
- case "check_suite":
798
- return normalizeCheckSuiteEvents(args.deliveryId, args.body, {
799
- failingChecks: args.failingChecks
800
- });
801
- case "release":
802
- return normalizeReleaseEvent(args.deliveryId, args.body);
803
- default:
804
- return [];
805
- }
806
- }
807
-
808
- export {
809
- GITHUB_ISSUE_EVENTS,
810
- GITHUB_ISSUE_SUGGESTED_EVENTS,
811
- gitHubIssueSubscribable,
812
- GITHUB_DEPLOYMENT_EVENTS,
813
- GITHUB_DEPLOYMENT_SUGGESTED_EVENTS,
814
- gitHubDeploymentSourceSubscribable,
815
- GITHUB_PULL_REQUEST_EVENTS,
816
- GITHUB_PULL_REQUEST_SUGGESTED_EVENTS,
817
- gitHubPullRequestSubscribable,
818
- GITHUB_RELEASE_EVENTS,
819
- GITHUB_RELEASE_SUGGESTED_EVENTS,
820
- gitHubReleaseSourceSubscribable,
821
- gitHubRepositorySubscribable,
822
- selectFailingChecks,
823
- parseCheckSuiteEnrichmentTarget,
824
- normalizeGitHubResourceEvents
825
- };