From ee043b82a0180bc0072d05818fb7065fb9fa984e Mon Sep 17 00:00:00 2001 From: uzhenaliev Date: Thu, 1 Feb 2024 03:09:57 +0600 Subject: [PATCH] 1 --- dist/index.js | 168 ++++++++++++++++++++++++----- lib/handle-pull-request-comment.ts | 107 ++++++++++++++++++ lib/handle-pull-request.ts | 28 +++-- lib/handle-schedule.ts | 6 +- lib/index.ts | 10 +- lib/utils.ts | 34 +++--- 6 files changed, 293 insertions(+), 60 deletions(-) create mode 100644 lib/handle-pull-request-comment.ts diff --git a/dist/index.js b/dist/index.js index 3e5a376..1150da6 100644 --- a/dist/index.js +++ b/dist/index.js @@ -9564,6 +9564,108 @@ async function getCommitStatusesStatus(octokit, commitRef) { exports.getCommitStatusesStatus = getCommitStatusesStatus; +/***/ }), + +/***/ 3285: +/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { + +"use strict"; + +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", ({ value: true })); +const core = __importStar(__nccwpck_require__(2186)); +const github = __importStar(__nccwpck_require__(5438)); +const fs_1 = __nccwpck_require__(7147); +const locale_date_1 = __importDefault(__nccwpck_require__(3663)); +const utils_1 = __nccwpck_require__(1715); +const comment_1 = __nccwpck_require__(8111); +/** + * Handle "pull_request" event + */ +async function handlePullRequestComment() { + if (!process.env.GITHUB_TOKEN) { + core.setFailed("GITHUB_TOKEN environment variable is not set"); + return; + } + const octokit = github.getOctokit(process.env.GITHUB_TOKEN); + const eventPayload = JSON.parse((0, fs_1.readFileSync)(process.env.GITHUB_EVENT_PATH, { encoding: "utf8" })); + const issue = eventPayload.issue; + core.info(`Handling issue ${eventPayload.action} for ${issue.html_url}`); + if (issue.state !== "open") { + core.info("Issue already closed, ignoring"); + return; + } + const previousComment = await (0, comment_1.getPreviousComment)(octokit, issue.number); + const scheduledDate = await (0, utils_1.findScheduleDateCommand)(issue.number, octokit); + if (scheduledDate) { + core.info(`Schedule date found: "${scheduledDate}"`); + } + else { + if (previousComment) { + await (0, comment_1.deleteComment)(octokit, previousComment.id); + } + core.info("No /schedule command found"); + return; + } + let commentBody; + if (scheduledDate) { + if (!(0, utils_1.isValidDate)(scheduledDate)) { + commentBody = (0, comment_1.generateBody)(`"${scheduledDate}" is not a valid date`, "error"); + } + else if (new Date(scheduledDate) < (0, locale_date_1.default)()) { + let message = `${(0, utils_1.stringifyDate)(scheduledDate)} (UTC) is already in the past`; + if (process.env.INPUT_TIME_ZONE !== "UTC") { + message = `${message} on ${process.env.INPUT_TIME_ZONE} time zone`; + } + commentBody = (0, comment_1.generateBody)(message, "warning"); + } + else { + commentBody = (0, comment_1.generateBody)(`Scheduled to be merged on ${(0, utils_1.stringifyDate)(scheduledDate)} (UTC)`, "pending"); + } + } + else { + commentBody = (0, comment_1.generateBody)(`Scheduled to be merged the next time the merge action is scheduled via the cron expressions`, "pending"); + } + if (previousComment) { + if (previousComment.body === commentBody) { + core.info("Comment already up to date"); + return; + } + const { data } = await (0, comment_1.updateComment)(octokit, previousComment.id, commentBody); + core.info(`Comment updated: ${data.html_url}`); + return; + } + const { data } = await (0, comment_1.createComment)(octokit, issue.number, commentBody); + core.info(`Comment created: ${data.html_url}`); +} +exports["default"] = handlePullRequestComment; + + /***/ }), /***/ 2719: @@ -9625,32 +9727,31 @@ async function handlePullRequest() { return; } const previousComment = await (0, comment_1.getPreviousComment)(octokit, pullRequest.number); - const prHasScheduledCommand = await (0, utils_1.hasScheduledCommand)(pullRequest, octokit); - if (!prHasScheduledCommand) { + const scheduledDate = await (0, utils_1.findScheduleDateCommand)(pullRequest.number, octokit); + if (scheduledDate) { + core.info(`Schedule date found: "${scheduledDate}"`); + } + else { if (previousComment) { await (0, comment_1.deleteComment)(octokit, previousComment.id); } core.info("No /schedule command found"); return; } - const dateString = (0, utils_1.getScheduleDateString)(pullRequest.body); - if (dateString) { - core.info(`Schedule date found: "${dateString}"`); - } - let commentBody = ""; - if (dateString) { - if (!(0, utils_1.isValidDate)(dateString)) { - commentBody = (0, comment_1.generateBody)(`"${dateString}" is not a valid date`, "error"); + let commentBody; + if (scheduledDate) { + if (!(0, utils_1.isValidDate)(scheduledDate)) { + commentBody = (0, comment_1.generateBody)(`"${scheduledDate}" is not a valid date`, "error"); } - else if (new Date(dateString) < (0, locale_date_1.default)()) { - let message = `${(0, utils_1.stringifyDate)(dateString)} (UTC) is already in the past`; + else if (new Date(scheduledDate) < (0, locale_date_1.default)()) { + let message = `${(0, utils_1.stringifyDate)(scheduledDate)} (UTC) is already in the past`; if (process.env.INPUT_TIME_ZONE !== "UTC") { message = `${message} on ${process.env.INPUT_TIME_ZONE} time zone`; } commentBody = (0, comment_1.generateBody)(message, "warning"); } else { - commentBody = (0, comment_1.generateBody)(`Scheduled to be merged on ${(0, utils_1.stringifyDate)(dateString)} (UTC)`, "pending"); + commentBody = (0, comment_1.generateBody)(`Scheduled to be merged on ${(0, utils_1.stringifyDate)(scheduledDate)} (UTC)`, "pending"); } } else { @@ -9737,7 +9838,7 @@ async function handleSchedule() { console.info(responseData); return responseData .filter((pullRequest) => !(0, utils_1.isFork)(pullRequest)) - .filter((pullRequest) => (0, utils_1.hasScheduledCommand)(pullRequest, octokit)) + .filter((pullRequest) => (0, utils_1.findScheduleDateCommand)(pullRequest.number, octokit)) .filter((pullRequest) => pullRequest.labels.every((label) => label.name !== automergeFailLabel)) .map((pullRequest) => { return { @@ -9854,14 +9955,18 @@ const core = __importStar(__nccwpck_require__(2186)); const github = __importStar(__nccwpck_require__(5438)); const handle_pull_request_1 = __importDefault(__nccwpck_require__(2719)); const handle_schedule_1 = __importDefault(__nccwpck_require__(7976)); +const handle_pull_request_comment_1 = __importDefault(__nccwpck_require__(3285)); main(); async function main() { try { - core.info(github.context.eventName); - if (github.context.eventName === "pull_request" || github.context.eventName === "issue_comment") { + if (github.context.eventName === "pull_request") { await (0, handle_pull_request_1.default)(); return; } + if (github.context.eventName === "issue_comment") { + await (0, handle_pull_request_comment_1.default)(); + return; + } await (0, handle_schedule_1.default)(); } catch (error) { @@ -9918,23 +10023,32 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.stringifyDate = exports.isValidDate = exports.isValidMergeMethod = exports.getScheduleDateString = exports.isFork = exports.hasScheduledCommand = void 0; +exports.stringifyDate = exports.isValidDate = exports.isValidMergeMethod = exports.getScheduleDateString = exports.isFork = exports.findScheduleDateCommand = void 0; const github = __importStar(__nccwpck_require__(5438)); const core = __importStar(__nccwpck_require__(2186)); -async function hasScheduledCommand(pullRequest, octokit) { - const bodyContains = pullRequest.body != null ? /(^|\n)\/schedule/.test(pullRequest.body) : false; - const prComments = await octokit.paginate(octokit.rest.issues.listComments, { +async function findScheduleDateCommand(pullRequestId, octokit) { + const pullRequestResponse = await octokit.rest.pulls.get({ + ...github.context.repo, + pull_number: pullRequestId, + }); + const bodyDate = getScheduleDateString(pullRequestResponse.data.body); + const commentDates = await octokit.paginate(octokit.rest.issues.listComments, { ...github.context.repo, - issue_number: pullRequest.number, + issue_number: pullRequestResponse.data.number, }, (response) => { - return response.data.filter((comment) => /(^|\n)\/schedule/.test(comment.body ?? "")); + return response + .data + .flatMap((comment) => getScheduleDateString(comment.body ?? "")) + .filter(Boolean) + .map((dateString) => new Date(dateString).toISOString()); }); - core.info(`PrComments: ${prComments}`); - const last = prComments.pop; - core.info(`Last pr comment: ${last}`); - return bodyContains || last != undefined; + commentDates.unshift(bodyDate); + core.info(`Dates: ${commentDates}`); + const lastDate = commentDates.pop() ?? ""; + core.info(`Last date: ${lastDate}`); + return lastDate; } -exports.hasScheduledCommand = hasScheduledCommand; +exports.findScheduleDateCommand = findScheduleDateCommand; function isFork(pullRequest) { return pullRequest.head.repo.fork; } diff --git a/lib/handle-pull-request-comment.ts b/lib/handle-pull-request-comment.ts new file mode 100644 index 0000000..bec3971 --- /dev/null +++ b/lib/handle-pull-request-comment.ts @@ -0,0 +1,107 @@ +import * as core from "@actions/core"; +import * as github from "@actions/github"; +import {readFileSync} from "fs"; +import localeDate from "./locale-date"; +import { + IssueCommentEvent, +} from "@octokit/webhooks-types"; +import { + findScheduleDateCommand, + isValidDate, + stringifyDate, +} from "./utils"; +import { + createComment, + deleteComment, + generateBody, + getPreviousComment, + updateComment, +} from "./comment"; + +/** + * Handle "pull_request" event + */ +export default async function handlePullRequestComment(): Promise { + if (!process.env.GITHUB_TOKEN) { + core.setFailed("GITHUB_TOKEN environment variable is not set"); + return; + } + + const octokit = github.getOctokit(process.env.GITHUB_TOKEN); + + const eventPayload = JSON.parse( + readFileSync(process.env.GITHUB_EVENT_PATH, {encoding: "utf8"}) + ) as IssueCommentEvent; + + const issue = eventPayload.issue; + + core.info( + `Handling issue ${eventPayload.action} for ${issue.html_url}` + ); + + if (issue.state !== "open") { + core.info("Issue already closed, ignoring"); + return; + } + + const previousComment = await getPreviousComment(octokit, issue.number); + const scheduledDate: string = await findScheduleDateCommand(issue.number, octokit); + + if (scheduledDate) { + core.info(`Schedule date found: "${scheduledDate}"`); + } else { + if (previousComment) { + await deleteComment(octokit, previousComment.id); + } + core.info("No /schedule command found"); + return; + } + + let commentBody: string; + + if (scheduledDate) { + if (!isValidDate(scheduledDate)) { + commentBody = generateBody( + `"${scheduledDate}" is not a valid date`, + "error" + ); + } else if (new Date(scheduledDate) < localeDate()) { + let message = `${stringifyDate(scheduledDate)} (UTC) is already in the past`; + if (process.env.INPUT_TIME_ZONE !== "UTC") { + message = `${message} on ${process.env.INPUT_TIME_ZONE} time zone`; + } + commentBody = generateBody(message, "warning"); + } else { + commentBody = generateBody( + `Scheduled to be merged on ${stringifyDate(scheduledDate)} (UTC)`, + "pending" + ); + } + } else { + commentBody = generateBody( + `Scheduled to be merged the next time the merge action is scheduled via the cron expressions`, + "pending" + ); + } + + if (previousComment) { + if (previousComment.body === commentBody) { + core.info("Comment already up to date"); + return; + } + const {data} = await updateComment( + octokit, + previousComment.id, + commentBody + ); + core.info(`Comment updated: ${data.html_url}`); + return; + } + + const {data} = await createComment( + octokit, + issue.number, + commentBody + ); + core.info(`Comment created: ${data.html_url}`); +} diff --git a/lib/handle-pull-request.ts b/lib/handle-pull-request.ts index e57b6bb..f46b73f 100644 --- a/lib/handle-pull-request.ts +++ b/lib/handle-pull-request.ts @@ -8,7 +8,7 @@ import type { } from "@octokit/webhooks-types"; import { getScheduleDateString, - hasScheduledCommand, + findScheduleDateCommand, isFork, isValidDate, stringifyDate, @@ -35,6 +35,7 @@ export default async function handlePullRequest(): Promise { const eventPayload = JSON.parse( readFileSync(process.env.GITHUB_EVENT_PATH, {encoding: "utf8"}) ) as PullRequestEvent; + const pullRequest = eventPayload.pull_request; core.info( @@ -52,9 +53,11 @@ export default async function handlePullRequest(): Promise { } const previousComment = await getPreviousComment(octokit, pullRequest.number); - const prHasScheduledCommand = await hasScheduledCommand(pullRequest, octokit); + const scheduledDate = await findScheduleDateCommand(pullRequest.number, octokit); - if (!prHasScheduledCommand) { + if (scheduledDate) { + core.info(`Schedule date found: "${scheduledDate}"`); + } else { if (previousComment) { await deleteComment(octokit, previousComment.id); } @@ -62,28 +65,23 @@ export default async function handlePullRequest(): Promise { return; } - const dateString = getScheduleDateString(pullRequest.body); - if (dateString) { - core.info(`Schedule date found: "${dateString}"`); - } - - let commentBody = ""; + let commentBody: string; - if (dateString) { - if (!isValidDate(dateString)) { + if (scheduledDate) { + if (!isValidDate(scheduledDate)) { commentBody = generateBody( - `"${dateString}" is not a valid date`, + `"${scheduledDate}" is not a valid date`, "error" ); - } else if (new Date(dateString) < localeDate()) { - let message = `${stringifyDate(dateString)} (UTC) is already in the past`; + } else if (new Date(scheduledDate) < localeDate()) { + let message = `${stringifyDate(scheduledDate)} (UTC) is already in the past`; if (process.env.INPUT_TIME_ZONE !== "UTC") { message = `${message} on ${process.env.INPUT_TIME_ZONE} time zone`; } commentBody = generateBody(message, "warning"); } else { commentBody = generateBody( - `Scheduled to be merged on ${stringifyDate(dateString)} (UTC)`, + `Scheduled to be merged on ${stringifyDate(scheduledDate)} (UTC)`, "pending" ); } diff --git a/lib/handle-schedule.ts b/lib/handle-schedule.ts index 87b5df6..21b8082 100644 --- a/lib/handle-schedule.ts +++ b/lib/handle-schedule.ts @@ -1,6 +1,6 @@ import * as core from "@actions/core"; import * as github from "@actions/github"; -import type {PullRequest, SimplePullRequest} from "@octokit/webhooks-types"; +import type {SimplePullRequest} from "@octokit/webhooks-types"; import { createComment, generateBody, @@ -11,7 +11,7 @@ import localeDate from "./locale-date"; import {getCommitChecksRunsStatus, getCommitStatusesStatus} from "./commit"; import { getScheduleDateString, - hasScheduledCommand, + findScheduleDateCommand, isFork, isValidMergeMethod, } from "./utils"; @@ -53,7 +53,7 @@ export default async function handleSchedule(): Promise { return responseData .filter((pullRequest) => !isFork(pullRequest as SimplePullRequest)) - .filter((pullRequest) => hasScheduledCommand(pullRequest as PullRequest, octokit)) + .filter((pullRequest) => findScheduleDateCommand(pullRequest.number, octokit)) .filter((pullRequest) => pullRequest.labels.every((label) => label.name !== automergeFailLabel) ) diff --git a/lib/index.ts b/lib/index.ts index 98efbd8..6c188f3 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -3,18 +3,22 @@ import * as github from "@actions/github"; import handlePullRequest from "./handle-pull-request"; import handleSchedule from "./handle-schedule"; +import handlePullRequestComment from "./handle-pull-request-comment"; main(); async function main() { try { - core.info(github.context.eventName); - - if (github.context.eventName === "pull_request" || github.context.eventName === "issue_comment") { + if (github.context.eventName === "pull_request") { await handlePullRequest(); return; } + if (github.context.eventName === "issue_comment") { + await handlePullRequestComment(); + return; + } + await handleSchedule(); } catch (error) { core.setFailed(error as Error); diff --git a/lib/utils.ts b/lib/utils.ts index 5bf7816..6dd7a0e 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,32 +1,42 @@ -import type {PullRequest, SimplePullRequest} from "@octokit/webhooks-types"; +import type {SimplePullRequest} from "@octokit/webhooks-types"; import * as github from "@actions/github"; import {GitHub} from "@actions/github/lib/utils"; import * as core from "@actions/core"; type Octokit = InstanceType; -export async function hasScheduledCommand(pullRequest: PullRequest, octokit: Octokit): Promise { - const bodyContains = pullRequest.body != null ? /(^|\n)\/schedule/.test(pullRequest.body) : false; - const prComments = await octokit.paginate( +export async function findScheduleDateCommand(pullRequestId: number, octokit: Octokit): Promise { + const pullRequestResponse = await octokit.rest.pulls.get({ + ...github.context.repo, + pull_number: pullRequestId, + }) + + const bodyDate = getScheduleDateString(pullRequestResponse.data.body); + + const commentDates: string[] = await octokit.paginate( octokit.rest.issues.listComments, { ...github.context.repo, - issue_number: pullRequest.number, + issue_number: pullRequestResponse.data.number, }, (response) => { - return response.data.filter((comment) => - /(^|\n)\/schedule/.test(comment.body ?? "") - ); + return response + .data + .flatMap((comment) => getScheduleDateString(comment.body ?? "")) + .filter(Boolean) + .map((dateString) => new Date(dateString).toISOString()); } ) - core.info(`PrComments: ${prComments}`); + commentDates.unshift(bodyDate) + + core.info(`Dates: ${commentDates}`); - const last = prComments.pop; + const lastDate: string = commentDates.pop() ?? ""; - core.info(`Last pr comment: ${last}`); + core.info(`Last date: ${lastDate}`); - return bodyContains || last != undefined + return lastDate } export function isFork(pullRequest: SimplePullRequest): boolean {