@sentry/junior-github 0.234.0 → 0.236.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.
- package/README.md +9 -0
- package/dist/{chunk-XP2336UO.js → chunk-UB3DDGLH.js} +46 -7
- package/dist/index.js +86 -65
- package/dist/testing.js +1 -1
- package/dist/webhooks/events.d.ts +7 -2
- package/dist/webhooks/ownership.d.ts +2 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -25,6 +25,15 @@ export const plugins = defineJuniorPlugins([
|
|
|
25
25
|
|
|
26
26
|
Full setup guide: https://junior.sentry.dev/extend/github-plugin/
|
|
27
27
|
|
|
28
|
+
The plugin tries to assign new pull requests to the current requester's linked
|
|
29
|
+
GitHub account. Assignment is optional. Missing handles, system actors, identity
|
|
30
|
+
lookup errors, and assignment failures do not stop creation or fail the tool.
|
|
31
|
+
If assignment is not possible, the pull request can remain unassigned.
|
|
32
|
+
|
|
33
|
+
The plugin saves the created pull request before it tries assignment. Retrying
|
|
34
|
+
the same tool call returns the saved pull request without retrying assignment,
|
|
35
|
+
creating another pull request, or replacing existing assignees.
|
|
36
|
+
|
|
28
37
|
The plugin owns its signed webhook route, deployment, pull request, and release
|
|
29
38
|
events, and normalized pull request and issue outcome projections.
|
|
30
39
|
Those projections also feed native code-change records used by the dashboard
|
|
@@ -1224,6 +1224,27 @@ async function loadCheckSuiteFacts(args) {
|
|
|
1224
1224
|
return facts.failingChecks || facts.pullRequestFactsByNumber ? facts : void 0;
|
|
1225
1225
|
}
|
|
1226
1226
|
|
|
1227
|
+
// src/webhooks/ownership.ts
|
|
1228
|
+
var GITHUB_BOT_NOREPLY_EMAIL = /^(?<userId>[1-9]\d*)\+(?<login>[^@]+\[bot\])@users\.noreply\.github\.com$/i;
|
|
1229
|
+
function parseGitHubBotIdentity(value) {
|
|
1230
|
+
const match = GITHUB_BOT_NOREPLY_EMAIL.exec(value?.trim() ?? "");
|
|
1231
|
+
if (!match?.groups) return void 0;
|
|
1232
|
+
return {
|
|
1233
|
+
login: match.groups.login,
|
|
1234
|
+
userId: Number(match.groups.userId)
|
|
1235
|
+
};
|
|
1236
|
+
}
|
|
1237
|
+
function botLoginFromEmail(value) {
|
|
1238
|
+
return parseGitHubBotIdentity(value)?.login;
|
|
1239
|
+
}
|
|
1240
|
+
function isBotLogin(login, botEmail) {
|
|
1241
|
+
const botLogin = botLoginFromEmail(botEmail)?.toLowerCase();
|
|
1242
|
+
return Boolean(botLogin && login?.trim().toLowerCase() === botLogin);
|
|
1243
|
+
}
|
|
1244
|
+
function botUserIdFromEmail(value) {
|
|
1245
|
+
return parseGitHubBotIdentity(value)?.userId;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1227
1248
|
// src/webhooks/events.ts
|
|
1228
1249
|
function gitHubEventKey2(deliveryId, eventType) {
|
|
1229
1250
|
return `github:${deliveryId}:${eventType}`;
|
|
@@ -1403,14 +1424,15 @@ var issueCommentWebhookSchema = z2.object({
|
|
|
1403
1424
|
}),
|
|
1404
1425
|
repository: repositorySchema2
|
|
1405
1426
|
});
|
|
1406
|
-
function normalizeIssueCommentEvents(deliveryId, body) {
|
|
1427
|
+
function normalizeIssueCommentEvents(deliveryId, body, botEmail) {
|
|
1407
1428
|
const parsed = issueCommentWebhookSchema.safeParse(body);
|
|
1408
1429
|
if (!parsed.success || parsed.data.action !== "created") return [];
|
|
1430
|
+
const author = parsed.data.comment.user?.login;
|
|
1431
|
+
if (isBotLogin(author, botEmail)) return [];
|
|
1409
1432
|
const input = {
|
|
1410
1433
|
number: parsed.data.issue.number,
|
|
1411
1434
|
repo: parsed.data.repository.full_name
|
|
1412
1435
|
};
|
|
1413
|
-
const author = parsed.data.comment.user?.login;
|
|
1414
1436
|
if (parsed.data.issue.pull_request) {
|
|
1415
1437
|
const eventType = "pull_request.comment.created";
|
|
1416
1438
|
const resource = gitHubPullRequestResource(input);
|
|
@@ -1531,9 +1553,10 @@ var pullRequestReviewCommentWebhookSchema = z2.object({
|
|
|
1531
1553
|
}),
|
|
1532
1554
|
repository: repositorySchema2
|
|
1533
1555
|
});
|
|
1534
|
-
function normalizePullRequestReviewCommentEvent(deliveryId, body) {
|
|
1556
|
+
function normalizePullRequestReviewCommentEvent(deliveryId, body, botEmail) {
|
|
1535
1557
|
const parsed = pullRequestReviewCommentWebhookSchema.safeParse(body);
|
|
1536
1558
|
if (!parsed.success || parsed.data.action !== "created") return [];
|
|
1559
|
+
if (isBotLogin(parsed.data.comment.user?.login, botEmail)) return [];
|
|
1537
1560
|
const eventType = "pull_request.review_comment.created";
|
|
1538
1561
|
const repo = parsed.data.repository.full_name;
|
|
1539
1562
|
const resource = gitHubPullRequestResource({
|
|
@@ -1585,9 +1608,10 @@ var pullRequestReviewWebhookSchema = z2.object({
|
|
|
1585
1608
|
user: z2.object({ login: z2.string().optional() }).optional()
|
|
1586
1609
|
})
|
|
1587
1610
|
});
|
|
1588
|
-
function normalizePullRequestReviewEvent(deliveryId, body) {
|
|
1611
|
+
function normalizePullRequestReviewEvent(deliveryId, body, botEmail) {
|
|
1589
1612
|
const parsed = pullRequestReviewWebhookSchema.safeParse(body);
|
|
1590
1613
|
if (!parsed.success || parsed.data.action !== "submitted") return [];
|
|
1614
|
+
if (isBotLogin(parsed.data.review.user?.login, botEmail)) return [];
|
|
1591
1615
|
const reviewState = parsed.data.review.state.toUpperCase();
|
|
1592
1616
|
const eventType = reviewState === "APPROVED" ? "pull_request.review.approved" : reviewState === "CHANGES_REQUESTED" ? "pull_request.review.changes_requested" : reviewState === "COMMENTED" ? "pull_request.review.commented" : void 0;
|
|
1593
1617
|
if (!eventType) return [];
|
|
@@ -1811,11 +1835,23 @@ function normalizeGitHubEvents(args) {
|
|
|
1811
1835
|
case "issues":
|
|
1812
1836
|
return normalizeIssueEvents(args.deliveryId, args.body);
|
|
1813
1837
|
case "pull_request_review":
|
|
1814
|
-
return normalizePullRequestReviewEvent(
|
|
1838
|
+
return normalizePullRequestReviewEvent(
|
|
1839
|
+
args.deliveryId,
|
|
1840
|
+
args.body,
|
|
1841
|
+
args.botEmail
|
|
1842
|
+
);
|
|
1815
1843
|
case "issue_comment":
|
|
1816
|
-
return normalizeIssueCommentEvents(
|
|
1844
|
+
return normalizeIssueCommentEvents(
|
|
1845
|
+
args.deliveryId,
|
|
1846
|
+
args.body,
|
|
1847
|
+
args.botEmail
|
|
1848
|
+
);
|
|
1817
1849
|
case "pull_request_review_comment":
|
|
1818
|
-
return normalizePullRequestReviewCommentEvent(
|
|
1850
|
+
return normalizePullRequestReviewCommentEvent(
|
|
1851
|
+
args.deliveryId,
|
|
1852
|
+
args.body,
|
|
1853
|
+
args.botEmail
|
|
1854
|
+
);
|
|
1819
1855
|
case "check_suite":
|
|
1820
1856
|
return normalizeCheckSuiteEvents(
|
|
1821
1857
|
args.deliveryId,
|
|
@@ -1847,6 +1883,9 @@ export {
|
|
|
1847
1883
|
GITHUB_RELEASE_SUGGESTED_EVENTS,
|
|
1848
1884
|
gitHubReleaseSourceSubscribable,
|
|
1849
1885
|
gitHubRepositorySubscribable,
|
|
1886
|
+
botLoginFromEmail,
|
|
1887
|
+
isBotLogin,
|
|
1888
|
+
botUserIdFromEmail,
|
|
1850
1889
|
GITHUB_APP_ID_ENV,
|
|
1851
1890
|
GITHUB_APP_PRIVATE_KEY_ENV,
|
|
1852
1891
|
GITHUB_INSTALLATION_ID_ENV,
|
package/dist/index.js
CHANGED
|
@@ -19,6 +19,8 @@ import {
|
|
|
19
19
|
HTTP_READ_METHODS,
|
|
20
20
|
USER_TOKEN_GRANTS,
|
|
21
21
|
USER_WRITE_REQUIREMENTS,
|
|
22
|
+
botLoginFromEmail,
|
|
23
|
+
botUserIdFromEmail,
|
|
22
24
|
createPermissionCache,
|
|
23
25
|
credentialUnavailable,
|
|
24
26
|
gitHubDeploymentSourceSubscribable,
|
|
@@ -29,6 +31,7 @@ import {
|
|
|
29
31
|
gitHubRepositorySubscribable,
|
|
30
32
|
githubRepositoryFromUrl,
|
|
31
33
|
githubRequest,
|
|
34
|
+
isBotLogin,
|
|
32
35
|
isRecord,
|
|
33
36
|
issueInstallationCredential,
|
|
34
37
|
issueInstallationToken,
|
|
@@ -43,7 +46,7 @@ import {
|
|
|
43
46
|
readGrantPermissions,
|
|
44
47
|
requireEnv,
|
|
45
48
|
resolveUserAccount
|
|
46
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-UB3DDGLH.js";
|
|
47
50
|
|
|
48
51
|
// src/plugin.ts
|
|
49
52
|
import {
|
|
@@ -1353,6 +1356,44 @@ async function createGitHubPullRequest(ctx, request) {
|
|
|
1353
1356
|
url: pullRequest.html_url
|
|
1354
1357
|
};
|
|
1355
1358
|
}
|
|
1359
|
+
async function assignPullRequestRequester(ctx, input, result) {
|
|
1360
|
+
if (!ctx.actor || ctx.actor.platform === "system") return;
|
|
1361
|
+
try {
|
|
1362
|
+
const requester = await ctx.users.resolveActor();
|
|
1363
|
+
const assignee = requester?.user?.identities.find((identity) => identity.provider === "github")?.handle?.trim();
|
|
1364
|
+
if (!assignee) return;
|
|
1365
|
+
const repo = parseRepo4(input.repo);
|
|
1366
|
+
const response = await ctx.egress.fetch({
|
|
1367
|
+
provider: "github",
|
|
1368
|
+
operation: "github.pull.assign",
|
|
1369
|
+
request: new Request(
|
|
1370
|
+
`https://api.github.com/repos/${encodeURIComponent(repo.owner)}/${encodeURIComponent(repo.name)}/issues/${result.number}/assignees`,
|
|
1371
|
+
{
|
|
1372
|
+
method: "POST",
|
|
1373
|
+
headers: {
|
|
1374
|
+
Accept: "application/vnd.github+json",
|
|
1375
|
+
"Content-Type": "application/json",
|
|
1376
|
+
"X-GitHub-Api-Version": "2022-11-28"
|
|
1377
|
+
},
|
|
1378
|
+
body: JSON.stringify({ assignees: [assignee] })
|
|
1379
|
+
}
|
|
1380
|
+
)
|
|
1381
|
+
});
|
|
1382
|
+
if (!response.ok) {
|
|
1383
|
+
ctx.log.warn("github.pull_request.assign_after_create.rejected", {
|
|
1384
|
+
number: result.number,
|
|
1385
|
+
repo: input.repo,
|
|
1386
|
+
status: response.status
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
} catch (error) {
|
|
1390
|
+
ctx.log.warn("github.pull_request.assign_after_create.failed", {
|
|
1391
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1392
|
+
number: result.number,
|
|
1393
|
+
repo: input.repo
|
|
1394
|
+
});
|
|
1395
|
+
}
|
|
1396
|
+
}
|
|
1356
1397
|
function gitHubPullRequestToolResult(input, result, canSubscribe, omitSuggestedEvents) {
|
|
1357
1398
|
const repo = parseRepo4(input.repo);
|
|
1358
1399
|
const subscribable = canSubscribe ? gitHubPullRequestSubscribable({
|
|
@@ -1431,7 +1472,7 @@ function createGitHubPullRequestTool(ctx, subscriptionConfig) {
|
|
|
1431
1472
|
openWorldHint: true,
|
|
1432
1473
|
readOnlyHint: false
|
|
1433
1474
|
},
|
|
1434
|
-
description: "Create a GitHub pull request with a runtime-owned conversation footer. Use this instead of shelling out to gh pr create when creating pull requests.",
|
|
1475
|
+
description: "Create a GitHub pull request with a runtime-owned conversation footer and assign it to the requester's linked GitHub account when available. Use this instead of shelling out to gh pr create when creating pull requests.",
|
|
1435
1476
|
exposure: "direct",
|
|
1436
1477
|
inputSchema: createPullRequestToolInputSchema,
|
|
1437
1478
|
outputSchema: gitHubPullRequestOutputSchema,
|
|
@@ -1485,33 +1526,39 @@ function createGitHubPullRequestTool(ctx, subscriptionConfig) {
|
|
|
1485
1526
|
pendingState,
|
|
1486
1527
|
GITHUB_PULL_REQUEST_CREATE_IDEMPOTENCY_TTL_MS
|
|
1487
1528
|
);
|
|
1529
|
+
let result;
|
|
1488
1530
|
try {
|
|
1489
|
-
|
|
1490
|
-
Object.assign(pendingState, { status: "completed", ...result });
|
|
1491
|
-
try {
|
|
1492
|
-
await ctx.state.set(
|
|
1493
|
-
key,
|
|
1494
|
-
pendingState,
|
|
1495
|
-
GITHUB_PULL_REQUEST_CREATE_IDEMPOTENCY_TTL_MS
|
|
1496
|
-
);
|
|
1497
|
-
} catch (error) {
|
|
1498
|
-
throw new Error(
|
|
1499
|
-
"GitHub pull request was created, but the runtime could not persist the completed pull request state.",
|
|
1500
|
-
{ cause: error }
|
|
1501
|
-
);
|
|
1502
|
-
}
|
|
1503
|
-
return await gitHubPullRequestStructuredResult(
|
|
1504
|
-
ctx,
|
|
1505
|
-
parsedInput,
|
|
1506
|
-
result,
|
|
1507
|
-
subscriptionConfig
|
|
1508
|
-
);
|
|
1531
|
+
result = await createGitHubPullRequest(ctx, request);
|
|
1509
1532
|
} catch (error) {
|
|
1510
1533
|
if (isEgressAuthRequired2(error) || isDefinitiveGitHubPullRequestCreateRejection(error)) {
|
|
1511
1534
|
await ctx.state.delete(key);
|
|
1512
1535
|
}
|
|
1513
1536
|
throw error;
|
|
1514
1537
|
}
|
|
1538
|
+
const completedState = {
|
|
1539
|
+
...pendingState,
|
|
1540
|
+
status: "completed",
|
|
1541
|
+
...result
|
|
1542
|
+
};
|
|
1543
|
+
try {
|
|
1544
|
+
await ctx.state.set(
|
|
1545
|
+
key,
|
|
1546
|
+
completedState,
|
|
1547
|
+
GITHUB_PULL_REQUEST_CREATE_IDEMPOTENCY_TTL_MS
|
|
1548
|
+
);
|
|
1549
|
+
} catch (error) {
|
|
1550
|
+
throw new Error(
|
|
1551
|
+
"GitHub pull request was created, but the runtime could not persist the completed pull request state.",
|
|
1552
|
+
{ cause: error }
|
|
1553
|
+
);
|
|
1554
|
+
}
|
|
1555
|
+
await assignPullRequestRequester(ctx, parsedInput, result);
|
|
1556
|
+
return await gitHubPullRequestStructuredResult(
|
|
1557
|
+
ctx,
|
|
1558
|
+
parsedInput,
|
|
1559
|
+
result,
|
|
1560
|
+
subscriptionConfig
|
|
1561
|
+
);
|
|
1515
1562
|
}
|
|
1516
1563
|
);
|
|
1517
1564
|
}
|
|
@@ -2217,25 +2264,6 @@ import {
|
|
|
2217
2264
|
pluginToolOutputSchema as pluginToolOutputSchema10
|
|
2218
2265
|
} from "@sentry/junior-plugin-api";
|
|
2219
2266
|
import { z as z11 } from "zod";
|
|
2220
|
-
|
|
2221
|
-
// src/webhooks/ownership.ts
|
|
2222
|
-
var GITHUB_BOT_NOREPLY_EMAIL = /^(?<userId>[1-9]\d*)\+(?<login>[^@]+\[bot\])@users\.noreply\.github\.com$/i;
|
|
2223
|
-
function parseGitHubBotIdentity(value) {
|
|
2224
|
-
const match = GITHUB_BOT_NOREPLY_EMAIL.exec(value?.trim() ?? "");
|
|
2225
|
-
if (!match?.groups) return void 0;
|
|
2226
|
-
return {
|
|
2227
|
-
login: match.groups.login,
|
|
2228
|
-
userId: Number(match.groups.userId)
|
|
2229
|
-
};
|
|
2230
|
-
}
|
|
2231
|
-
function botLoginFromEmail(value) {
|
|
2232
|
-
return parseGitHubBotIdentity(value)?.login;
|
|
2233
|
-
}
|
|
2234
|
-
function botUserIdFromEmail(value) {
|
|
2235
|
-
return parseGitHubBotIdentity(value)?.userId;
|
|
2236
|
-
}
|
|
2237
|
-
|
|
2238
|
-
// src/tools/update-pull-request-feedback.ts
|
|
2239
2267
|
var STATUS_TO_REACTION_CONTENT = {
|
|
2240
2268
|
reviewing: "eyes",
|
|
2241
2269
|
addressed: "+1",
|
|
@@ -3184,15 +3212,13 @@ function normalizeGitHubIssueOutcome(args) {
|
|
|
3184
3212
|
if (!openedAt || !updatedAt) {
|
|
3185
3213
|
throw new Error("GitHub issue lifecycle timestamps are invalid");
|
|
3186
3214
|
}
|
|
3187
|
-
|
|
3188
|
-
const botLogin = botLoginFromEmail(args.botEmail)?.toLowerCase();
|
|
3189
|
-
if (parsed.action === "opened" && !botLogin) {
|
|
3215
|
+
if (parsed.action === "opened" && !botLoginFromEmail(args.botEmail)) {
|
|
3190
3216
|
throw new Error(
|
|
3191
3217
|
"The configured GitHub App bot email must encode a [bot] login in GitHub's noreply format to classify issue ownership"
|
|
3192
3218
|
);
|
|
3193
3219
|
}
|
|
3194
3220
|
const hasOwnershipMarker = Boolean(
|
|
3195
|
-
|
|
3221
|
+
isBotLogin(issue.user.login, args.botEmail) && issue.body?.includes(GITHUB_SESSION_FOOTER_START)
|
|
3196
3222
|
);
|
|
3197
3223
|
const candidateOwned = hasOwnershipMarker && (parsed.action === "opened" || parsed.action === "closed");
|
|
3198
3224
|
const closedAt = timestamp2(issue.closed_at);
|
|
@@ -3239,12 +3265,12 @@ var issueConversationSchema = z17.object({
|
|
|
3239
3265
|
);
|
|
3240
3266
|
function normalizeGitHubIssueConversations(args) {
|
|
3241
3267
|
const parsed = issueConversationSchema.safeParse(args.body);
|
|
3242
|
-
|
|
3243
|
-
if (!parsed.
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
const
|
|
3247
|
-
if (
|
|
3268
|
+
if (!parsed.success) return void 0;
|
|
3269
|
+
if (!isBotLogin(parsed.data.issue.user.login, args.botEmail)) {
|
|
3270
|
+
return void 0;
|
|
3271
|
+
}
|
|
3272
|
+
const sender = parsed.data.sender;
|
|
3273
|
+
if (sender && !isBotLogin(sender.login, args.botEmail)) return void 0;
|
|
3248
3274
|
const conversationIds = githubConversationIds(parsed.data.issue.body);
|
|
3249
3275
|
return conversationIds.length > 0 ? {
|
|
3250
3276
|
conversationIds,
|
|
@@ -3358,15 +3384,13 @@ function normalizeGitHubPullRequestOutcome(args) {
|
|
|
3358
3384
|
if (!openedAt || !updatedAt) {
|
|
3359
3385
|
throw new Error("GitHub pull request lifecycle timestamps are invalid");
|
|
3360
3386
|
}
|
|
3361
|
-
|
|
3362
|
-
const botLogin = botLoginFromEmail(args.botEmail)?.toLowerCase();
|
|
3363
|
-
if (parsed.action === "opened" && !botLogin) {
|
|
3387
|
+
if (parsed.action === "opened" && !botLoginFromEmail(args.botEmail)) {
|
|
3364
3388
|
throw new Error(
|
|
3365
3389
|
"The configured GitHub App bot email must encode a [bot] login in GitHub's noreply format to classify pull request ownership"
|
|
3366
3390
|
);
|
|
3367
3391
|
}
|
|
3368
3392
|
const hasOwnershipMarker = Boolean(
|
|
3369
|
-
|
|
3393
|
+
isBotLogin(pullRequest.user.login, args.botEmail) && pullRequest.body?.includes(GITHUB_SESSION_FOOTER_START)
|
|
3370
3394
|
);
|
|
3371
3395
|
const candidateOwned = hasOwnershipMarker && (parsed.action === "opened" || parsed.action === "closed");
|
|
3372
3396
|
const state = parsed.action !== "closed" ? "open" : pullRequest.merged ? "merged" : "closed_unmerged";
|
|
@@ -3391,9 +3415,8 @@ function normalizeGitHubPullRequestOutcome(args) {
|
|
|
3391
3415
|
}
|
|
3392
3416
|
function normalizeGitHubPullRequestConversations(args) {
|
|
3393
3417
|
const parsed = pullRequestConversationSchema.safeParse(args.body);
|
|
3394
|
-
|
|
3395
|
-
if (!parsed.
|
|
3396
|
-
if (parsed.data.pull_request.user.login.trim().toLowerCase() !== botLogin || parsed.data.sender.login.trim().toLowerCase() !== botLogin) {
|
|
3418
|
+
if (!parsed.success) return void 0;
|
|
3419
|
+
if (!isBotLogin(parsed.data.pull_request.user.login, args.botEmail) || !isBotLogin(parsed.data.sender.login, args.botEmail)) {
|
|
3397
3420
|
return void 0;
|
|
3398
3421
|
}
|
|
3399
3422
|
const conversationIds = githubConversationIds(parsed.data.pull_request.body);
|
|
@@ -3404,9 +3427,8 @@ function normalizeGitHubPullRequestConversations(args) {
|
|
|
3404
3427
|
}
|
|
3405
3428
|
function normalizeGitHubPullRequestLinkedIssues(args) {
|
|
3406
3429
|
const parsed = pullRequestConversationSchema.safeParse(args.body);
|
|
3407
|
-
|
|
3408
|
-
if (!parsed.
|
|
3409
|
-
if (parsed.data.pull_request.user.login.trim().toLowerCase() !== botLogin || parsed.data.sender.login.trim().toLowerCase() !== botLogin) {
|
|
3430
|
+
if (!parsed.success) return void 0;
|
|
3431
|
+
if (!isBotLogin(parsed.data.pull_request.user.login, args.botEmail) || !isBotLogin(parsed.data.sender.login, args.botEmail)) {
|
|
3410
3432
|
return void 0;
|
|
3411
3433
|
}
|
|
3412
3434
|
const linkedIssues = githubLinkedIssues(
|
|
@@ -3613,6 +3635,7 @@ function createGitHubWebhookRoute(args) {
|
|
|
3613
3635
|
}) : void 0;
|
|
3614
3636
|
const events = normalizeGitHubEvents({
|
|
3615
3637
|
body,
|
|
3638
|
+
botEmail,
|
|
3616
3639
|
...checkSuiteFacts ? { checkSuiteFacts } : void 0,
|
|
3617
3640
|
deliveryId,
|
|
3618
3641
|
eventName
|
|
@@ -3673,8 +3696,7 @@ var MAX_PAGES = 3;
|
|
|
3673
3696
|
var MAX_LISTED_COMMITS = 250;
|
|
3674
3697
|
async function classifyGitHubPullRequestCommitComposition(args) {
|
|
3675
3698
|
const botEmail = args.botEmail.trim().toLowerCase();
|
|
3676
|
-
|
|
3677
|
-
if (!botEmail || !botLogin) {
|
|
3699
|
+
if (!botEmail || !botLoginFromEmail(botEmail)) {
|
|
3678
3700
|
throw new Error(
|
|
3679
3701
|
"The configured GitHub App bot email cannot classify pull request commits"
|
|
3680
3702
|
);
|
|
@@ -3688,9 +3710,8 @@ async function classifyGitHubPullRequestCommitComposition(args) {
|
|
|
3688
3710
|
inspectedCommits += commits.length;
|
|
3689
3711
|
for (const commit of commits) {
|
|
3690
3712
|
foundCommit = true;
|
|
3691
|
-
const authorLogin = commit.authorLogin?.trim().toLowerCase();
|
|
3692
3713
|
const authorEmail = commit.authorEmail?.trim().toLowerCase();
|
|
3693
|
-
if (authorLogin
|
|
3714
|
+
if (!isBotLogin(commit.authorLogin, botEmail) && authorEmail !== botEmail) {
|
|
3694
3715
|
return "mixed";
|
|
3695
3716
|
}
|
|
3696
3717
|
}
|
package/dist/testing.js
CHANGED
|
@@ -2,10 +2,15 @@ import type { EventInput } from "@sentry/junior-plugin-api";
|
|
|
2
2
|
import { type GitHubCheckSuiteFacts } from "./check-suite.js";
|
|
3
3
|
export type { GitHubCheckSuiteFacts, GitHubCheckSuitePullRequestFacts, GitHubFailingCheck, } from "./check-suite.js";
|
|
4
4
|
export { buildCheckSuiteEvent, buildCheckSuiteUrl, loadCheckSuiteFacts, needsCheckSuitePullRequestFacts, parseCheckSuiteFactsTarget, parseCheckSuitePublishTargets, selectFailingChecks, } from "./check-suite.js";
|
|
5
|
-
/**
|
|
6
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Normalize one verified GitHub delivery into conversation events.
|
|
7
|
+
*
|
|
8
|
+
* Comments and reviews written by the configured bot are dropped, so Junior
|
|
9
|
+
* does not react to or act on its own feedback.
|
|
10
|
+
*/
|
|
7
11
|
export declare function normalizeGitHubEvents(args: {
|
|
8
12
|
body: unknown;
|
|
13
|
+
botEmail?: string;
|
|
9
14
|
checkSuiteFacts?: GitHubCheckSuiteFacts;
|
|
10
15
|
deliveryId: string;
|
|
11
16
|
eventName: string;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/** Derive the provider login encoded in a standard GitHub noreply address. */
|
|
2
2
|
export declare function botLoginFromEmail(value: string | undefined): string | undefined;
|
|
3
|
+
/** Check whether a GitHub login is the bot encoded in the configured bot email. */
|
|
4
|
+
export declare function isBotLogin(login: string | null | undefined, botEmail: string | undefined): boolean;
|
|
3
5
|
/** Derive the GitHub user id encoded in a standard GitHub noreply address. */
|
|
4
6
|
export declare function botUserIdFromEmail(value: string | undefined): number | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/junior-github",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.236.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"@sinclair/typebox": "^0.34.49",
|
|
32
32
|
"drizzle-orm": "^0.45.2",
|
|
33
33
|
"zod": "^4.5.4",
|
|
34
|
-
"@sentry/junior-plugin-api": "0.
|
|
34
|
+
"@sentry/junior-plugin-api": "0.236.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@oxlint/plugins": "1.79.0",
|