@slates-integrations/github 0.2.0-rc.2
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 +109 -0
- package/docs/SPEC.md +215 -0
- package/logo.png +0 -0
- package/package.json +18 -0
- package/slate.json +22 -0
- package/src/auth.ts +257 -0
- package/src/config.ts +4 -0
- package/src/index.ts +78 -0
- package/src/lib/client.ts +974 -0
- package/src/spec.ts +13 -0
- package/src/tools/comment-on-issue.ts +46 -0
- package/src/tools/create-commit-status.ts +97 -0
- package/src/tools/create-release.ts +69 -0
- package/src/tools/create-repository.ts +70 -0
- package/src/tools/get-issue.ts +67 -0
- package/src/tools/get-repository.ts +75 -0
- package/src/tools/get-user.ts +64 -0
- package/src/tools/index.ts +24 -0
- package/src/tools/list-branches.ts +54 -0
- package/src/tools/list-commits.ts +70 -0
- package/src/tools/list-issues.ts +90 -0
- package/src/tools/list-pull-requests.ts +82 -0
- package/src/tools/list-repositories.ts +102 -0
- package/src/tools/manage-collaborators.ts +88 -0
- package/src/tools/manage-file-content.ts +117 -0
- package/src/tools/manage-gist.ts +183 -0
- package/src/tools/manage-issue.ts +94 -0
- package/src/tools/manage-labels.ts +93 -0
- package/src/tools/manage-pull-request.ts +111 -0
- package/src/tools/manage-workflow.ts +242 -0
- package/src/tools/merge-pull-request.ts +61 -0
- package/src/tools/review-pull-request.ts +90 -0
- package/src/tools/search.ts +72 -0
- package/src/tools/star-repository.ts +57 -0
- package/src/tools/update-repository.ts +56 -0
- package/src/triggers/index.ts +8 -0
- package/src/triggers/issue-comment.ts +94 -0
- package/src/triggers/issues.ts +111 -0
- package/src/triggers/pull-request-review.ts +95 -0
- package/src/triggers/pull-request.ts +123 -0
- package/src/triggers/push.ts +117 -0
- package/src/triggers/release.ts +103 -0
- package/src/triggers/star.ts +71 -0
- package/src/triggers/workflow-run.ts +112 -0
- package/tsconfig.json +23 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { SlateTool } from 'slates';
|
|
2
|
+
import { GitHubClient } from '../lib/client';
|
|
3
|
+
import { spec } from '../spec';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
|
|
6
|
+
export let search = SlateTool.create(spec, {
|
|
7
|
+
name: 'Search GitHub',
|
|
8
|
+
key: 'search',
|
|
9
|
+
description: `Search across GitHub for repositories, code, issues/pull requests, or users using GitHub's search syntax.
|
|
10
|
+
Supports qualifiers for filtering (e.g., "language:python stars:>100" for repositories).`,
|
|
11
|
+
instructions: [
|
|
12
|
+
'Use GitHub search qualifiers in the query for precise results (e.g., "repo:owner/name", "language:go", "is:pr is:merged").',
|
|
13
|
+
'For issues vs PRs, use "is:issue" or "is:pr" qualifier in the query when searching type "issues".'
|
|
14
|
+
],
|
|
15
|
+
tags: {
|
|
16
|
+
readOnly: true
|
|
17
|
+
}
|
|
18
|
+
})
|
|
19
|
+
.input(
|
|
20
|
+
z.object({
|
|
21
|
+
type: z
|
|
22
|
+
.enum(['repositories', 'code', 'issues', 'users'])
|
|
23
|
+
.describe('Type of resource to search'),
|
|
24
|
+
query: z.string().describe('Search query with optional GitHub search qualifiers'),
|
|
25
|
+
sort: z
|
|
26
|
+
.string()
|
|
27
|
+
.optional()
|
|
28
|
+
.describe('Sort field (varies by type, e.g., "stars", "updated", "comments")'),
|
|
29
|
+
order: z.enum(['asc', 'desc']).optional().describe('Sort order'),
|
|
30
|
+
perPage: z.number().optional().describe('Results per page (max 100)'),
|
|
31
|
+
page: z.number().optional().describe('Page number')
|
|
32
|
+
})
|
|
33
|
+
)
|
|
34
|
+
.output(
|
|
35
|
+
z.object({
|
|
36
|
+
totalCount: z.number().describe('Total number of matching results'),
|
|
37
|
+
incompleteResults: z.boolean().describe('Whether results may be incomplete'),
|
|
38
|
+
items: z
|
|
39
|
+
.array(z.record(z.string(), z.any()))
|
|
40
|
+
.describe('Search result items (shape depends on search type)')
|
|
41
|
+
})
|
|
42
|
+
)
|
|
43
|
+
.handleInvocation(async ctx => {
|
|
44
|
+
let client = new GitHubClient(ctx.auth.token);
|
|
45
|
+
let { type, query, ...params } = ctx.input;
|
|
46
|
+
let result: any;
|
|
47
|
+
|
|
48
|
+
switch (type) {
|
|
49
|
+
case 'repositories':
|
|
50
|
+
result = await client.searchRepositories(query, params);
|
|
51
|
+
break;
|
|
52
|
+
case 'code':
|
|
53
|
+
result = await client.searchCode(query, params);
|
|
54
|
+
break;
|
|
55
|
+
case 'issues':
|
|
56
|
+
result = await client.searchIssues(query, params);
|
|
57
|
+
break;
|
|
58
|
+
case 'users':
|
|
59
|
+
result = await client.searchUsers(query, params);
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
output: {
|
|
65
|
+
totalCount: result.total_count,
|
|
66
|
+
incompleteResults: result.incomplete_results,
|
|
67
|
+
items: result.items
|
|
68
|
+
},
|
|
69
|
+
message: `Found **${result.total_count}** results for "${query}" (${type}).`
|
|
70
|
+
};
|
|
71
|
+
})
|
|
72
|
+
.build();
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { SlateTool } from 'slates';
|
|
2
|
+
import { GitHubClient } from '../lib/client';
|
|
3
|
+
import { spec } from '../spec';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
|
|
6
|
+
export let starRepository = SlateTool.create(spec, {
|
|
7
|
+
name: 'Star Repository',
|
|
8
|
+
key: 'star_repository',
|
|
9
|
+
description: `Star or unstar a GitHub repository for the authenticated user.`
|
|
10
|
+
})
|
|
11
|
+
.input(
|
|
12
|
+
z.object({
|
|
13
|
+
owner: z.string().describe('Repository owner'),
|
|
14
|
+
repo: z.string().describe('Repository name'),
|
|
15
|
+
action: z.enum(['star', 'unstar']).describe('Whether to star or unstar the repository')
|
|
16
|
+
})
|
|
17
|
+
)
|
|
18
|
+
.output(
|
|
19
|
+
z.object({
|
|
20
|
+
owner: z.string().describe('Repository owner'),
|
|
21
|
+
repo: z.string().describe('Repository name'),
|
|
22
|
+
fullName: z.string().describe('Repository full name'),
|
|
23
|
+
htmlUrl: z.string().describe('Repository URL'),
|
|
24
|
+
starred: z.boolean().describe('Whether the repository is starred after this action')
|
|
25
|
+
})
|
|
26
|
+
)
|
|
27
|
+
.handleInvocation(async ctx => {
|
|
28
|
+
let client = new GitHubClient(ctx.auth.token);
|
|
29
|
+
let { owner, repo, action } = ctx.input;
|
|
30
|
+
|
|
31
|
+
if (action === 'star') {
|
|
32
|
+
await client.starRepository(owner, repo);
|
|
33
|
+
return {
|
|
34
|
+
output: {
|
|
35
|
+
owner,
|
|
36
|
+
repo,
|
|
37
|
+
fullName: `${owner}/${repo}`,
|
|
38
|
+
htmlUrl: `https://github.com/${owner}/${repo}`,
|
|
39
|
+
starred: true
|
|
40
|
+
},
|
|
41
|
+
message: `Starred **${owner}/${repo}**.`
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
await client.unstarRepository(owner, repo);
|
|
46
|
+
return {
|
|
47
|
+
output: {
|
|
48
|
+
owner,
|
|
49
|
+
repo,
|
|
50
|
+
fullName: `${owner}/${repo}`,
|
|
51
|
+
htmlUrl: `https://github.com/${owner}/${repo}`,
|
|
52
|
+
starred: false
|
|
53
|
+
},
|
|
54
|
+
message: `Removed star from **${owner}/${repo}**.`
|
|
55
|
+
};
|
|
56
|
+
})
|
|
57
|
+
.build();
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { SlateTool } from 'slates';
|
|
2
|
+
import { GitHubClient } from '../lib/client';
|
|
3
|
+
import { spec } from '../spec';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
|
|
6
|
+
export let updateRepository = SlateTool.create(spec, {
|
|
7
|
+
name: 'Update Repository',
|
|
8
|
+
key: 'update_repository',
|
|
9
|
+
description: `Update settings of an existing GitHub repository.
|
|
10
|
+
Modify name, description, visibility, feature toggles (issues, wiki, projects), default branch, and archive status.`
|
|
11
|
+
})
|
|
12
|
+
.input(
|
|
13
|
+
z.object({
|
|
14
|
+
owner: z.string().describe('Repository owner (user or organization)'),
|
|
15
|
+
repo: z.string().describe('Repository name'),
|
|
16
|
+
name: z.string().optional().describe('New repository name'),
|
|
17
|
+
description: z.string().optional().describe('New description'),
|
|
18
|
+
homepage: z.string().optional().describe('Homepage URL'),
|
|
19
|
+
private: z.boolean().optional().describe('Set repository visibility'),
|
|
20
|
+
hasIssues: z.boolean().optional().describe('Enable or disable issues'),
|
|
21
|
+
hasProjects: z.boolean().optional().describe('Enable or disable projects'),
|
|
22
|
+
hasWiki: z.boolean().optional().describe('Enable or disable wiki'),
|
|
23
|
+
defaultBranch: z.string().optional().describe('Change default branch'),
|
|
24
|
+
archived: z.boolean().optional().describe('Archive or unarchive the repository')
|
|
25
|
+
})
|
|
26
|
+
)
|
|
27
|
+
.output(
|
|
28
|
+
z.object({
|
|
29
|
+
repositoryId: z.number().describe('Unique repository ID'),
|
|
30
|
+
name: z.string().describe('Repository name'),
|
|
31
|
+
fullName: z.string().describe('Full name in owner/repo format'),
|
|
32
|
+
htmlUrl: z.string().describe('URL to the repository on GitHub'),
|
|
33
|
+
private: z.boolean().describe('Whether the repository is private'),
|
|
34
|
+
defaultBranch: z.string().describe('Default branch name'),
|
|
35
|
+
archived: z.boolean().describe('Whether the repository is archived')
|
|
36
|
+
})
|
|
37
|
+
)
|
|
38
|
+
.handleInvocation(async ctx => {
|
|
39
|
+
let client = new GitHubClient(ctx.auth.token);
|
|
40
|
+
let { owner, repo, ...updateData } = ctx.input;
|
|
41
|
+
let updated = await client.updateRepository(owner, repo, updateData);
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
output: {
|
|
45
|
+
repositoryId: updated.id,
|
|
46
|
+
name: updated.name,
|
|
47
|
+
fullName: updated.full_name,
|
|
48
|
+
htmlUrl: updated.html_url,
|
|
49
|
+
private: updated.private,
|
|
50
|
+
defaultBranch: updated.default_branch,
|
|
51
|
+
archived: updated.archived
|
|
52
|
+
},
|
|
53
|
+
message: `Updated repository **${updated.full_name}**.`
|
|
54
|
+
};
|
|
55
|
+
})
|
|
56
|
+
.build();
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { SlateTrigger } from 'slates';
|
|
2
|
+
import { spec } from '../spec';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
|
|
5
|
+
export let issueCommentTrigger = SlateTrigger.create(spec, {
|
|
6
|
+
name: 'Issue Comment',
|
|
7
|
+
key: 'issue_comment',
|
|
8
|
+
description:
|
|
9
|
+
'Triggered when a comment is created, edited, or deleted on an issue or pull request.'
|
|
10
|
+
})
|
|
11
|
+
.input(
|
|
12
|
+
z.object({
|
|
13
|
+
action: z.string().describe('Comment event action (created, edited, deleted)'),
|
|
14
|
+
owner: z.string().describe('Repository owner'),
|
|
15
|
+
repo: z.string().describe('Repository name'),
|
|
16
|
+
issueNumber: z.number().describe('Issue or PR number'),
|
|
17
|
+
issueTitle: z.string().describe('Issue or PR title'),
|
|
18
|
+
isPullRequest: z.boolean().describe('Whether the comment is on a pull request'),
|
|
19
|
+
commentId: z.number().describe('Comment ID'),
|
|
20
|
+
commentBody: z.string().describe('Comment body'),
|
|
21
|
+
commentAuthor: z.string().describe('Comment author login'),
|
|
22
|
+
commentHtmlUrl: z.string().describe('URL to the comment'),
|
|
23
|
+
commentCreatedAt: z.string().describe('Comment creation timestamp'),
|
|
24
|
+
deliveryId: z.string().describe('Webhook delivery ID')
|
|
25
|
+
})
|
|
26
|
+
)
|
|
27
|
+
.output(
|
|
28
|
+
z.object({
|
|
29
|
+
action: z.string().describe('Comment event action'),
|
|
30
|
+
owner: z.string().describe('Repository owner'),
|
|
31
|
+
repo: z.string().describe('Repository name'),
|
|
32
|
+
issueNumber: z.number().describe('Issue or PR number'),
|
|
33
|
+
issueTitle: z.string().describe('Issue or PR title'),
|
|
34
|
+
isPullRequest: z.boolean().describe('Whether the comment is on a pull request'),
|
|
35
|
+
commentId: z.number().describe('Comment ID'),
|
|
36
|
+
commentBody: z.string().describe('Comment body'),
|
|
37
|
+
commentAuthor: z.string().describe('Comment author login'),
|
|
38
|
+
commentHtmlUrl: z.string().describe('URL to the comment'),
|
|
39
|
+
commentCreatedAt: z.string().describe('Comment creation timestamp')
|
|
40
|
+
})
|
|
41
|
+
)
|
|
42
|
+
.webhook({
|
|
43
|
+
handleRequest: async ctx => {
|
|
44
|
+
let event = ctx.request.headers.get('x-github-event');
|
|
45
|
+
if (event !== 'issue_comment') {
|
|
46
|
+
return { inputs: [] };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
let data = (await ctx.request.json()) as any;
|
|
50
|
+
let comment = data.comment;
|
|
51
|
+
let issue = data.issue;
|
|
52
|
+
let deliveryId = ctx.request.headers.get('x-github-delivery') ?? '';
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
inputs: [
|
|
56
|
+
{
|
|
57
|
+
action: data.action,
|
|
58
|
+
owner: data.repository.owner.login,
|
|
59
|
+
repo: data.repository.name,
|
|
60
|
+
issueNumber: issue.number,
|
|
61
|
+
issueTitle: issue.title,
|
|
62
|
+
isPullRequest: !!issue.pull_request,
|
|
63
|
+
commentId: comment.id,
|
|
64
|
+
commentBody: comment.body,
|
|
65
|
+
commentAuthor: comment.user.login,
|
|
66
|
+
commentHtmlUrl: comment.html_url,
|
|
67
|
+
commentCreatedAt: comment.created_at,
|
|
68
|
+
deliveryId
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
};
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
handleEvent: async ctx => {
|
|
75
|
+
return {
|
|
76
|
+
type: `issue_comment.${ctx.input.action}`,
|
|
77
|
+
id: ctx.input.deliveryId,
|
|
78
|
+
output: {
|
|
79
|
+
action: ctx.input.action,
|
|
80
|
+
owner: ctx.input.owner,
|
|
81
|
+
repo: ctx.input.repo,
|
|
82
|
+
issueNumber: ctx.input.issueNumber,
|
|
83
|
+
issueTitle: ctx.input.issueTitle,
|
|
84
|
+
isPullRequest: ctx.input.isPullRequest,
|
|
85
|
+
commentId: ctx.input.commentId,
|
|
86
|
+
commentBody: ctx.input.commentBody,
|
|
87
|
+
commentAuthor: ctx.input.commentAuthor,
|
|
88
|
+
commentHtmlUrl: ctx.input.commentHtmlUrl,
|
|
89
|
+
commentCreatedAt: ctx.input.commentCreatedAt
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
})
|
|
94
|
+
.build();
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { SlateTrigger } from 'slates';
|
|
2
|
+
import { spec } from '../spec';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
|
|
5
|
+
export let issuesTrigger = SlateTrigger.create(spec, {
|
|
6
|
+
name: 'Issues',
|
|
7
|
+
key: 'issues',
|
|
8
|
+
description:
|
|
9
|
+
'Triggered for issue activity including opened, edited, closed, assigned, labeled, milestoned, and more.'
|
|
10
|
+
})
|
|
11
|
+
.input(
|
|
12
|
+
z.object({
|
|
13
|
+
action: z
|
|
14
|
+
.string()
|
|
15
|
+
.describe('Issue event action (e.g., opened, closed, edited, labeled)'),
|
|
16
|
+
owner: z.string().describe('Repository owner'),
|
|
17
|
+
repo: z.string().describe('Repository name'),
|
|
18
|
+
issueNumber: z.number().describe('Issue number'),
|
|
19
|
+
title: z.string().describe('Issue title'),
|
|
20
|
+
body: z.string().nullable().describe('Issue body'),
|
|
21
|
+
state: z.string().describe('Issue state'),
|
|
22
|
+
author: z.string().describe('Issue author login'),
|
|
23
|
+
htmlUrl: z.string().describe('URL to the issue'),
|
|
24
|
+
labels: z.array(z.string()).describe('Label names'),
|
|
25
|
+
assignees: z.array(z.string()).describe('Assigned usernames'),
|
|
26
|
+
milestoneName: z.string().nullable().describe('Milestone title'),
|
|
27
|
+
createdAt: z.string().describe('Creation timestamp'),
|
|
28
|
+
updatedAt: z.string().describe('Last update timestamp'),
|
|
29
|
+
closedAt: z.string().nullable().describe('Closure timestamp'),
|
|
30
|
+
deliveryId: z.string().describe('Webhook delivery ID')
|
|
31
|
+
})
|
|
32
|
+
)
|
|
33
|
+
.output(
|
|
34
|
+
z.object({
|
|
35
|
+
action: z.string().describe('Issue event action'),
|
|
36
|
+
owner: z.string().describe('Repository owner'),
|
|
37
|
+
repo: z.string().describe('Repository name'),
|
|
38
|
+
issueNumber: z.number().describe('Issue number'),
|
|
39
|
+
title: z.string().describe('Issue title'),
|
|
40
|
+
body: z.string().nullable().describe('Issue body'),
|
|
41
|
+
state: z.string().describe('Issue state'),
|
|
42
|
+
author: z.string().describe('Issue author login'),
|
|
43
|
+
htmlUrl: z.string().describe('URL to the issue'),
|
|
44
|
+
labels: z.array(z.string()).describe('Label names'),
|
|
45
|
+
assignees: z.array(z.string()).describe('Assigned usernames'),
|
|
46
|
+
milestoneName: z.string().nullable().describe('Milestone title'),
|
|
47
|
+
createdAt: z.string().describe('Creation timestamp'),
|
|
48
|
+
updatedAt: z.string().describe('Last update timestamp'),
|
|
49
|
+
closedAt: z.string().nullable().describe('Closure timestamp')
|
|
50
|
+
})
|
|
51
|
+
)
|
|
52
|
+
.webhook({
|
|
53
|
+
handleRequest: async ctx => {
|
|
54
|
+
let event = ctx.request.headers.get('x-github-event');
|
|
55
|
+
if (event !== 'issues') {
|
|
56
|
+
return { inputs: [] };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let data = (await ctx.request.json()) as any;
|
|
60
|
+
let issue = data.issue;
|
|
61
|
+
let deliveryId = ctx.request.headers.get('x-github-delivery') ?? '';
|
|
62
|
+
|
|
63
|
+
return {
|
|
64
|
+
inputs: [
|
|
65
|
+
{
|
|
66
|
+
action: data.action,
|
|
67
|
+
owner: data.repository.owner.login,
|
|
68
|
+
repo: data.repository.name,
|
|
69
|
+
issueNumber: issue.number,
|
|
70
|
+
title: issue.title,
|
|
71
|
+
body: issue.body,
|
|
72
|
+
state: issue.state,
|
|
73
|
+
author: issue.user.login,
|
|
74
|
+
htmlUrl: issue.html_url,
|
|
75
|
+
labels: (issue.labels ?? []).map((l: any) => l.name),
|
|
76
|
+
assignees: (issue.assignees ?? []).map((a: any) => a.login),
|
|
77
|
+
milestoneName: issue.milestone?.title ?? null,
|
|
78
|
+
createdAt: issue.created_at,
|
|
79
|
+
updatedAt: issue.updated_at,
|
|
80
|
+
closedAt: issue.closed_at ?? null,
|
|
81
|
+
deliveryId
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
};
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
handleEvent: async ctx => {
|
|
88
|
+
return {
|
|
89
|
+
type: `issue.${ctx.input.action}`,
|
|
90
|
+
id: ctx.input.deliveryId,
|
|
91
|
+
output: {
|
|
92
|
+
action: ctx.input.action,
|
|
93
|
+
owner: ctx.input.owner,
|
|
94
|
+
repo: ctx.input.repo,
|
|
95
|
+
issueNumber: ctx.input.issueNumber,
|
|
96
|
+
title: ctx.input.title,
|
|
97
|
+
body: ctx.input.body,
|
|
98
|
+
state: ctx.input.state,
|
|
99
|
+
author: ctx.input.author,
|
|
100
|
+
htmlUrl: ctx.input.htmlUrl,
|
|
101
|
+
labels: ctx.input.labels,
|
|
102
|
+
assignees: ctx.input.assignees,
|
|
103
|
+
milestoneName: ctx.input.milestoneName,
|
|
104
|
+
createdAt: ctx.input.createdAt,
|
|
105
|
+
updatedAt: ctx.input.updatedAt,
|
|
106
|
+
closedAt: ctx.input.closedAt
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
.build();
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { SlateTrigger } from 'slates';
|
|
2
|
+
import { spec } from '../spec';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
|
|
5
|
+
export let pullRequestReviewTrigger = SlateTrigger.create(spec, {
|
|
6
|
+
name: 'Pull Request Review',
|
|
7
|
+
key: 'pull_request_review',
|
|
8
|
+
description: 'Triggered when a pull request review is submitted, edited, or dismissed.'
|
|
9
|
+
})
|
|
10
|
+
.input(
|
|
11
|
+
z.object({
|
|
12
|
+
action: z.string().describe('Review event action (submitted, edited, dismissed)'),
|
|
13
|
+
owner: z.string().describe('Repository owner'),
|
|
14
|
+
repo: z.string().describe('Repository name'),
|
|
15
|
+
pullNumber: z.number().describe('Pull request number'),
|
|
16
|
+
pullTitle: z.string().describe('Pull request title'),
|
|
17
|
+
reviewId: z.number().describe('Review ID'),
|
|
18
|
+
reviewState: z
|
|
19
|
+
.string()
|
|
20
|
+
.describe('Review state (approved, changes_requested, commented, dismissed)'),
|
|
21
|
+
reviewBody: z.string().nullable().describe('Review body'),
|
|
22
|
+
reviewer: z.string().describe('Reviewer login'),
|
|
23
|
+
reviewHtmlUrl: z.string().describe('URL to the review'),
|
|
24
|
+
submittedAt: z.string().nullable().describe('Submission timestamp'),
|
|
25
|
+
deliveryId: z.string().describe('Webhook delivery ID')
|
|
26
|
+
})
|
|
27
|
+
)
|
|
28
|
+
.output(
|
|
29
|
+
z.object({
|
|
30
|
+
action: z.string().describe('Review event action'),
|
|
31
|
+
owner: z.string().describe('Repository owner'),
|
|
32
|
+
repo: z.string().describe('Repository name'),
|
|
33
|
+
pullNumber: z.number().describe('Pull request number'),
|
|
34
|
+
pullTitle: z.string().describe('Pull request title'),
|
|
35
|
+
reviewId: z.number().describe('Review ID'),
|
|
36
|
+
reviewState: z.string().describe('Review state'),
|
|
37
|
+
reviewBody: z.string().nullable().describe('Review body'),
|
|
38
|
+
reviewer: z.string().describe('Reviewer login'),
|
|
39
|
+
reviewHtmlUrl: z.string().describe('URL to the review'),
|
|
40
|
+
submittedAt: z.string().nullable().describe('Submission timestamp')
|
|
41
|
+
})
|
|
42
|
+
)
|
|
43
|
+
.webhook({
|
|
44
|
+
handleRequest: async ctx => {
|
|
45
|
+
let event = ctx.request.headers.get('x-github-event');
|
|
46
|
+
if (event !== 'pull_request_review') {
|
|
47
|
+
return { inputs: [] };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let data = (await ctx.request.json()) as any;
|
|
51
|
+
let review = data.review;
|
|
52
|
+
let pr = data.pull_request;
|
|
53
|
+
let deliveryId = ctx.request.headers.get('x-github-delivery') ?? '';
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
inputs: [
|
|
57
|
+
{
|
|
58
|
+
action: data.action,
|
|
59
|
+
owner: data.repository.owner.login,
|
|
60
|
+
repo: data.repository.name,
|
|
61
|
+
pullNumber: pr.number,
|
|
62
|
+
pullTitle: pr.title,
|
|
63
|
+
reviewId: review.id,
|
|
64
|
+
reviewState: review.state,
|
|
65
|
+
reviewBody: review.body,
|
|
66
|
+
reviewer: review.user.login,
|
|
67
|
+
reviewHtmlUrl: review.html_url,
|
|
68
|
+
submittedAt: review.submitted_at ?? null,
|
|
69
|
+
deliveryId
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
};
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
handleEvent: async ctx => {
|
|
76
|
+
return {
|
|
77
|
+
type: `pull_request_review.${ctx.input.action}`,
|
|
78
|
+
id: ctx.input.deliveryId,
|
|
79
|
+
output: {
|
|
80
|
+
action: ctx.input.action,
|
|
81
|
+
owner: ctx.input.owner,
|
|
82
|
+
repo: ctx.input.repo,
|
|
83
|
+
pullNumber: ctx.input.pullNumber,
|
|
84
|
+
pullTitle: ctx.input.pullTitle,
|
|
85
|
+
reviewId: ctx.input.reviewId,
|
|
86
|
+
reviewState: ctx.input.reviewState,
|
|
87
|
+
reviewBody: ctx.input.reviewBody,
|
|
88
|
+
reviewer: ctx.input.reviewer,
|
|
89
|
+
reviewHtmlUrl: ctx.input.reviewHtmlUrl,
|
|
90
|
+
submittedAt: ctx.input.submittedAt
|
|
91
|
+
}
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
})
|
|
95
|
+
.build();
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { SlateTrigger } from 'slates';
|
|
2
|
+
import { spec } from '../spec';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
|
|
5
|
+
export let pullRequestTrigger = SlateTrigger.create(spec, {
|
|
6
|
+
name: 'Pull Request',
|
|
7
|
+
key: 'pull_request',
|
|
8
|
+
description:
|
|
9
|
+
'Triggered for pull request activity including opened, closed, merged, assigned, labeled, review requested, synchronized, and more.'
|
|
10
|
+
})
|
|
11
|
+
.input(
|
|
12
|
+
z.object({
|
|
13
|
+
action: z
|
|
14
|
+
.string()
|
|
15
|
+
.describe('PR event action (e.g., opened, closed, synchronize, labeled)'),
|
|
16
|
+
owner: z.string().describe('Repository owner'),
|
|
17
|
+
repo: z.string().describe('Repository name'),
|
|
18
|
+
pullNumber: z.number().describe('Pull request number'),
|
|
19
|
+
title: z.string().describe('PR title'),
|
|
20
|
+
body: z.string().nullable().describe('PR body'),
|
|
21
|
+
state: z.string().describe('PR state'),
|
|
22
|
+
author: z.string().describe('PR author login'),
|
|
23
|
+
head: z.string().describe('Head branch ref'),
|
|
24
|
+
base: z.string().describe('Base branch ref'),
|
|
25
|
+
htmlUrl: z.string().describe('URL to the PR'),
|
|
26
|
+
draft: z.boolean().describe('Whether the PR is a draft'),
|
|
27
|
+
merged: z.boolean().describe('Whether the PR was merged'),
|
|
28
|
+
mergedBy: z.string().nullable().describe('User who merged the PR'),
|
|
29
|
+
labels: z.array(z.string()).describe('Label names'),
|
|
30
|
+
assignees: z.array(z.string()).describe('Assigned usernames'),
|
|
31
|
+
createdAt: z.string().describe('Creation timestamp'),
|
|
32
|
+
updatedAt: z.string().describe('Last update timestamp'),
|
|
33
|
+
deliveryId: z.string().describe('Webhook delivery ID')
|
|
34
|
+
})
|
|
35
|
+
)
|
|
36
|
+
.output(
|
|
37
|
+
z.object({
|
|
38
|
+
action: z.string().describe('PR event action'),
|
|
39
|
+
owner: z.string().describe('Repository owner'),
|
|
40
|
+
repo: z.string().describe('Repository name'),
|
|
41
|
+
pullNumber: z.number().describe('Pull request number'),
|
|
42
|
+
title: z.string().describe('PR title'),
|
|
43
|
+
body: z.string().nullable().describe('PR body'),
|
|
44
|
+
state: z.string().describe('PR state'),
|
|
45
|
+
author: z.string().describe('PR author login'),
|
|
46
|
+
head: z.string().describe('Head branch ref'),
|
|
47
|
+
base: z.string().describe('Base branch ref'),
|
|
48
|
+
htmlUrl: z.string().describe('URL to the PR'),
|
|
49
|
+
draft: z.boolean().describe('Whether the PR is a draft'),
|
|
50
|
+
merged: z.boolean().describe('Whether the PR was merged'),
|
|
51
|
+
mergedBy: z.string().nullable().describe('User who merged the PR'),
|
|
52
|
+
labels: z.array(z.string()).describe('Label names'),
|
|
53
|
+
assignees: z.array(z.string()).describe('Assigned usernames'),
|
|
54
|
+
createdAt: z.string().describe('Creation timestamp'),
|
|
55
|
+
updatedAt: z.string().describe('Last update timestamp')
|
|
56
|
+
})
|
|
57
|
+
)
|
|
58
|
+
.webhook({
|
|
59
|
+
handleRequest: async ctx => {
|
|
60
|
+
let event = ctx.request.headers.get('x-github-event');
|
|
61
|
+
if (event !== 'pull_request') {
|
|
62
|
+
return { inputs: [] };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let data = (await ctx.request.json()) as any;
|
|
66
|
+
let pr = data.pull_request;
|
|
67
|
+
let deliveryId = ctx.request.headers.get('x-github-delivery') ?? '';
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
inputs: [
|
|
71
|
+
{
|
|
72
|
+
action: data.action,
|
|
73
|
+
owner: data.repository.owner.login,
|
|
74
|
+
repo: data.repository.name,
|
|
75
|
+
pullNumber: pr.number,
|
|
76
|
+
title: pr.title,
|
|
77
|
+
body: pr.body,
|
|
78
|
+
state: pr.state,
|
|
79
|
+
author: pr.user.login,
|
|
80
|
+
head: pr.head.ref,
|
|
81
|
+
base: pr.base.ref,
|
|
82
|
+
htmlUrl: pr.html_url,
|
|
83
|
+
draft: pr.draft ?? false,
|
|
84
|
+
merged: pr.merged ?? false,
|
|
85
|
+
mergedBy: pr.merged_by?.login ?? null,
|
|
86
|
+
labels: (pr.labels ?? []).map((l: any) => l.name),
|
|
87
|
+
assignees: (pr.assignees ?? []).map((a: any) => a.login),
|
|
88
|
+
createdAt: pr.created_at,
|
|
89
|
+
updatedAt: pr.updated_at,
|
|
90
|
+
deliveryId
|
|
91
|
+
}
|
|
92
|
+
]
|
|
93
|
+
};
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
handleEvent: async ctx => {
|
|
97
|
+
return {
|
|
98
|
+
type: `pull_request.${ctx.input.action}`,
|
|
99
|
+
id: ctx.input.deliveryId,
|
|
100
|
+
output: {
|
|
101
|
+
action: ctx.input.action,
|
|
102
|
+
owner: ctx.input.owner,
|
|
103
|
+
repo: ctx.input.repo,
|
|
104
|
+
pullNumber: ctx.input.pullNumber,
|
|
105
|
+
title: ctx.input.title,
|
|
106
|
+
body: ctx.input.body,
|
|
107
|
+
state: ctx.input.state,
|
|
108
|
+
author: ctx.input.author,
|
|
109
|
+
head: ctx.input.head,
|
|
110
|
+
base: ctx.input.base,
|
|
111
|
+
htmlUrl: ctx.input.htmlUrl,
|
|
112
|
+
draft: ctx.input.draft,
|
|
113
|
+
merged: ctx.input.merged,
|
|
114
|
+
mergedBy: ctx.input.mergedBy,
|
|
115
|
+
labels: ctx.input.labels,
|
|
116
|
+
assignees: ctx.input.assignees,
|
|
117
|
+
createdAt: ctx.input.createdAt,
|
|
118
|
+
updatedAt: ctx.input.updatedAt
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
.build();
|