From df19ac68bfbdb9903418acfc8aa9228f9770c65d Mon Sep 17 00:00:00 2001 From: Harry Marr Date: Sat, 2 Apr 2022 15:50:40 +0100 Subject: [PATCH] Handle GITHUB_TOKEN 403 error gracefully --- dist/index.js | 24 +++++++++++++++++++++--- src/approve.test.ts | 24 +++++++++++++++++++++++- src/approve.ts | 25 ++++++++++++++++++++++--- 3 files changed, 66 insertions(+), 7 deletions(-) diff --git a/dist/index.js b/dist/index.js index 4a7518a..f5c3ac7 100644 --- a/dist/index.js +++ b/dist/index.js @@ -8355,8 +8355,8 @@ function approve(token, context, prNumber) { const client = github.getOctokit(token); try { core.info(`Getting current user info`); - const { data: user } = yield client.rest.users.getAuthenticated(); - core.info(`Current user is ${user.login}`); + const login = yield getLoginForToken(client); + core.info(`Current user is ${login}`); core.info(`Getting pull request #${prNumber} info`); const pull_request = yield client.rest.pulls.get({ owner: context.repo.owner, @@ -8372,7 +8372,7 @@ function approve(token, context, prNumber) { pull_number: prNumber, }); for (const review of reviews.data) { - if (((_b = review.user) === null || _b === void 0 ? void 0 : _b.login) == user.login && + if (((_b = review.user) === null || _b === void 0 ? void 0 : _b.login) == login && review.commit_id == commit && review.state == "APPROVED") { core.info(`Current user already approved pull request #${prNumber}, nothing to do`); @@ -8427,6 +8427,24 @@ function approve(token, context, prNumber) { }); } exports.approve = approve; +function getLoginForToken(client) { + return __awaiter(this, void 0, void 0, function* () { + try { + const { data: user } = yield client.rest.users.getAuthenticated(); + return user.login; + } + catch (error) { + if (error instanceof request_error_1.RequestError) { + // If you use the GITHUB_TOKEN provided by GitHub Actions to fetch the current user + // you get a 403. For now we'll assume any 403 means this is an Actions token. + if (error.status === 403) { + return "github-actions[bot]"; + } + } + throw error; + } + }); +} /***/ }), diff --git a/src/approve.test.ts b/src/approve.test.ts index cc797e7..41890be 100644 --- a/src/approve.test.ts +++ b/src/approve.test.ts @@ -20,7 +20,7 @@ afterEach(() => { process.env = originalEnv; }); -test("when a review is successfully created", async () => { +test("a review is successfully created with a PAT", async () => { nock("https://api.github.com").get("/user").reply(200, { login: "hmarr" }); nock("https://api.github.com") @@ -42,6 +42,28 @@ test("when a review is successfully created", async () => { ); }); +test("a review is successfully created with an Actions token", async () => { + nock("https://api.github.com").get("/user").reply(403, {}); + + nock("https://api.github.com") + .get("/repos/hmarr/test/pulls/101") + .reply(200, { head: { sha: "24c5451bbf1fb09caa3ac8024df4788aff4d4974" } }); + + nock("https://api.github.com") + .get("/repos/hmarr/test/pulls/101/reviews") + .reply(200, []); + + nock("https://api.github.com") + .post("/repos/hmarr/test/pulls/101/reviews") + .reply(200, { id: 1 }); + + await approve("gh-tok", ghContext()); + + expect(core.info).toHaveBeenCalledWith( + expect.stringContaining("Approved pull request #101") + ); +}); + test("when a review is successfully created using pull-request-number", async () => { nock("https://api.github.com").get("/user").reply(200, { login: "hmarr" }); diff --git a/src/approve.ts b/src/approve.ts index 4f29c82..9903ee9 100644 --- a/src/approve.ts +++ b/src/approve.ts @@ -2,6 +2,7 @@ import * as core from "@actions/core"; import * as github from "@actions/github"; import { RequestError } from "@octokit/request-error"; import { Context } from "@actions/github/lib/context"; +import { GitHub } from "@actions/github/lib/utils"; export async function approve( token: string, @@ -24,8 +25,8 @@ export async function approve( try { core.info(`Getting current user info`); - const { data: user } = await client.rest.users.getAuthenticated(); - core.info(`Current user is ${user.login}`); + const login = await getLoginForToken(client); + core.info(`Current user is ${login}`); core.info(`Getting pull request #${prNumber} info`); const pull_request = await client.rest.pulls.get({ @@ -48,7 +49,7 @@ export async function approve( for (const review of reviews.data) { if ( - review.user?.login == user.login && + review.user?.login == login && review.commit_id == commit && review.state == "APPROVED" ) { @@ -114,3 +115,21 @@ export async function approve( return; } } + +async function getLoginForToken( + client: InstanceType +): Promise { + try { + const { data: user } = await client.rest.users.getAuthenticated(); + return user.login; + } catch (error) { + if (error instanceof RequestError) { + // If you use the GITHUB_TOKEN provided by GitHub Actions to fetch the current user + // you get a 403. For now we'll assume any 403 means this is an Actions token. + if (error.status === 403) { + return "github-actions[bot]"; + } + } + throw error; + } +}