@render-harness/cap-github 0.2.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/dist/index.d.ts +5 -0
- package/dist/index.js +570 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,570 @@
|
|
|
1
|
+
import { createHash, createHmac, timingSafeEqual } from 'crypto';
|
|
2
|
+
import { definePack } from '@render-harness/registry';
|
|
3
|
+
import { Octokit } from '@octokit/rest';
|
|
4
|
+
|
|
5
|
+
// src/index.ts
|
|
6
|
+
|
|
7
|
+
// src/normalize.ts
|
|
8
|
+
var SUPPORTED_EVENTS = /* @__PURE__ */ new Set([
|
|
9
|
+
"issues",
|
|
10
|
+
"issue_comment",
|
|
11
|
+
"pull_request",
|
|
12
|
+
"pull_request_review",
|
|
13
|
+
"pull_request_review_comment",
|
|
14
|
+
"push",
|
|
15
|
+
"check_run",
|
|
16
|
+
"check_suite",
|
|
17
|
+
"workflow_run"
|
|
18
|
+
]);
|
|
19
|
+
function normalizeGitHubEvent(event, body, cfg = {}) {
|
|
20
|
+
if (!SUPPORTED_EVENTS.has(event)) return null;
|
|
21
|
+
if (cfg.events?.length && !cfg.events.includes(event)) return null;
|
|
22
|
+
if (!body || typeof body !== "object") return null;
|
|
23
|
+
const payload = body;
|
|
24
|
+
const repo = stringAt(payload, "repository.full_name");
|
|
25
|
+
if (!repo) return null;
|
|
26
|
+
if (cfg.allowedRepositories?.length && !cfg.allowedRepositories.includes(repo)) return null;
|
|
27
|
+
const actor = stringAt(payload, "sender.login");
|
|
28
|
+
if (actor && cfg.ignoredActors?.includes(actor)) return null;
|
|
29
|
+
const branch = branchFor(event, payload);
|
|
30
|
+
if (cfg.branches?.length && branch && !cfg.branches.includes(branch)) return null;
|
|
31
|
+
if (cfg.labels?.length && !hasAllowedLabel(payload, cfg.labels)) return null;
|
|
32
|
+
const action = stringValue(payload.action);
|
|
33
|
+
const normalized = buildNormalized(event, payload, repo, actor, action, branch);
|
|
34
|
+
return normalized;
|
|
35
|
+
}
|
|
36
|
+
function buildNormalized(event, payload, repo, actor, action, branch) {
|
|
37
|
+
if (event === "issues") {
|
|
38
|
+
const number = numberAt(payload, "issue.number");
|
|
39
|
+
const url2 = stringAt(payload, "issue.html_url");
|
|
40
|
+
return {
|
|
41
|
+
event,
|
|
42
|
+
...action ? { action } : {},
|
|
43
|
+
repo,
|
|
44
|
+
...actor ? { actor } : {},
|
|
45
|
+
objectType: "issue",
|
|
46
|
+
...number !== void 0 ? { objectId: number } : {},
|
|
47
|
+
...number !== void 0 ? { number } : {},
|
|
48
|
+
...url2 ? { url: url2 } : {},
|
|
49
|
+
summary: `GitHub issue ${repo}#${number ?? "unknown"} ${action ?? "changed"}`
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (event === "pull_request") {
|
|
53
|
+
const number = numberAt(payload, "pull_request.number");
|
|
54
|
+
const url2 = stringAt(payload, "pull_request.html_url");
|
|
55
|
+
return {
|
|
56
|
+
event,
|
|
57
|
+
...action ? { action } : {},
|
|
58
|
+
repo,
|
|
59
|
+
...actor ? { actor } : {},
|
|
60
|
+
objectType: "pull_request",
|
|
61
|
+
...number !== void 0 ? { objectId: number } : {},
|
|
62
|
+
...number !== void 0 ? { number } : {},
|
|
63
|
+
...branch ? { branch } : {},
|
|
64
|
+
...url2 ? { url: url2 } : {},
|
|
65
|
+
summary: `GitHub PR ${repo}#${number ?? "unknown"} ${action ?? "changed"}`
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
if (event === "push") {
|
|
69
|
+
const objectId2 = stringAt(payload, "after");
|
|
70
|
+
const url2 = stringAt(payload, "compare");
|
|
71
|
+
return {
|
|
72
|
+
event,
|
|
73
|
+
repo,
|
|
74
|
+
...actor ? { actor } : {},
|
|
75
|
+
objectType: "push",
|
|
76
|
+
...objectId2 ? { objectId: objectId2 } : {},
|
|
77
|
+
...branch ? { branch } : {},
|
|
78
|
+
...url2 ? { url: url2 } : {},
|
|
79
|
+
summary: `GitHub push to ${repo}${branch ? `:${branch}` : ""}`
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
const objectType = event.replace(/_/g, "-");
|
|
83
|
+
const objectId = stringAt(payload, `${event}.id`) ?? numberAt(payload, `${event}.id`) ?? stringAt(payload, "check_run.id") ?? numberAt(payload, "check_run.id");
|
|
84
|
+
const url = stringAt(payload, `${event}.html_url`) ?? stringAt(payload, `${event}.url`);
|
|
85
|
+
return {
|
|
86
|
+
event,
|
|
87
|
+
...action ? { action } : {},
|
|
88
|
+
repo,
|
|
89
|
+
...actor ? { actor } : {},
|
|
90
|
+
objectType,
|
|
91
|
+
...objectId !== void 0 ? { objectId } : {},
|
|
92
|
+
...branch ? { branch } : {},
|
|
93
|
+
...url ? { url } : {},
|
|
94
|
+
summary: `GitHub ${objectType} event for ${repo}`
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
function branchFor(event, payload) {
|
|
98
|
+
if (event === "push") {
|
|
99
|
+
const ref = stringValue(payload.ref);
|
|
100
|
+
return ref?.startsWith("refs/heads/") ? ref.slice("refs/heads/".length) : ref;
|
|
101
|
+
}
|
|
102
|
+
return stringAt(payload, "pull_request.head.ref") ?? stringAt(payload, "workflow_run.head_branch");
|
|
103
|
+
}
|
|
104
|
+
function hasAllowedLabel(payload, allowed) {
|
|
105
|
+
const issueLabels = arrayAt(payload, "issue.labels");
|
|
106
|
+
const prLabels = arrayAt(payload, "pull_request.labels");
|
|
107
|
+
const labels = [...issueLabels, ...prLabels].map(
|
|
108
|
+
(label) => label && typeof label === "object" ? stringValue(label.name) : null
|
|
109
|
+
).filter((label) => !!label);
|
|
110
|
+
return labels.some((label) => allowed.includes(label));
|
|
111
|
+
}
|
|
112
|
+
function stringAt(value, path) {
|
|
113
|
+
return stringValue(readPath(value, path));
|
|
114
|
+
}
|
|
115
|
+
function numberAt(value, path) {
|
|
116
|
+
const found = readPath(value, path);
|
|
117
|
+
return typeof found === "number" ? found : void 0;
|
|
118
|
+
}
|
|
119
|
+
function arrayAt(value, path) {
|
|
120
|
+
const found = readPath(value, path);
|
|
121
|
+
return Array.isArray(found) ? found : [];
|
|
122
|
+
}
|
|
123
|
+
function readPath(value, path) {
|
|
124
|
+
let cursor = value;
|
|
125
|
+
for (const part of path.split(".")) {
|
|
126
|
+
if (!cursor || typeof cursor !== "object") return void 0;
|
|
127
|
+
cursor = cursor[part];
|
|
128
|
+
}
|
|
129
|
+
return cursor;
|
|
130
|
+
}
|
|
131
|
+
function stringValue(value) {
|
|
132
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
133
|
+
}
|
|
134
|
+
function githubTools(args) {
|
|
135
|
+
const octokit = new Octokit({ auth: args.token });
|
|
136
|
+
const tools = [
|
|
137
|
+
jsonTool("github.get_issue", "Read a GitHub issue.", issueSchema(), async (input) => {
|
|
138
|
+
const { owner, repo, issue_number } = input;
|
|
139
|
+
return octokit.rest.issues.get({ owner, repo, issue_number });
|
|
140
|
+
}),
|
|
141
|
+
jsonTool(
|
|
142
|
+
"github.get_pull_request",
|
|
143
|
+
"Read a GitHub pull request.",
|
|
144
|
+
prSchema(),
|
|
145
|
+
async (input) => {
|
|
146
|
+
const { owner, repo, pull_number } = input;
|
|
147
|
+
return octokit.rest.pulls.get({ owner, repo, pull_number });
|
|
148
|
+
}
|
|
149
|
+
),
|
|
150
|
+
jsonTool(
|
|
151
|
+
"github.list_pull_request_files",
|
|
152
|
+
"List files changed by a GitHub pull request.",
|
|
153
|
+
prSchema(),
|
|
154
|
+
async (input) => {
|
|
155
|
+
const { owner, repo, pull_number } = input;
|
|
156
|
+
return octokit.paginate(octokit.rest.pulls.listFiles, { owner, repo, pull_number });
|
|
157
|
+
}
|
|
158
|
+
),
|
|
159
|
+
jsonTool(
|
|
160
|
+
"github.list_pull_request_reviews",
|
|
161
|
+
"List reviews on a GitHub pull request.",
|
|
162
|
+
prSchema(),
|
|
163
|
+
async (input) => {
|
|
164
|
+
const { owner, repo, pull_number } = input;
|
|
165
|
+
return octokit.paginate(octokit.rest.pulls.listReviews, { owner, repo, pull_number });
|
|
166
|
+
}
|
|
167
|
+
),
|
|
168
|
+
jsonTool(
|
|
169
|
+
"github.list_pull_request_commits",
|
|
170
|
+
"List commits on a GitHub pull request.",
|
|
171
|
+
prSchema(),
|
|
172
|
+
async (input) => {
|
|
173
|
+
const { owner, repo, pull_number } = input;
|
|
174
|
+
return octokit.paginate(octokit.rest.pulls.listCommits, { owner, repo, pull_number });
|
|
175
|
+
}
|
|
176
|
+
),
|
|
177
|
+
jsonTool(
|
|
178
|
+
"github.list_issue_comments",
|
|
179
|
+
"List comments on a GitHub issue or pull request.",
|
|
180
|
+
issueSchema(),
|
|
181
|
+
async (input) => {
|
|
182
|
+
const { owner, repo, issue_number } = input;
|
|
183
|
+
return octokit.paginate(octokit.rest.issues.listComments, { owner, repo, issue_number });
|
|
184
|
+
}
|
|
185
|
+
),
|
|
186
|
+
jsonTool(
|
|
187
|
+
"github.get_content",
|
|
188
|
+
"Read a file or directory listing from a GitHub repository.",
|
|
189
|
+
contentSchema(),
|
|
190
|
+
async (input) => {
|
|
191
|
+
const { owner, repo, path, ref } = input;
|
|
192
|
+
return octokit.rest.repos.getContent({
|
|
193
|
+
owner,
|
|
194
|
+
repo,
|
|
195
|
+
path,
|
|
196
|
+
...ref ? { ref } : {}
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
),
|
|
200
|
+
jsonTool(
|
|
201
|
+
"github.list_checks",
|
|
202
|
+
"List check runs for a GitHub ref.",
|
|
203
|
+
refSchema(),
|
|
204
|
+
async (input) => {
|
|
205
|
+
const { owner, repo, ref } = input;
|
|
206
|
+
return octokit.rest.checks.listForRef({ owner, repo, ref });
|
|
207
|
+
}
|
|
208
|
+
),
|
|
209
|
+
jsonTool(
|
|
210
|
+
"github.list_workflow_runs",
|
|
211
|
+
"List GitHub Actions workflow runs.",
|
|
212
|
+
repoSchema(),
|
|
213
|
+
async (input) => {
|
|
214
|
+
const { owner, repo } = input;
|
|
215
|
+
return octokit.rest.actions.listWorkflowRunsForRepo({ owner, repo });
|
|
216
|
+
}
|
|
217
|
+
),
|
|
218
|
+
jsonTool(
|
|
219
|
+
"github.get_workflow_run",
|
|
220
|
+
"Read one GitHub Actions workflow run.",
|
|
221
|
+
workflowRunSchema(),
|
|
222
|
+
async (input) => {
|
|
223
|
+
const { owner, repo, run_id } = input;
|
|
224
|
+
return octokit.rest.actions.getWorkflowRun({ owner, repo, run_id });
|
|
225
|
+
}
|
|
226
|
+
),
|
|
227
|
+
jsonTool(
|
|
228
|
+
"github.list_workflow_run_jobs",
|
|
229
|
+
"List jobs for a GitHub Actions workflow run.",
|
|
230
|
+
workflowRunSchema(),
|
|
231
|
+
async (input) => {
|
|
232
|
+
const { owner, repo, run_id } = input;
|
|
233
|
+
return octokit.rest.actions.listJobsForWorkflowRun({ owner, repo, run_id });
|
|
234
|
+
}
|
|
235
|
+
)
|
|
236
|
+
];
|
|
237
|
+
if (args.accessMode === "read_write") {
|
|
238
|
+
tools.push(
|
|
239
|
+
jsonTool(
|
|
240
|
+
"github.create_issue_comment",
|
|
241
|
+
"Create a comment on a GitHub issue or pull request.",
|
|
242
|
+
issueCommentSchema(),
|
|
243
|
+
async (input) => {
|
|
244
|
+
const { owner, repo, issue_number, body } = input;
|
|
245
|
+
return octokit.rest.issues.createComment({ owner, repo, issue_number, body });
|
|
246
|
+
}
|
|
247
|
+
),
|
|
248
|
+
jsonTool(
|
|
249
|
+
"github.create_pull_request_review_comment",
|
|
250
|
+
"Create a review comment on a GitHub pull request diff.",
|
|
251
|
+
reviewCommentSchema(),
|
|
252
|
+
async (input) => {
|
|
253
|
+
const { owner, repo, pull_number, body, commit_id, path, line, side } = input;
|
|
254
|
+
return octokit.rest.pulls.createReviewComment({
|
|
255
|
+
owner,
|
|
256
|
+
repo,
|
|
257
|
+
pull_number,
|
|
258
|
+
body,
|
|
259
|
+
commit_id,
|
|
260
|
+
path,
|
|
261
|
+
line,
|
|
262
|
+
...side ? { side } : {}
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
),
|
|
266
|
+
jsonTool(
|
|
267
|
+
"github.update_issue",
|
|
268
|
+
"Update a GitHub issue or pull request issue fields.",
|
|
269
|
+
updateIssueSchema(),
|
|
270
|
+
async (input) => {
|
|
271
|
+
const { owner, repo, issue_number, title, body, state, assignees, labels } = input;
|
|
272
|
+
return octokit.rest.issues.update({
|
|
273
|
+
owner,
|
|
274
|
+
repo,
|
|
275
|
+
issue_number,
|
|
276
|
+
...title ? { title } : {},
|
|
277
|
+
...body ? { body } : {},
|
|
278
|
+
...state ? { state } : {},
|
|
279
|
+
...assignees ? { assignees } : {},
|
|
280
|
+
...labels ? { labels } : {}
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
),
|
|
284
|
+
jsonTool(
|
|
285
|
+
"github.add_issue_labels",
|
|
286
|
+
"Add labels to a GitHub issue or pull request.",
|
|
287
|
+
labelsSchema(),
|
|
288
|
+
async (input) => {
|
|
289
|
+
const { owner, repo, issue_number, labels } = input;
|
|
290
|
+
return octokit.rest.issues.addLabels({ owner, repo, issue_number, labels });
|
|
291
|
+
}
|
|
292
|
+
),
|
|
293
|
+
jsonTool(
|
|
294
|
+
"github.set_commit_status",
|
|
295
|
+
"Set a GitHub commit status.",
|
|
296
|
+
commitStatusSchema(),
|
|
297
|
+
async (input) => {
|
|
298
|
+
const { owner, repo, sha, state, description, context, target_url } = input;
|
|
299
|
+
return octokit.rest.repos.createCommitStatus({
|
|
300
|
+
owner,
|
|
301
|
+
repo,
|
|
302
|
+
sha,
|
|
303
|
+
state,
|
|
304
|
+
...description ? { description } : {},
|
|
305
|
+
...context ? { context } : {},
|
|
306
|
+
...target_url ? { target_url } : {}
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
),
|
|
310
|
+
jsonTool(
|
|
311
|
+
"github.rerun_workflow_run",
|
|
312
|
+
"Rerun a GitHub Actions workflow run.",
|
|
313
|
+
workflowRunSchema(),
|
|
314
|
+
async (input) => {
|
|
315
|
+
const { owner, repo, run_id } = input;
|
|
316
|
+
return octokit.rest.actions.reRunWorkflow({ owner, repo, run_id });
|
|
317
|
+
}
|
|
318
|
+
),
|
|
319
|
+
jsonTool(
|
|
320
|
+
"github.cancel_workflow_run",
|
|
321
|
+
"Cancel a GitHub Actions workflow run.",
|
|
322
|
+
workflowRunSchema(),
|
|
323
|
+
async (input) => {
|
|
324
|
+
const { owner, repo, run_id } = input;
|
|
325
|
+
return octokit.rest.actions.cancelWorkflowRun({ owner, repo, run_id });
|
|
326
|
+
}
|
|
327
|
+
)
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
return tools;
|
|
331
|
+
}
|
|
332
|
+
function jsonTool(name, description, inputSchema, call) {
|
|
333
|
+
return {
|
|
334
|
+
definition: { name, description, inputSchema, source: "pack:cap-github" },
|
|
335
|
+
handler: async ({ input }) => {
|
|
336
|
+
try {
|
|
337
|
+
const result = await call(input);
|
|
338
|
+
return { content: JSON.stringify(result, null, 2) };
|
|
339
|
+
} catch (err) {
|
|
340
|
+
return {
|
|
341
|
+
content: err instanceof Error ? err.message : String(err),
|
|
342
|
+
isError: true
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
function repoSchema() {
|
|
349
|
+
return objectSchema({
|
|
350
|
+
owner: { type: "string" },
|
|
351
|
+
repo: { type: "string" }
|
|
352
|
+
});
|
|
353
|
+
}
|
|
354
|
+
function issueSchema() {
|
|
355
|
+
return objectSchema({
|
|
356
|
+
owner: { type: "string" },
|
|
357
|
+
repo: { type: "string" },
|
|
358
|
+
issue_number: { type: "number" }
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
function prSchema() {
|
|
362
|
+
return objectSchema({
|
|
363
|
+
owner: { type: "string" },
|
|
364
|
+
repo: { type: "string" },
|
|
365
|
+
pull_number: { type: "number" }
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
function refSchema() {
|
|
369
|
+
return objectSchema({
|
|
370
|
+
owner: { type: "string" },
|
|
371
|
+
repo: { type: "string" },
|
|
372
|
+
ref: { type: "string" }
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
function workflowRunSchema() {
|
|
376
|
+
return objectSchema({
|
|
377
|
+
owner: { type: "string" },
|
|
378
|
+
repo: { type: "string" },
|
|
379
|
+
run_id: { type: "number" }
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
function contentSchema() {
|
|
383
|
+
return objectSchema({
|
|
384
|
+
owner: { type: "string" },
|
|
385
|
+
repo: { type: "string" },
|
|
386
|
+
path: { type: "string" },
|
|
387
|
+
ref: { type: "string", optional: true }
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
function issueCommentSchema() {
|
|
391
|
+
return objectSchema({
|
|
392
|
+
owner: { type: "string" },
|
|
393
|
+
repo: { type: "string" },
|
|
394
|
+
issue_number: { type: "number" },
|
|
395
|
+
body: { type: "string" }
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
function reviewCommentSchema() {
|
|
399
|
+
return objectSchema({
|
|
400
|
+
owner: { type: "string" },
|
|
401
|
+
repo: { type: "string" },
|
|
402
|
+
pull_number: { type: "number" },
|
|
403
|
+
body: { type: "string" },
|
|
404
|
+
commit_id: { type: "string" },
|
|
405
|
+
path: { type: "string" },
|
|
406
|
+
line: { type: "number" },
|
|
407
|
+
side: { type: "string", enum: ["LEFT", "RIGHT"], optional: true }
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
function updateIssueSchema() {
|
|
411
|
+
return objectSchema({
|
|
412
|
+
owner: { type: "string" },
|
|
413
|
+
repo: { type: "string" },
|
|
414
|
+
issue_number: { type: "number" },
|
|
415
|
+
title: { type: "string", optional: true },
|
|
416
|
+
body: { type: "string", optional: true },
|
|
417
|
+
state: { type: "string", enum: ["open", "closed"], optional: true },
|
|
418
|
+
assignees: { type: "array", items: { type: "string" }, optional: true },
|
|
419
|
+
labels: { type: "array", items: { type: "string" }, optional: true }
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
function labelsSchema() {
|
|
423
|
+
return objectSchema({
|
|
424
|
+
owner: { type: "string" },
|
|
425
|
+
repo: { type: "string" },
|
|
426
|
+
issue_number: { type: "number" },
|
|
427
|
+
labels: { type: "array", items: { type: "string" } }
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
function commitStatusSchema() {
|
|
431
|
+
return objectSchema({
|
|
432
|
+
owner: { type: "string" },
|
|
433
|
+
repo: { type: "string" },
|
|
434
|
+
sha: { type: "string" },
|
|
435
|
+
state: { type: "string", enum: ["error", "failure", "pending", "success"] },
|
|
436
|
+
description: { type: "string", optional: true },
|
|
437
|
+
context: { type: "string", optional: true },
|
|
438
|
+
target_url: { type: "string", optional: true }
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
function objectSchema(properties) {
|
|
442
|
+
return {
|
|
443
|
+
type: "object",
|
|
444
|
+
additionalProperties: false,
|
|
445
|
+
properties,
|
|
446
|
+
required: Object.entries(properties).filter(([, value]) => !value.optional).map(([key]) => key)
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
function verifyGitHubSignature(args) {
|
|
450
|
+
if (!args.signature?.startsWith("sha256=")) return false;
|
|
451
|
+
const expected = createHmac("sha256", args.secret).update(args.rawBody).digest("hex");
|
|
452
|
+
const actual = args.signature.slice("sha256=".length);
|
|
453
|
+
const expectedBuf = Buffer.from(expected, "hex");
|
|
454
|
+
const actualBuf = Buffer.from(actual, "hex");
|
|
455
|
+
if (expectedBuf.length !== actualBuf.length) return false;
|
|
456
|
+
return timingSafeEqual(expectedBuf, actualBuf);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// src/index.ts
|
|
460
|
+
var DEFAULT_WEBHOOK_SECRET_ENV = "GITHUB_WEBHOOK_SECRET";
|
|
461
|
+
var DEFAULT_TOKEN_ENV = "GITHUB_TOKEN";
|
|
462
|
+
var pack = definePack({
|
|
463
|
+
name: "cap-github",
|
|
464
|
+
version: "0.1.0",
|
|
465
|
+
envSchema: [
|
|
466
|
+
{
|
|
467
|
+
name: DEFAULT_WEBHOOK_SECRET_ENV,
|
|
468
|
+
required: true,
|
|
469
|
+
secret: true,
|
|
470
|
+
description: "GitHub webhook secret."
|
|
471
|
+
},
|
|
472
|
+
{
|
|
473
|
+
name: DEFAULT_TOKEN_ENV,
|
|
474
|
+
required: true,
|
|
475
|
+
secret: true,
|
|
476
|
+
description: "GitHub token used for read tools and optional write tools."
|
|
477
|
+
}
|
|
478
|
+
],
|
|
479
|
+
localTools(ctx) {
|
|
480
|
+
const cfg = readConfig(ctx.config);
|
|
481
|
+
const token = ctx.env(cfg.tokenEnv);
|
|
482
|
+
if (!token) throw new Error(`cap-github: ${cfg.tokenEnv} is not set`);
|
|
483
|
+
return githubTools({ token, accessMode: cfg.accessMode });
|
|
484
|
+
},
|
|
485
|
+
connectors(ctx) {
|
|
486
|
+
const cfg = readConfig(ctx.config);
|
|
487
|
+
return [
|
|
488
|
+
{
|
|
489
|
+
key: "github",
|
|
490
|
+
webhook: async (req, webCtx) => {
|
|
491
|
+
const rawBody = await req.text();
|
|
492
|
+
const secret = ctx.env(cfg.webhookSecretEnv);
|
|
493
|
+
if (!secret) return json({ error: "missing_secret", env: cfg.webhookSecretEnv }, 500);
|
|
494
|
+
if (!verifyGitHubSignature({
|
|
495
|
+
rawBody,
|
|
496
|
+
secret,
|
|
497
|
+
signature: req.headers.get("x-hub-signature-256")
|
|
498
|
+
})) {
|
|
499
|
+
return json({ error: "invalid_signature" }, 401);
|
|
500
|
+
}
|
|
501
|
+
const event = req.headers.get("x-github-event") ?? "";
|
|
502
|
+
const delivery = req.headers.get("x-github-delivery");
|
|
503
|
+
const parsed = parseBody(rawBody);
|
|
504
|
+
const normalized = normalizeGitHubEvent(event, parsed, cfg);
|
|
505
|
+
if (!normalized) return json({ ok: true, skipped: true });
|
|
506
|
+
const agent = webCtx.resolveAgent(cfg.agent);
|
|
507
|
+
const result = await webCtx.enqueueRun({
|
|
508
|
+
agentName: agent.name,
|
|
509
|
+
agentVersion: agent.version,
|
|
510
|
+
userId: cfg.userId ?? "cap-github",
|
|
511
|
+
runId: `github-${hash(delivery ?? rawBody)}`,
|
|
512
|
+
initialContent: [{ type: "text", text: normalized.summary }],
|
|
513
|
+
metadata: {
|
|
514
|
+
connector: "cap-github",
|
|
515
|
+
deliveryId: delivery,
|
|
516
|
+
...normalized
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
return json(result, result.status === "enqueued" ? 202 : 200);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
];
|
|
523
|
+
}
|
|
524
|
+
});
|
|
525
|
+
var src_default = pack;
|
|
526
|
+
function readConfig(raw) {
|
|
527
|
+
const cfg = {
|
|
528
|
+
webhookSecretEnv: stringValue2(raw.webhookSecretEnv) ?? DEFAULT_WEBHOOK_SECRET_ENV,
|
|
529
|
+
tokenEnv: stringValue2(raw.tokenEnv) ?? DEFAULT_TOKEN_ENV,
|
|
530
|
+
accessMode: raw.accessMode === "read_write" ? "read_write" : "read"
|
|
531
|
+
};
|
|
532
|
+
const agent = stringValue2(raw.agent);
|
|
533
|
+
if (agent) cfg.agent = agent;
|
|
534
|
+
const userId = stringValue2(raw.userId);
|
|
535
|
+
if (userId) cfg.userId = userId;
|
|
536
|
+
const allowedRepositories = stringArray(raw.allowedRepositories);
|
|
537
|
+
if (allowedRepositories) cfg.allowedRepositories = allowedRepositories;
|
|
538
|
+
const events = stringArray(raw.events);
|
|
539
|
+
if (events) cfg.events = events;
|
|
540
|
+
const branches = stringArray(raw.branches);
|
|
541
|
+
if (branches) cfg.branches = branches;
|
|
542
|
+
const labels = stringArray(raw.labels);
|
|
543
|
+
if (labels) cfg.labels = labels;
|
|
544
|
+
const ignoredActors = stringArray(raw.ignoredActors);
|
|
545
|
+
if (ignoredActors) cfg.ignoredActors = ignoredActors;
|
|
546
|
+
return cfg;
|
|
547
|
+
}
|
|
548
|
+
function parseBody(rawBody) {
|
|
549
|
+
try {
|
|
550
|
+
return JSON.parse(rawBody);
|
|
551
|
+
} catch {
|
|
552
|
+
return null;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
function hash(value) {
|
|
556
|
+
return createHash("sha256").update(value).digest("hex").slice(0, 32);
|
|
557
|
+
}
|
|
558
|
+
function json(body, status = 200) {
|
|
559
|
+
return Response.json(body, { status });
|
|
560
|
+
}
|
|
561
|
+
function stringValue2(value) {
|
|
562
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
563
|
+
}
|
|
564
|
+
function stringArray(value) {
|
|
565
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : void 0;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
export { src_default as default };
|
|
569
|
+
//# sourceMappingURL=index.js.map
|
|
570
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/normalize.ts","../src/tools.ts","../src/verify.ts","../src/index.ts"],"names":["url","objectId","stringValue"],"mappings":"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","file":"index.js","sourcesContent":["export interface GitHubFilterConfig {\n allowedRepositories?: string[];\n events?: string[];\n branches?: string[];\n labels?: string[];\n ignoredActors?: string[];\n}\n\nexport interface NormalizedGitHubEvent {\n event: string;\n action?: string;\n repo: string;\n actor?: string;\n objectType: string;\n objectId?: string | number;\n number?: number;\n branch?: string;\n url?: string;\n summary: string;\n}\n\nconst SUPPORTED_EVENTS = new Set([\n \"issues\",\n \"issue_comment\",\n \"pull_request\",\n \"pull_request_review\",\n \"pull_request_review_comment\",\n \"push\",\n \"check_run\",\n \"check_suite\",\n \"workflow_run\",\n]);\n\nexport function normalizeGitHubEvent(\n event: string,\n body: unknown,\n cfg: GitHubFilterConfig = {},\n): NormalizedGitHubEvent | null {\n if (!SUPPORTED_EVENTS.has(event)) return null;\n if (cfg.events?.length && !cfg.events.includes(event)) return null;\n if (!body || typeof body !== \"object\") return null;\n const payload = body as Record<string, unknown>;\n const repo = stringAt(payload, \"repository.full_name\");\n if (!repo) return null;\n if (cfg.allowedRepositories?.length && !cfg.allowedRepositories.includes(repo)) return null;\n const actor = stringAt(payload, \"sender.login\");\n if (actor && cfg.ignoredActors?.includes(actor)) return null;\n const branch = branchFor(event, payload);\n if (cfg.branches?.length && branch && !cfg.branches.includes(branch)) return null;\n if (cfg.labels?.length && !hasAllowedLabel(payload, cfg.labels)) return null;\n\n const action = stringValue(payload.action);\n const normalized = buildNormalized(event, payload, repo, actor, action, branch);\n return normalized;\n}\n\nfunction buildNormalized(\n event: string,\n payload: Record<string, unknown>,\n repo: string,\n actor: string | undefined,\n action: string | undefined,\n branch: string | undefined,\n): NormalizedGitHubEvent {\n if (event === \"issues\") {\n const number = numberAt(payload, \"issue.number\");\n const url = stringAt(payload, \"issue.html_url\");\n return {\n event,\n ...(action ? { action } : {}),\n repo,\n ...(actor ? { actor } : {}),\n objectType: \"issue\",\n ...(number !== undefined ? { objectId: number } : {}),\n ...(number !== undefined ? { number } : {}),\n ...(url ? { url } : {}),\n summary: `GitHub issue ${repo}#${number ?? \"unknown\"} ${action ?? \"changed\"}`,\n };\n }\n if (event === \"pull_request\") {\n const number = numberAt(payload, \"pull_request.number\");\n const url = stringAt(payload, \"pull_request.html_url\");\n return {\n event,\n ...(action ? { action } : {}),\n repo,\n ...(actor ? { actor } : {}),\n objectType: \"pull_request\",\n ...(number !== undefined ? { objectId: number } : {}),\n ...(number !== undefined ? { number } : {}),\n ...(branch ? { branch } : {}),\n ...(url ? { url } : {}),\n summary: `GitHub PR ${repo}#${number ?? \"unknown\"} ${action ?? \"changed\"}`,\n };\n }\n if (event === \"push\") {\n const objectId = stringAt(payload, \"after\");\n const url = stringAt(payload, \"compare\");\n return {\n event,\n repo,\n ...(actor ? { actor } : {}),\n objectType: \"push\",\n ...(objectId ? { objectId } : {}),\n ...(branch ? { branch } : {}),\n ...(url ? { url } : {}),\n summary: `GitHub push to ${repo}${branch ? `:${branch}` : \"\"}`,\n };\n }\n const objectType = event.replace(/_/g, \"-\");\n const objectId =\n stringAt(payload, `${event}.id`) ??\n numberAt(payload, `${event}.id`) ??\n stringAt(payload, \"check_run.id\") ??\n numberAt(payload, \"check_run.id\");\n const url = stringAt(payload, `${event}.html_url`) ?? stringAt(payload, `${event}.url`);\n return {\n event,\n ...(action ? { action } : {}),\n repo,\n ...(actor ? { actor } : {}),\n objectType,\n ...(objectId !== undefined ? { objectId } : {}),\n ...(branch ? { branch } : {}),\n ...(url ? { url } : {}),\n summary: `GitHub ${objectType} event for ${repo}`,\n };\n}\n\nfunction branchFor(event: string, payload: Record<string, unknown>): string | undefined {\n if (event === \"push\") {\n const ref = stringValue(payload.ref);\n return ref?.startsWith(\"refs/heads/\") ? ref.slice(\"refs/heads/\".length) : ref;\n }\n return (\n stringAt(payload, \"pull_request.head.ref\") ?? stringAt(payload, \"workflow_run.head_branch\")\n );\n}\n\nfunction hasAllowedLabel(payload: Record<string, unknown>, allowed: string[]): boolean {\n const issueLabels = arrayAt(payload, \"issue.labels\");\n const prLabels = arrayAt(payload, \"pull_request.labels\");\n const labels = [...issueLabels, ...prLabels]\n .map((label) =>\n label && typeof label === \"object\" ? stringValue((label as { name?: unknown }).name) : null,\n )\n .filter((label): label is string => !!label);\n return labels.some((label) => allowed.includes(label));\n}\n\nfunction stringAt(value: unknown, path: string): string | undefined {\n return stringValue(readPath(value, path));\n}\n\nfunction numberAt(value: unknown, path: string): number | undefined {\n const found = readPath(value, path);\n return typeof found === \"number\" ? found : undefined;\n}\n\nfunction arrayAt(value: unknown, path: string): unknown[] {\n const found = readPath(value, path);\n return Array.isArray(found) ? found : [];\n}\n\nfunction readPath(value: unknown, path: string): unknown {\n let cursor = value;\n for (const part of path.split(\".\")) {\n if (!cursor || typeof cursor !== \"object\") return undefined;\n cursor = (cursor as Record<string, unknown>)[part];\n }\n return cursor;\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n","import { Octokit } from \"@octokit/rest\";\nimport type { LocalToolHandler } from \"@render-harness/core\";\n\nexport type GitHubAccessMode = \"read\" | \"read_write\";\n\nexport function githubTools(args: {\n token: string;\n accessMode: GitHubAccessMode;\n}): LocalToolHandler[] {\n const octokit = new Octokit({ auth: args.token });\n const tools: LocalToolHandler[] = [\n jsonTool(\"github.get_issue\", \"Read a GitHub issue.\", issueSchema(), async (input) => {\n const { owner, repo, issue_number } = input as IssueInput;\n return octokit.rest.issues.get({ owner, repo, issue_number });\n }),\n jsonTool(\n \"github.get_pull_request\",\n \"Read a GitHub pull request.\",\n prSchema(),\n async (input) => {\n const { owner, repo, pull_number } = input as PullInput;\n return octokit.rest.pulls.get({ owner, repo, pull_number });\n },\n ),\n jsonTool(\n \"github.list_pull_request_files\",\n \"List files changed by a GitHub pull request.\",\n prSchema(),\n async (input) => {\n const { owner, repo, pull_number } = input as PullInput;\n return octokit.paginate(octokit.rest.pulls.listFiles, { owner, repo, pull_number });\n },\n ),\n jsonTool(\n \"github.list_pull_request_reviews\",\n \"List reviews on a GitHub pull request.\",\n prSchema(),\n async (input) => {\n const { owner, repo, pull_number } = input as PullInput;\n return octokit.paginate(octokit.rest.pulls.listReviews, { owner, repo, pull_number });\n },\n ),\n jsonTool(\n \"github.list_pull_request_commits\",\n \"List commits on a GitHub pull request.\",\n prSchema(),\n async (input) => {\n const { owner, repo, pull_number } = input as PullInput;\n return octokit.paginate(octokit.rest.pulls.listCommits, { owner, repo, pull_number });\n },\n ),\n jsonTool(\n \"github.list_issue_comments\",\n \"List comments on a GitHub issue or pull request.\",\n issueSchema(),\n async (input) => {\n const { owner, repo, issue_number } = input as IssueInput;\n return octokit.paginate(octokit.rest.issues.listComments, { owner, repo, issue_number });\n },\n ),\n jsonTool(\n \"github.get_content\",\n \"Read a file or directory listing from a GitHub repository.\",\n contentSchema(),\n async (input) => {\n const { owner, repo, path, ref } = input as ContentInput;\n return octokit.rest.repos.getContent({\n owner,\n repo,\n path,\n ...(ref ? { ref } : {}),\n });\n },\n ),\n jsonTool(\n \"github.list_checks\",\n \"List check runs for a GitHub ref.\",\n refSchema(),\n async (input) => {\n const { owner, repo, ref } = input as RefInput;\n return octokit.rest.checks.listForRef({ owner, repo, ref });\n },\n ),\n jsonTool(\n \"github.list_workflow_runs\",\n \"List GitHub Actions workflow runs.\",\n repoSchema(),\n async (input) => {\n const { owner, repo } = input as RepoInput;\n return octokit.rest.actions.listWorkflowRunsForRepo({ owner, repo });\n },\n ),\n jsonTool(\n \"github.get_workflow_run\",\n \"Read one GitHub Actions workflow run.\",\n workflowRunSchema(),\n async (input) => {\n const { owner, repo, run_id } = input as WorkflowRunInput;\n return octokit.rest.actions.getWorkflowRun({ owner, repo, run_id });\n },\n ),\n jsonTool(\n \"github.list_workflow_run_jobs\",\n \"List jobs for a GitHub Actions workflow run.\",\n workflowRunSchema(),\n async (input) => {\n const { owner, repo, run_id } = input as WorkflowRunInput;\n return octokit.rest.actions.listJobsForWorkflowRun({ owner, repo, run_id });\n },\n ),\n ];\n\n if (args.accessMode === \"read_write\") {\n tools.push(\n jsonTool(\n \"github.create_issue_comment\",\n \"Create a comment on a GitHub issue or pull request.\",\n issueCommentSchema(),\n async (input) => {\n const { owner, repo, issue_number, body } = input as IssueCommentInput;\n return octokit.rest.issues.createComment({ owner, repo, issue_number, body });\n },\n ),\n jsonTool(\n \"github.create_pull_request_review_comment\",\n \"Create a review comment on a GitHub pull request diff.\",\n reviewCommentSchema(),\n async (input) => {\n const { owner, repo, pull_number, body, commit_id, path, line, side } =\n input as PullReviewCommentInput;\n return octokit.rest.pulls.createReviewComment({\n owner,\n repo,\n pull_number,\n body,\n commit_id,\n path,\n line,\n ...(side ? { side } : {}),\n });\n },\n ),\n jsonTool(\n \"github.update_issue\",\n \"Update a GitHub issue or pull request issue fields.\",\n updateIssueSchema(),\n async (input) => {\n const { owner, repo, issue_number, title, body, state, assignees, labels } =\n input as UpdateIssueInput;\n return octokit.rest.issues.update({\n owner,\n repo,\n issue_number,\n ...(title ? { title } : {}),\n ...(body ? { body } : {}),\n ...(state ? { state } : {}),\n ...(assignees ? { assignees } : {}),\n ...(labels ? { labels } : {}),\n });\n },\n ),\n jsonTool(\n \"github.add_issue_labels\",\n \"Add labels to a GitHub issue or pull request.\",\n labelsSchema(),\n async (input) => {\n const { owner, repo, issue_number, labels } = input as LabelsInput;\n return octokit.rest.issues.addLabels({ owner, repo, issue_number, labels });\n },\n ),\n jsonTool(\n \"github.set_commit_status\",\n \"Set a GitHub commit status.\",\n commitStatusSchema(),\n async (input) => {\n const { owner, repo, sha, state, description, context, target_url } =\n input as CommitStatusInput;\n return octokit.rest.repos.createCommitStatus({\n owner,\n repo,\n sha,\n state,\n ...(description ? { description } : {}),\n ...(context ? { context } : {}),\n ...(target_url ? { target_url } : {}),\n });\n },\n ),\n jsonTool(\n \"github.rerun_workflow_run\",\n \"Rerun a GitHub Actions workflow run.\",\n workflowRunSchema(),\n async (input) => {\n const { owner, repo, run_id } = input as WorkflowRunInput;\n return octokit.rest.actions.reRunWorkflow({ owner, repo, run_id });\n },\n ),\n jsonTool(\n \"github.cancel_workflow_run\",\n \"Cancel a GitHub Actions workflow run.\",\n workflowRunSchema(),\n async (input) => {\n const { owner, repo, run_id } = input as WorkflowRunInput;\n return octokit.rest.actions.cancelWorkflowRun({ owner, repo, run_id });\n },\n ),\n );\n }\n\n return tools;\n}\n\nfunction jsonTool(\n name: string,\n description: string,\n inputSchema: Record<string, unknown>,\n call: (input: unknown) => Promise<unknown>,\n): LocalToolHandler {\n return {\n definition: { name, description, inputSchema, source: \"pack:cap-github\" },\n handler: async ({ input }) => {\n try {\n const result = await call(input);\n return { content: JSON.stringify(result, null, 2) };\n } catch (err) {\n return {\n content: err instanceof Error ? err.message : String(err),\n isError: true,\n };\n }\n },\n };\n}\n\ninterface RepoInput {\n owner: string;\n repo: string;\n}\ninterface IssueInput extends RepoInput {\n issue_number: number;\n}\ninterface PullInput extends RepoInput {\n pull_number: number;\n}\ninterface RefInput extends RepoInput {\n ref: string;\n}\ninterface WorkflowRunInput extends RepoInput {\n run_id: number;\n}\ninterface ContentInput extends RepoInput {\n path: string;\n ref?: string;\n}\ninterface IssueCommentInput extends IssueInput {\n body: string;\n}\ninterface PullReviewCommentInput extends PullInput {\n body: string;\n commit_id: string;\n path: string;\n line: number;\n side?: \"LEFT\" | \"RIGHT\";\n}\ninterface UpdateIssueInput extends IssueInput {\n title?: string;\n body?: string;\n state?: \"open\" | \"closed\";\n assignees?: string[];\n labels?: string[];\n}\ninterface LabelsInput extends IssueInput {\n labels: string[];\n}\ninterface CommitStatusInput extends RepoInput {\n sha: string;\n state: \"error\" | \"failure\" | \"pending\" | \"success\";\n description?: string;\n context?: string;\n target_url?: string;\n}\n\nfunction repoSchema() {\n return objectSchema({\n owner: { type: \"string\" },\n repo: { type: \"string\" },\n });\n}\n\nfunction issueSchema() {\n return objectSchema({\n owner: { type: \"string\" },\n repo: { type: \"string\" },\n issue_number: { type: \"number\" },\n });\n}\n\nfunction prSchema() {\n return objectSchema({\n owner: { type: \"string\" },\n repo: { type: \"string\" },\n pull_number: { type: \"number\" },\n });\n}\n\nfunction refSchema() {\n return objectSchema({\n owner: { type: \"string\" },\n repo: { type: \"string\" },\n ref: { type: \"string\" },\n });\n}\n\nfunction workflowRunSchema() {\n return objectSchema({\n owner: { type: \"string\" },\n repo: { type: \"string\" },\n run_id: { type: \"number\" },\n });\n}\n\nfunction contentSchema() {\n return objectSchema({\n owner: { type: \"string\" },\n repo: { type: \"string\" },\n path: { type: \"string\" },\n ref: { type: \"string\", optional: true },\n });\n}\n\nfunction issueCommentSchema() {\n return objectSchema({\n owner: { type: \"string\" },\n repo: { type: \"string\" },\n issue_number: { type: \"number\" },\n body: { type: \"string\" },\n });\n}\n\nfunction reviewCommentSchema() {\n return objectSchema({\n owner: { type: \"string\" },\n repo: { type: \"string\" },\n pull_number: { type: \"number\" },\n body: { type: \"string\" },\n commit_id: { type: \"string\" },\n path: { type: \"string\" },\n line: { type: \"number\" },\n side: { type: \"string\", enum: [\"LEFT\", \"RIGHT\"], optional: true },\n });\n}\n\nfunction updateIssueSchema() {\n return objectSchema({\n owner: { type: \"string\" },\n repo: { type: \"string\" },\n issue_number: { type: \"number\" },\n title: { type: \"string\", optional: true },\n body: { type: \"string\", optional: true },\n state: { type: \"string\", enum: [\"open\", \"closed\"], optional: true },\n assignees: { type: \"array\", items: { type: \"string\" }, optional: true },\n labels: { type: \"array\", items: { type: \"string\" }, optional: true },\n });\n}\n\nfunction labelsSchema() {\n return objectSchema({\n owner: { type: \"string\" },\n repo: { type: \"string\" },\n issue_number: { type: \"number\" },\n labels: { type: \"array\", items: { type: \"string\" } },\n });\n}\n\nfunction commitStatusSchema() {\n return objectSchema({\n owner: { type: \"string\" },\n repo: { type: \"string\" },\n sha: { type: \"string\" },\n state: { type: \"string\", enum: [\"error\", \"failure\", \"pending\", \"success\"] },\n description: { type: \"string\", optional: true },\n context: { type: \"string\", optional: true },\n target_url: { type: \"string\", optional: true },\n });\n}\n\nfunction objectSchema(properties: Record<string, unknown>) {\n return {\n type: \"object\",\n additionalProperties: false,\n properties,\n required: Object.entries(properties)\n .filter(([, value]) => !(value as { optional?: boolean }).optional)\n .map(([key]) => key),\n };\n}\n","import { createHmac, timingSafeEqual } from \"node:crypto\";\n\nexport function verifyGitHubSignature(args: {\n rawBody: string;\n signature: string | null;\n secret: string;\n}): boolean {\n if (!args.signature?.startsWith(\"sha256=\")) return false;\n const expected = createHmac(\"sha256\", args.secret).update(args.rawBody).digest(\"hex\");\n const actual = args.signature.slice(\"sha256=\".length);\n const expectedBuf = Buffer.from(expected, \"hex\");\n const actualBuf = Buffer.from(actual, \"hex\");\n if (expectedBuf.length !== actualBuf.length) return false;\n return timingSafeEqual(expectedBuf, actualBuf);\n}\n","import { createHash } from \"node:crypto\";\nimport type { LocalToolHandler } from \"@render-harness/core\";\nimport { type ConnectorContribution, definePack, type PackContext } from \"@render-harness/registry\";\nimport { type GitHubFilterConfig, normalizeGitHubEvent } from \"./normalize.js\";\nimport { type GitHubAccessMode, githubTools } from \"./tools.js\";\nimport { verifyGitHubSignature } from \"./verify.js\";\n\ninterface GitHubConfig extends GitHubFilterConfig {\n agent?: string;\n userId?: string;\n webhookSecretEnv?: string;\n tokenEnv?: string;\n accessMode?: GitHubAccessMode;\n}\n\nconst DEFAULT_WEBHOOK_SECRET_ENV = \"GITHUB_WEBHOOK_SECRET\";\nconst DEFAULT_TOKEN_ENV = \"GITHUB_TOKEN\";\n\nconst pack = definePack({\n name: \"cap-github\",\n version: \"0.1.0\",\n envSchema: [\n {\n name: DEFAULT_WEBHOOK_SECRET_ENV,\n required: true,\n secret: true,\n description: \"GitHub webhook secret.\",\n },\n {\n name: DEFAULT_TOKEN_ENV,\n required: true,\n secret: true,\n description: \"GitHub token used for read tools and optional write tools.\",\n },\n ],\n localTools(ctx: PackContext): LocalToolHandler[] {\n const cfg = readConfig(ctx.config);\n const token = ctx.env(cfg.tokenEnv);\n if (!token) throw new Error(`cap-github: ${cfg.tokenEnv} is not set`);\n return githubTools({ token, accessMode: cfg.accessMode });\n },\n connectors(ctx: PackContext): ConnectorContribution[] {\n const cfg = readConfig(ctx.config);\n return [\n {\n key: \"github\",\n webhook: async (req, webCtx) => {\n const rawBody = await req.text();\n const secret = ctx.env(cfg.webhookSecretEnv);\n if (!secret) return json({ error: \"missing_secret\", env: cfg.webhookSecretEnv }, 500);\n if (\n !verifyGitHubSignature({\n rawBody,\n secret,\n signature: req.headers.get(\"x-hub-signature-256\"),\n })\n ) {\n return json({ error: \"invalid_signature\" }, 401);\n }\n\n const event = req.headers.get(\"x-github-event\") ?? \"\";\n const delivery = req.headers.get(\"x-github-delivery\");\n const parsed = parseBody(rawBody);\n const normalized = normalizeGitHubEvent(event, parsed, cfg);\n if (!normalized) return json({ ok: true, skipped: true });\n const agent = webCtx.resolveAgent(cfg.agent);\n const result = await webCtx.enqueueRun({\n agentName: agent.name,\n agentVersion: agent.version,\n userId: cfg.userId ?? \"cap-github\",\n runId: `github-${hash(delivery ?? rawBody)}`,\n initialContent: [{ type: \"text\", text: normalized.summary }],\n metadata: {\n connector: \"cap-github\",\n deliveryId: delivery,\n ...normalized,\n },\n });\n return json(result, result.status === \"enqueued\" ? 202 : 200);\n },\n },\n ];\n },\n});\n\nexport default pack;\n\ntype ResolvedGitHubConfig = Required<\n Pick<GitHubConfig, \"webhookSecretEnv\" | \"tokenEnv\" | \"accessMode\">\n> &\n Omit<GitHubConfig, \"webhookSecretEnv\" | \"tokenEnv\" | \"accessMode\">;\n\nfunction readConfig(raw: Record<string, unknown>): ResolvedGitHubConfig {\n const cfg: ResolvedGitHubConfig = {\n webhookSecretEnv: stringValue(raw.webhookSecretEnv) ?? DEFAULT_WEBHOOK_SECRET_ENV,\n tokenEnv: stringValue(raw.tokenEnv) ?? DEFAULT_TOKEN_ENV,\n accessMode: raw.accessMode === \"read_write\" ? \"read_write\" : \"read\",\n };\n const agent = stringValue(raw.agent);\n if (agent) cfg.agent = agent;\n const userId = stringValue(raw.userId);\n if (userId) cfg.userId = userId;\n const allowedRepositories = stringArray(raw.allowedRepositories);\n if (allowedRepositories) cfg.allowedRepositories = allowedRepositories;\n const events = stringArray(raw.events);\n if (events) cfg.events = events;\n const branches = stringArray(raw.branches);\n if (branches) cfg.branches = branches;\n const labels = stringArray(raw.labels);\n if (labels) cfg.labels = labels;\n const ignoredActors = stringArray(raw.ignoredActors);\n if (ignoredActors) cfg.ignoredActors = ignoredActors;\n return cfg;\n}\n\nfunction parseBody(rawBody: string): unknown {\n try {\n return JSON.parse(rawBody);\n } catch {\n return null;\n }\n}\n\nfunction hash(value: string): string {\n return createHash(\"sha256\").update(value).digest(\"hex\").slice(0, 32);\n}\n\nfunction json(body: unknown, status = 200): Response {\n return Response.json(body, { status });\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n\nfunction stringArray(value: unknown): string[] | undefined {\n return Array.isArray(value)\n ? value.filter((item): item is string => typeof item === \"string\")\n : undefined;\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@render-harness/cap-github",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "GitHub monitoring capability pack for the Render agent harness.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"keywords": [
|
|
19
|
+
"render-harness-cap",
|
|
20
|
+
"render-harness",
|
|
21
|
+
"github"
|
|
22
|
+
],
|
|
23
|
+
"renderHarness": {
|
|
24
|
+
"gallery": {
|
|
25
|
+
"label": "GitHub",
|
|
26
|
+
"envHint": "GITHUB_TOKEN"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@octokit/rest": "^22.0.1",
|
|
31
|
+
"@render-harness/registry": "0.2.0"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/node": "^25.6.2",
|
|
35
|
+
"tsup": "^8.5.1",
|
|
36
|
+
"typescript": "^6.0.3",
|
|
37
|
+
"vitest": "^4.1.5",
|
|
38
|
+
"@render-harness/core": "0.2.0"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsup",
|
|
45
|
+
"typecheck": "tsc --noEmit",
|
|
46
|
+
"test": "vitest run --passWithNoTests"
|
|
47
|
+
}
|
|
48
|
+
}
|