diff --git a/src/index.ts b/src/index.ts index 38554ba..ce9991d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ import { EmitterWebhookEvent } from "@octokit/webhooks"; import { APIGatewayEvent, APIGatewayProxyResult } from "aws-lambda"; import { App } from "octokit"; +import { safeOctokitRequest } from "./utils"; const app = new App({ appId: process.env.APP_ID!, @@ -34,7 +35,7 @@ async function run({ payload }: EmitterWebhookEvent<"pull_request">) { const octokit = await app.getInstallationOctokit(payload.installation!.id); if (!payload.pull_request.merged) { - await octokit.rest.issues.createComment({ + await safeOctokitRequest(octokit.rest.issues.createComment, { body: "Pull request was closed without merging.", issue_number: payload.pull_request.number, owner: payload.repository.owner.login, @@ -44,23 +45,19 @@ async function run({ payload }: EmitterWebhookEvent<"pull_request">) { return; } - const { data, status } = await octokit.rest.issues.createComment({ + const { id: commentId } = await safeOctokitRequest(octokit.rest.issues.createComment, { body: "Running `multi-gitter`...", issue_number: payload.pull_request.number, owner: payload.repository.owner.login, repo: payload.repository.name, }); - if (!(status >= 200 && status < 300)) { - return; - } - - await octokit.rest.issues.updateComment({ + await safeOctokitRequest(octokit.rest.issues.updateComment, { body: "Done running `multi-gitter`.", issue_number: payload.pull_request.number, owner: payload.repository.owner.login, repo: payload.repository.name, - comment_id: data.id, + comment_id: commentId, }); // check verification status @@ -71,22 +68,18 @@ async function run({ payload }: EmitterWebhookEvent<"pull_request">) { async function verify({ payload }: EmitterWebhookEvent<"pull_request">) { const octokit = await app.getInstallationOctokit(payload.installation!.id); - const { data, status } = await octokit.rest.issues.createComment({ + const { id: commentId } = await safeOctokitRequest(octokit.rest.issues.createComment, { body: "Verifying pull request contents...", issue_number: payload.pull_request.number, owner: payload.repository.owner.login, repo: payload.repository.name, }); - if (!(status >= 200 && status < 300)) { - return; - } - - await octokit.rest.issues.updateComment({ + await safeOctokitRequest(octokit.rest.issues.updateComment, { body: "Done verifying.", issue_number: payload.pull_request.number, owner: payload.repository.owner.login, repo: payload.repository.name, - comment_id: data.id, + comment_id: commentId, }); } diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 0000000..8b6e721 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,41 @@ +import { RequestError } from "octokit"; + +function camelCaseToSentenceCase(str: string) { + return str.replace( + /([a-z])([A-Z])/g, + (_, lower: string, upper: string) => `${lower} ${upper.toLowerCase()}` + ); +} + +// TODO: figure out how to type this to restrict the method to only +// those which are available on the `octokit.rest` instance + +/** + * Calls an Octokit method, logging any errors that occur. + * + * @param method Octokit method to call + * @param params parameters to pass to the method + * + * @returns the `data` property of the response + * + * @todo figure out how to type this to restrict the method to only those which are available on the `octokit.rest` instance + */ +export async function safeOctokitRequest any>( + method: Method, + ...params: Parameters +): Promise>["data"]> { + try { + const response = await method(params); + return response.data; + } catch (error) { + if (error instanceof RequestError) { + console.error( + "Failed to %s: got HTTP %s response.", + camelCaseToSentenceCase(method.name), + error.status + ); + } + console.error(error); + throw error; + } +}