diff --git a/dist/comment.js b/dist/comment.js new file mode 100644 index 0000000..91fed38 --- /dev/null +++ b/dist/comment.js @@ -0,0 +1,159 @@ +"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 () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.findPreviousComment = findPreviousComment; +exports.updateComment = updateComment; +exports.createComment = createComment; +exports.deleteComment = deleteComment; +exports.minimizeComment = minimizeComment; +exports.getBodyOf = getBodyOf; +exports.commentsEqual = commentsEqual; +const core = __importStar(require("@actions/core")); +function headerComment(header) { + return ``; +} +function bodyWithHeader(body, header) { + return `${body}\n${headerComment(header)}`; +} +function bodyWithoutHeader(body, header) { + return body.replace(`\n${headerComment(header)}`, ""); +} +async function findPreviousComment(octokit, repo, number, header) { + let after = null; + let hasNextPage = true; + const h = headerComment(header); + while (hasNextPage) { + const data = await octokit.graphql(` + query($repo: String! $owner: String! $number: Int! $after: String) { + viewer { login } + repository(name: $repo owner: $owner) { + pullRequest(number: $number) { + comments(first: 100 after: $after) { + nodes { + id + author { + login + } + isMinimized + body + } + pageInfo { + endCursor + hasNextPage + } + } + } + } + } + `, { ...repo, after, number }); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion + const viewer = data.viewer; + // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion + const repository = data.repository; + const target = repository.pullRequest?.comments?.nodes?.find((node) => node?.author?.login === viewer.login.replace("[bot]", "") && + !node?.isMinimized && + node?.body?.includes(h)); + if (target) { + return target; + } + after = repository.pullRequest?.comments?.pageInfo?.endCursor; + hasNextPage = repository.pullRequest?.comments?.pageInfo?.hasNextPage ?? false; + } + return undefined; +} +async function updateComment(octokit, id, body, header, previousBody) { + if (!body && !previousBody) + return core.warning("Comment body cannot be blank"); + const rawPreviousBody = previousBody ? bodyWithoutHeader(previousBody, header) : ""; + await octokit.graphql(` + mutation($input: UpdateIssueCommentInput!) { + updateIssueComment(input: $input) { + issueComment { + id + body + } + } + } + `, { + input: { + id, + body: previousBody + ? bodyWithHeader(`${rawPreviousBody}\n${body}`, header) + : bodyWithHeader(body, header), + }, + }); +} +async function createComment(octokit, repo, issue_number, body, header, previousBody) { + if (!body && !previousBody) { + core.warning("Comment body cannot be blank"); + return; + } + return await octokit.rest.issues.createComment({ + ...repo, + issue_number, + body: previousBody ? `${previousBody}\n${body}` : bodyWithHeader(body, header), + }); +} +async function deleteComment(octokit, id) { + await octokit.graphql(` + mutation($id: ID!) { + deleteIssueComment(input: { id: $id }) { + clientMutationId + } + } + `, { id }); +} +async function minimizeComment(octokit, subjectId, classifier) { + await octokit.graphql(` + mutation($input: MinimizeCommentInput!) { + minimizeComment(input: $input) { + clientMutationId + } + } + `, { input: { subjectId, classifier } }); +} +function getBodyOf(previous, append, hideDetails) { + if (!append) { + return undefined; + } + if (!hideDetails || !previous.body) { + return previous.body; + } + return previous.body.replace(/()/g, "$1$2"); +} +function commentsEqual(body, previous, header) { + const newBody = bodyWithHeader(body, header); + return newBody === previous; +} diff --git a/dist/config.js b/dist/config.js new file mode 100644 index 0000000..7cfb0f9 --- /dev/null +++ b/dist/config.js @@ -0,0 +1,100 @@ +"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 () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +exports.ignoreEmpty = exports.githubToken = exports.hideOldComment = exports.skipUnchanged = exports.onlyUpdateComment = exports.onlyCreateComment = exports.deleteOldComment = exports.hideClassify = exports.hideAndRecreate = exports.recreate = exports.hideDetails = exports.append = exports.header = exports.repo = exports.pullRequestNumber = void 0; +exports.getBody = getBody; +const node_fs_1 = require("node:fs"); +const core = __importStar(require("@actions/core")); +const github_1 = require("@actions/github"); +const glob_1 = require("@actions/glob"); +exports.pullRequestNumber = github_1.context?.payload?.pull_request?.number || +core.getInput("number", { required: false }); +exports.repo = buildRepo(); +exports.header = core.getInput("header", { required: false }); +exports.append = core.getBooleanInput("append", { required: true }); +exports.hideDetails = core.getBooleanInput("hide_details", { + required: true, +}); +exports.recreate = core.getBooleanInput("recreate", { required: true }); +exports.hideAndRecreate = core.getBooleanInput("hide_and_recreate", { + required: true, +}); +exports.hideClassify = core.getInput("hide_classify", { + required: true, +}); +exports.deleteOldComment = core.getBooleanInput("delete", { required: true }); +exports.onlyCreateComment = core.getBooleanInput("only_create", { + required: true, +}); +exports.onlyUpdateComment = core.getBooleanInput("only_update", { + required: true, +}); +exports.skipUnchanged = core.getBooleanInput("skip_unchanged", { + required: true, +}); +exports.hideOldComment = core.getBooleanInput("hide", { required: true }); +exports.githubToken = core.getInput("GITHUB_TOKEN", { required: true }); +exports.ignoreEmpty = core.getBooleanInput("ignore_empty", { + required: true, +}); +function buildRepo() { + return { + owner: core.getInput("owner", { required: false }) || github_1.context.repo.owner, + repo: core.getInput("repo", { required: false }) || github_1.context.repo.repo, + }; +} +async function getBody() { + const pathInput = core.getMultilineInput("path", { required: false }); + const followSymbolicLinks = core.getBooleanInput("follow_symbolic_links", { + required: true, + }); + if (pathInput && pathInput.length > 0) { + try { + const globber = await (0, glob_1.create)(pathInput.join("\n"), { + followSymbolicLinks, + matchDirectories: false, + }); + return (await globber.glob()).map(path => (0, node_fs_1.readFileSync)(path, "utf-8")).join("\n"); + } + catch (error) { + if (error instanceof Error) { + core.setFailed(error.message); + } + return ""; + } + } + else { + return core.getInput("message", { required: false }); + } +} diff --git a/dist/main.js b/dist/main.js new file mode 100644 index 0000000..3823cdb --- /dev/null +++ b/dist/main.js @@ -0,0 +1,114 @@ +"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 () { + var ownKeys = function(o) { + ownKeys = Object.getOwnPropertyNames || function (o) { + var ar = []; + for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; + return ar; + }; + return ownKeys(o); + }; + return function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); + __setModuleDefault(result, mod); + return result; + }; +})(); +Object.defineProperty(exports, "__esModule", { value: true }); +const core = __importStar(require("@actions/core")); +const github = __importStar(require("@actions/github")); +const comment_1 = require("./comment"); +const config_1 = require("./config"); +async function run() { + if (Number.isNaN(config_1.pullRequestNumber) || config_1.pullRequestNumber < 1) { + core.info("no pull request numbers given: skip step"); + return; + } + try { + const body = await (0, config_1.getBody)(); + if (!body && config_1.ignoreEmpty) { + core.info("no body given: skip step by ignoreEmpty"); + return; + } + if (!config_1.deleteOldComment && !config_1.hideOldComment && !body) { + throw new Error("Either message or path input is required"); + } + if (config_1.deleteOldComment && config_1.recreate) { + throw new Error("delete and recreate cannot be both set to true"); + } + if (config_1.onlyCreateComment && config_1.onlyUpdateComment) { + throw new Error("only_create and only_update cannot be both set to true"); + } + if (config_1.hideOldComment && config_1.hideAndRecreate) { + throw new Error("hide and hide_and_recreate cannot be both set to true"); + } + const octokit = github.getOctokit(config_1.githubToken); + const previous = await (0, comment_1.findPreviousComment)(octokit, config_1.repo, config_1.pullRequestNumber, config_1.header); + core.setOutput("previous_comment_id", previous?.id); + if (config_1.deleteOldComment) { + if (previous) { + await (0, comment_1.deleteComment)(octokit, previous.id); + } + return; + } + if (!previous) { + if (config_1.onlyUpdateComment) { + return; + } + const created = await (0, comment_1.createComment)(octokit, config_1.repo, config_1.pullRequestNumber, body, config_1.header); + core.setOutput("created_comment_id", created?.data.id); + return; + } + if (config_1.onlyCreateComment) { + // don't comment anything, user specified only_create and there is an + // existing comment, so this is probably a placeholder / introduction one. + return; + } + if (config_1.hideOldComment) { + await (0, comment_1.minimizeComment)(octokit, previous.id, config_1.hideClassify); + return; + } + if (config_1.skipUnchanged && (0, comment_1.commentsEqual)(body, previous.body || "", config_1.header)) { + // don't recreate or update if the message is unchanged + return; + } + const previousBody = (0, comment_1.getBodyOf)({ body: previous.body || "" }, config_1.append, config_1.hideDetails); + if (config_1.recreate) { + await (0, comment_1.deleteComment)(octokit, previous.id); + const created = await (0, comment_1.createComment)(octokit, config_1.repo, config_1.pullRequestNumber, body, config_1.header, previousBody); + core.setOutput("created_comment_id", created?.data.id); + return; + } + if (config_1.hideAndRecreate) { + await (0, comment_1.minimizeComment)(octokit, previous.id, config_1.hideClassify); + const created = await (0, comment_1.createComment)(octokit, config_1.repo, config_1.pullRequestNumber, body, config_1.header); + core.setOutput("created_comment_id", created?.data.id); + return; + } + await (0, comment_1.updateComment)(octokit, previous.id, body, config_1.header, previousBody); + } + catch (error) { + if (error instanceof Error) { + core.setFailed(error.message); + } + } +} +run();