generated from slack-samples/deno-starter-template
/
create_issue.ts
128 lines (117 loc) · 3.71 KB
/
create_issue.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { DefineFunction, Schema, SlackFunction } from "deno-slack-sdk/mod.ts";
/**
* Functions are reusable building blocks of automation that accept inputs,
* perform calculations, and provide outputs. Functions can be used as steps in
* a workflow or independently.
* Learn more: https://api.slack.com/automation/functions/custom
*/
export const CreateIssueDefinition = DefineFunction({
callback_id: "create_issue",
title: "Create GitHub issue",
description: "Create a new GitHub issue in a repository",
source_file: "functions/create_issue.ts", // The file with the exported function handler
input_parameters: {
properties: {
githubAccessTokenId: {
type: Schema.slack.types.oauth2,
oauth2_provider_key: "github",
},
url: {
type: Schema.types.string,
description: "Repository URL",
},
title: {
type: Schema.types.string,
description: "Issue Title",
},
description: {
type: Schema.types.string,
description: "Issue Description",
},
assignees: {
type: Schema.types.string,
description: "Assignees",
},
},
required: [
"githubAccessTokenId",
"url",
"title",
],
},
output_parameters: {
properties: {
GitHubIssueNumber: {
type: Schema.types.number,
description: "Issue number",
},
GitHubIssueLink: {
type: Schema.types.string,
description: "Issue link",
},
},
required: ["GitHubIssueNumber", "GitHubIssueLink"],
},
});
/**
* The default export for a custom function accepts a function definition
* and a function handler that contains the custom logic for the function.
*/
export default SlackFunction(
CreateIssueDefinition,
async ({ inputs, client }) => {
/**
* Gather the stored external authentication access token using the access
* token id passed from the workflow's input. This token can be used to
* authorize requests made to an external service on behalf of the user.
*/
const token = await client.apps.auth.external.get({
external_token_id: inputs.githubAccessTokenId,
});
if (!token.ok) throw new Error("Failed to access auth token");
const headers = {
Accept: "application/vnd.github+json",
Authorization: `Bearer ${token.external_token}`,
"Content-Type": "application/json",
"X-GitHub-Api-Version": "2022-11-28",
};
const { url, title, description, assignees } = inputs;
try {
const { hostname, pathname } = new URL(url);
const [_, owner, repo] = pathname.split("/");
// https://docs.github.com/en/enterprise-server@3.3/rest/guides/getting-started-with-the-rest-api
const apiURL = hostname === "github.com"
? "api.github.com"
: `${hostname}/api/v3`;
// https://docs.github.com/en/rest/issues/issues#create-an-issue
const issueEndpoint = `https://${apiURL}/repos/${owner}/${repo}/issues`;
const body = JSON.stringify({
title,
body: description,
assignees: assignees?.split(",").map((assignee: string) => {
return assignee.trim();
}),
});
const issue = await fetch(issueEndpoint, {
method: "POST",
headers,
body,
}).then((res: Response) => {
if (res.status === 201) return res.json();
else throw new Error(`${res.status}: ${res.statusText}`);
});
return {
outputs: {
GitHubIssueNumber: issue.number,
GitHubIssueLink: issue.html_url,
},
};
} catch (err) {
console.error(err);
return {
error:
`An error was encountered during issue creation: \`${err.message}\``,
};
}
},
);