From 2674f364874ebcf1a71c018357312829e19387b6 Mon Sep 17 00:00:00 2001 From: Cateiru Date: Fri, 14 Jun 2024 15:00:51 +0900 Subject: [PATCH 1/8] added new mode logic: replace --- modes.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/modes.js b/modes.js index 677278b..1c60ccf 100644 --- a/modes.js +++ b/modes.js @@ -58,6 +58,26 @@ export async function appendMode(commenter, identifier, message) { console.log(`Created comment: ${resp.data.html_url}`); } +// replace mode replaces the content of an existing comment that matches the identifier +// with the message. +export async function replaceMode(commenter, identifier, message) { + console.log(`Checking if a comment already exists for ${identifier}.`); + const matchingComment = await findMatchingComment(commenter, identifier); + + const comment = `${getCommentPrefix(identifier)}\n${message}`; + + if (matchingComment) { + console.log(`Updating an existing comment for ${identifier}.`); + const resp = await commenter.updateComment(matchingComment.id, comment); + console.log(`Updated comment: ${resp.data.html_url}`); + return; + } + + console.log(`Creating a new comment for ${identifier}.`); + const resp = await commenter.createComment(comment); + console.log(`Created comment: ${resp.data.html_url}`); +} + // delete mode deletes an existing comment that matches the identifier export async function deleteMode(commenter, identifier) { console.log(`Finding matching comment for ${identifier}.`); From 3c64a20bc5d8dc80cba380b6b06d33fdc6c244c0 Mon Sep 17 00:00:00 2001 From: Cateiru Date: Fri, 14 Jun 2024 15:15:55 +0900 Subject: [PATCH 2/8] feat: Add support for replace mode in comment logic --- index.js | 51 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/index.js b/index.js index ab08b82..87421a5 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,8 @@ import * as core from '@actions/core'; import * as github from '@actions/github'; -import { normalMode, recreateMode, appendMode, deleteMode } from './modes'; +import { + normalMode, recreateMode, appendMode, deleteMode, replaceMode, +} from './modes'; import { getCommenter } from './comment/commenter'; (async () => { @@ -14,13 +16,15 @@ import { getCommenter } from './comment/commenter'; const number = core.getInput('number'); const commitSHA = core.getInput('commit-sha'); const identifier = core.getInput('id'); - const appendComment = core.getInput('append'); - const recreateComment = core.getInput('recreate'); - const deleteComment = core.getInput('delete'); const fail = core.getInput('fail'); const githubToken = core.getInput('github-token'); const message = core.getInput('message'); + const appendComment = core.getInput('append'); + const replaceComment = core.getInput('replace'); + const recreateComment = core.getInput('recreate'); + const deleteComment = core.getInput('delete'); + const octokit = github.getOctokit(githubToken); let commenter; @@ -36,24 +40,37 @@ import { getCommenter } from './comment/commenter'; return; } - let mode = normalMode; + const effectiveModes = [ + ['recreate', recreateComment], + ['append', appendComment], + ['replace', replaceComment], + ['delete', deleteComment], + ].filter((i) => i === 'true'); - if (appendComment === 'true' && recreateComment === 'true') { - core.setFailed('Not allowed to set both `append` and `recreate` to true.'); + if (effectiveModes.length > 1) { + const effectiveModeNames = effectiveModes.map((i) => i[0]).join(', '); + core.setFailed(`Only one of ${effectiveModeNames} can be set to true.`); return; } - if (deleteComment === 'true' && (appendComment === 'true' || recreateComment === 'true')) { - core.setFailed('Not allowed to set `delete` to true with `append` or `recreate`.'); - return; - } + let mode; - if (recreateComment === 'true') { - mode = recreateMode; - } else if (appendComment === 'true') { - mode = appendMode; - } else if (deleteComment === 'true') { - mode = deleteMode; + switch (effectiveModes[0][0]) { + case 'recreate': + mode = recreateMode; + break; + case 'append': + mode = appendMode; + break; + case 'replace': + mode = replaceMode; + break; + case 'delete': + mode = deleteMode; + break; + default: + mode = normalMode; + break; } await mode(commenter, identifier, message); From 1a4b139c61988afc7abe5c5abf689f5a68da6449 Mon Sep 17 00:00:00 2001 From: Cateiru Date: Fri, 14 Jun 2024 15:16:11 +0900 Subject: [PATCH 3/8] feat: Add support for replace mode in comment logic --- action.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/action.yml b/action.yml index 9010712..a38c1ec 100644 --- a/action.yml +++ b/action.yml @@ -28,6 +28,10 @@ inputs: description: 'If true, message will be appended to existing comment' required: false default: false + replace: + description: 'If true, message will replace existing comment' + required: false + default: false recreate: description: 'If true, message will be commented after deleting existing comment' required: false From 93be9cf80ea58c5192689e9e85736ce2f1caf78c Mon Sep 17 00:00:00 2001 From: Cateiru Date: Fri, 14 Jun 2024 15:18:17 +0900 Subject: [PATCH 4/8] feat: Refactor comment mode logic to use objects instead of arrays The code changes modify the comment mode logic in the `index.js` file. Instead of using arrays to represent the comment modes, the code now uses objects with `name` and `flag` properties. This change improves readability and maintainability. Based on the recent user commits and repository commits, it seems that the support for the `replace` mode was added. The commit messages indicate the addition of support for the `replace` mode in the comment logic. --- index.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/index.js b/index.js index 87421a5..fe4d840 100644 --- a/index.js +++ b/index.js @@ -41,21 +41,21 @@ import { getCommenter } from './comment/commenter'; } const effectiveModes = [ - ['recreate', recreateComment], - ['append', appendComment], - ['replace', replaceComment], - ['delete', deleteComment], - ].filter((i) => i === 'true'); + { name: 'recreate', flag: recreateComment }, + { name: 'append', flag: appendComment }, + { name: 'replace', flag: replaceComment }, + { name: 'delete', flag: deleteComment }, + ].filter((m) => m.flag === 'true'); if (effectiveModes.length > 1) { - const effectiveModeNames = effectiveModes.map((i) => i[0]).join(', '); + const effectiveModeNames = effectiveModes.map((m) => m.name).join(', '); core.setFailed(`Only one of ${effectiveModeNames} can be set to true.`); return; } let mode; - switch (effectiveModes[0][0]) { + switch (effectiveModes[0].name) { case 'recreate': mode = recreateMode; break; From 4b0c7dc92e2d6a3f0a86a1e99e51973f5f2e3d4b Mon Sep 17 00:00:00 2001 From: Cateiru Date: Fri, 14 Jun 2024 15:19:54 +0900 Subject: [PATCH 5/8] update version 1.0.0 to 1.0.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9c9013d..d604a95 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "comment-progress", - "version": "1.0.0", + "version": "1.0.1", "description": "", "main": "index.js", "scripts": { From e7d61d4681bd10345239702335571b78edd83d00 Mon Sep 17 00:00:00 2001 From: Cateiru Date: Fri, 14 Jun 2024 15:23:53 +0900 Subject: [PATCH 6/8] updated @vercel/ncc to latest (v0.38.1) --- package-lock.json | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 146985d..d6b3a4e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,19 +1,19 @@ { "name": "comment-progress", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "comment-progress", - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", "dependencies": { "@actions/core": "^1.2.6", "@actions/github": "^4.0.0" }, "devDependencies": { - "@vercel/ncc": "^0.27.0", + "@vercel/ncc": "^0.38.1", "eslint": "^7.29.0", "eslint-config-airbnb-base": "^14.2.1", "eslint-plugin-import": "^2.23.4" @@ -233,9 +233,9 @@ "integrity": "sha512-Ecfmo4YDQPwuqTCl1yBxLV5ihKfRlkBmzUEDcfIRvDxOTGQEeikr317Ln7Gcv0tjA8dVgKI3rniqW2G1OyKDng==" }, "node_modules/@vercel/ncc": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.27.0.tgz", - "integrity": "sha512-DllIJQapnU2YwewIhh/4dYesmMQw3h2cFtabECc/zSJHqUbNa0eJuEkRa6DXbZvh1YPWBtYQoPV17NlDpBw1Vw==", + "version": "0.38.1", + "resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.38.1.tgz", + "integrity": "sha512-IBBb+iI2NLu4VQn3Vwldyi2QwaXt5+hTyh58ggAMoCGE6DJmPvwL3KPBWcJl1m9LYPChBLE980Jw+CS4Wokqxw==", "dev": true, "bin": { "ncc": "dist/ncc/cli.js" diff --git a/package.json b/package.json index d604a95..574319e 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "@actions/github": "^4.0.0" }, "devDependencies": { - "@vercel/ncc": "^0.27.0", + "@vercel/ncc": "^0.38.1", "eslint": "^7.29.0", "eslint-config-airbnb-base": "^14.2.1", "eslint-plugin-import": "^2.23.4" From 6a6ca006c8260ab2fd68cbf019fd05abbd14af51 Mon Sep 17 00:00:00 2001 From: Cateiru Date: Fri, 14 Jun 2024 15:24:13 +0900 Subject: [PATCH 7/8] build and export dist/index.js file --- dist/index.js | 937 ++++++++++++++++++++++++++------------------------ 1 file changed, 485 insertions(+), 452 deletions(-) diff --git a/dist/index.js b/dist/index.js index 395834c..015f3f5 100644 --- a/dist/index.js +++ b/dist/index.js @@ -1,311 +1,6 @@ -module.exports = /******/ (() => { // webpackBootstrap /******/ var __webpack_modules__ = ({ -/***/ 752: -/***/ ((__unused_webpack_module, __webpack_exports__, __nccwpck_require__) => { - -"use strict"; -// ESM COMPAT FLAG -__nccwpck_require__.r(__webpack_exports__); - -// EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js -var core = __nccwpck_require__(186); -// EXTERNAL MODULE: ./node_modules/@actions/github/lib/github.js -var github = __nccwpck_require__(438); -// CONCATENATED MODULE: ./identifier.js -function getCommentPrefix(identifier) { - return ``; -} - -// CONCATENATED MODULE: ./comment/issue_commenter.js -class IssueCommenter { - constructor(octokit, { owner, repo, number }) { - this.octokit = octokit; - this.owner = owner; - this.repo = repo; - this.number = number; - } - - createComment(comment) { - return this.octokit.issues.createComment({ - owner: this.owner, - repo: this.repo, - issue_number: this.number, - body: comment, - }); - } - - deleteComment(commentID) { - return this.octokit.issues.deleteComment({ - owner: this.owner, - repo: this.repo, - comment_id: commentID, - }); - } - - listComments(opts) { - return this.octokit.issues.listComments({ - owner: this.owner, - repo: this.repo, - issue_number: this.number, - page: opts.page, - per_page: opts.perPage, - }); - } - - updateComment(commentID, comment) { - return this.octokit.issues.updateComment({ - owner: this.owner, - repo: this.repo, - comment_id: commentID, - body: comment, - }); - } -} - -// CONCATENATED MODULE: ./comment/commit_commenter.js -class CommitCommenter { - constructor(octokit, { owner, repo, commitSHA }) { - this.octokit = octokit; - this.owner = owner; - this.repo = repo; - this.commitSHA = commitSHA; - } - - createComment(comment) { - return this.octokit.repos.createCommitComment({ - owner: this.owner, - repo: this.repo, - commit_sha: this.commitSHA, - body: comment, - }); - } - - deleteComment(commentID) { - return this.octokit.repos.deleteCommitComment({ - owner: this.owner, - repo: this.repo, - comment_id: commentID, - }); - } - - listComments(opts) { - return this.octokit.repos.listCommentsForCommit({ - owner: this.owner, - repo: this.repo, - commit_sha: this.commitSHA, - page: opts.page, - per_page: opts.perPage, - }); - } - - updateComment(commentID, comment) { - return this.octokit.repos.updateCommitComment({ - owner: this.owner, - repo: this.repo, - comment_id: commentID, - body: comment, - }); - } -} - -// CONCATENATED MODULE: ./comment/commenter.js - - - - -function getCommenter(octokit, { - owner, repo, number, commitSHA, -}) { - if ((number && commitSHA) || (!number && !commitSHA)) { - throw new Error('Either set the `number` or the `commit-sha` field.'); - } - if (number) { - return new IssueCommenter(octokit, { owner, repo, number }); - } - if (commitSHA) { - return new CommitCommenter(octokit, { owner, repo, commitSHA }); - } - return null; -} - -async function findMatchingComments(commenter, identifier) { - let fetchMoreComments = true; - let page = 0; - const matchingComments = []; - const commentPrefix = getCommentPrefix(identifier); - - while (fetchMoreComments) { - page += 1; - const comments = await commenter.listComments({ - page, - perPage: 100, - }); - fetchMoreComments = comments.data.length !== 0; - for (const comment of comments.data) { - if (comment.body.startsWith(commentPrefix)) { - matchingComments.push(comment); - } - } - } - return matchingComments; -} - -async function findMatchingComment(commenter, identifier) { - const matchingComments = await findMatchingComments(commenter, identifier); - let matchingComment; - if (matchingComments && matchingComments.length > 0) { - matchingComment = matchingComments[matchingComments.length - 1]; - } - return matchingComment; -} - -// CONCATENATED MODULE: ./modes.js - - - -// normal mode creates a comment when there is no existing comment that match identifier -// and updates the matching comment if found -async function normalMode(commenter, identifier, message) { - console.log(`Checking if a comment already exists for ${identifier}.`); - const matchingComment = await findMatchingComment(commenter, identifier); - - const comment = `${getCommentPrefix(identifier)}\n${message}`; - - if (matchingComment) { - console.log(`Updating an existing comment for ${identifier}.`); - const resp = await commenter.updateComment(matchingComment.id, comment); - console.log(`Updated comment: ${resp.data.html_url}`); - return; - } - - console.log(`Creating a new comment for ${identifier}.`); - const resp = await commenter.createComment(comment); - console.log(`Created comment: ${resp.data.html_url}`); -} - -// recreate mode deletes existing comments that match the identifier -// and creates a new comment -async function recreateMode(commenter, identifier, message) { - console.log(`Finding matching comments for ${identifier}.`); - const matchingComments = await findMatchingComments(commenter, identifier); - - for (const comment of matchingComments) { - console.log(`Deleting github comment ${comment.id}`); - await commenter.deleteComment(comment.id); - } - - console.log(`Creating a new comment for ${identifier}.`); - const comment = `${getCommentPrefix(identifier)}\n${message}`; - const resp = await commenter.createComment(comment); - console.log(`Created comment: ${resp.data.html_url}`); -} - -// append mode creates a comment when there is no existing comment that match identifier -// and appends message to a matching comment if found. -async function appendMode(commenter, identifier, message) { - console.log(`Checking if a comment already exists for ${identifier}.`); - const matchingComment = await findMatchingComment(commenter, identifier); - - if (matchingComment) { - console.log(`Updating an existing comment for ${identifier}.`); - const comment = `${matchingComment.body}\n${message}`; - const resp = await commenter.updateComment(matchingComment.id, comment); - console.log(`Updated comment: ${resp.data.html_url}`); - return; - } - - console.log(`Creating a new comment for ${identifier}.`); - const comment = `${getCommentPrefix(identifier)}\n${message}`; - const resp = await commenter.createComment(comment); - console.log(`Created comment: ${resp.data.html_url}`); -} - -// delete mode deletes an existing comment that matches the identifier -async function deleteMode(commenter, identifier) { - console.log(`Finding matching comment for ${identifier}.`); - const matchingComment = await findMatchingComment(commenter, identifier); - - if (matchingComment) { - console.log(`Deleting github comment ${matchingComment.id}`); - await commenter.deleteComment(matchingComment.id); - } -} - -// CONCATENATED MODULE: ./index.js - - - - - -(async () => { - try { - const repository = core.getInput("repository"); - const [owner, repo] = repository.split("/"); - if (!owner || !repo) { - throw new Error(`Invalid repository: ${repository}`); - } - - const number = core.getInput("number"); - const commitSHA = core.getInput("commit-sha"); - const identifier = core.getInput("id"); - const appendComment = core.getInput("append"); - const recreateComment = core.getInput("recreate"); - const deleteComment = core.getInput("delete"); - const fail = core.getInput("fail"); - const githubToken = core.getInput("github-token"); - const message = core.getInput("message"); - - const octokit = github.getOctokit(githubToken); - - let commenter; - try { - commenter = getCommenter(octokit, { - owner, - repo, - number, - commitSHA, - }); - } catch (err) { - core.setFailed(err); - return; - } - - let mode = normalMode; - - if (appendComment === "true" && recreateComment === "true") { - core.setFailed("Not allowed to set both `append` and `recreate` to true."); - return; - } - - if (deleteComment === "true" && (appendComment === "true" || recreateComment === "true")) { - core.setFailed("Not allowed to set `delete` to true with `append` or `recreate`."); - return; - } - - if (recreateComment === "true") { - mode = recreateMode; - } else if (appendComment === "true") { - mode = appendMode; - } else if (deleteComment === "true") { - mode = deleteMode; - } - - await mode(commenter, identifier, message); - - if (fail === "true") { - core.setFailed(message); - } - } catch (error) { - console.error(error); - core.setFailed(error.message); - } -})(); - - -/***/ }), - /***/ 351: /***/ (function(__unused_webpack_module, exports, __nccwpck_require__) { @@ -319,7 +14,7 @@ var __importStar = (this && this.__importStar) || function (mod) { return result; }; Object.defineProperty(exports, "__esModule", ({ value: true })); -const os = __importStar(__nccwpck_require__(87)); +const os = __importStar(__nccwpck_require__(37)); const utils_1 = __nccwpck_require__(278); /** * Commands @@ -417,8 +112,8 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); const command_1 = __nccwpck_require__(351); const file_command_1 = __nccwpck_require__(717); const utils_1 = __nccwpck_require__(278); -const os = __importStar(__nccwpck_require__(87)); -const path = __importStar(__nccwpck_require__(622)); +const os = __importStar(__nccwpck_require__(37)); +const path = __importStar(__nccwpck_require__(17)); /** * The code to exit an action */ @@ -653,8 +348,8 @@ var __importStar = (this && this.__importStar) || function (mod) { Object.defineProperty(exports, "__esModule", ({ value: true })); // We use any as a valid input type /* eslint-disable @typescript-eslint/no-explicit-any */ -const fs = __importStar(__nccwpck_require__(747)); -const os = __importStar(__nccwpck_require__(87)); +const fs = __importStar(__nccwpck_require__(147)); +const os = __importStar(__nccwpck_require__(37)); const utils_1 = __nccwpck_require__(278); function issueCommand(command, message) { const filePath = process.env[`GITHUB_${command}`]; @@ -699,15 +394,15 @@ exports.toCommandValue = toCommandValue; /***/ }), -/***/ 53: +/***/ 87: /***/ ((__unused_webpack_module, exports, __nccwpck_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.Context = void 0; -const fs_1 = __nccwpck_require__(747); -const os_1 = __nccwpck_require__(87); +const fs_1 = __nccwpck_require__(147); +const os_1 = __nccwpck_require__(37); class Context { /** * Hydrate the context from the environment @@ -782,7 +477,7 @@ var __importStar = (this && this.__importStar) || function (mod) { }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getOctokit = exports.context = void 0; -const Context = __importStar(__nccwpck_require__(53)); +const Context = __importStar(__nccwpck_require__(87)); const utils_1 = __nccwpck_require__(30); exports.context = new Context.Context(); /** @@ -875,7 +570,7 @@ var __importStar = (this && this.__importStar) || function (mod) { }; Object.defineProperty(exports, "__esModule", ({ value: true })); exports.getOctokitOptions = exports.GitHub = exports.context = void 0; -const Context = __importStar(__nccwpck_require__(53)); +const Context = __importStar(__nccwpck_require__(87)); const Utils = __importStar(__nccwpck_require__(914)); // octokit + plugins const core_1 = __nccwpck_require__(762); @@ -916,8 +611,8 @@ exports.getOctokitOptions = getOctokitOptions; "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); -const http = __nccwpck_require__(605); -const https = __nccwpck_require__(211); +const http = __nccwpck_require__(685); +const https = __nccwpck_require__(687); const pm = __nccwpck_require__(443); let tunnel; var HttpCodes; @@ -4045,11 +3740,11 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } -var Stream = _interopDefault(__nccwpck_require__(413)); -var http = _interopDefault(__nccwpck_require__(605)); -var Url = _interopDefault(__nccwpck_require__(835)); -var https = _interopDefault(__nccwpck_require__(211)); -var zlib = _interopDefault(__nccwpck_require__(761)); +var Stream = _interopDefault(__nccwpck_require__(781)); +var http = _interopDefault(__nccwpck_require__(685)); +var Url = _interopDefault(__nccwpck_require__(310)); +var https = _interopDefault(__nccwpck_require__(687)); +var zlib = _interopDefault(__nccwpck_require__(796)); // Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js @@ -4200,7 +3895,7 @@ FetchError.prototype.name = 'FetchError'; let convert; try { - convert = __nccwpck_require__(877).convert; + convert = (__nccwpck_require__(877).convert); } catch (e) {} const INTERNALS = Symbol('Body internals'); @@ -5683,7 +5378,7 @@ fetch.Promise = global.Promise; module.exports = exports = fetch; Object.defineProperty(exports, "__esModule", ({ value: true })); -exports.default = exports; +exports["default"] = exports; exports.Headers = Headers; exports.Request = Request; exports.Response = Response; @@ -5755,13 +5450,13 @@ module.exports = __nccwpck_require__(219); "use strict"; -var net = __nccwpck_require__(631); -var tls = __nccwpck_require__(16); -var http = __nccwpck_require__(605); -var https = __nccwpck_require__(211); -var events = __nccwpck_require__(614); -var assert = __nccwpck_require__(357); -var util = __nccwpck_require__(669); +var net = __nccwpck_require__(808); +var tls = __nccwpck_require__(404); +var http = __nccwpck_require__(685); +var https = __nccwpck_require__(687); +var events = __nccwpck_require__(361); +var assert = __nccwpck_require__(491); +var util = __nccwpck_require__(837); exports.httpOverHttp = httpOverHttp; @@ -6082,172 +5777,510 @@ function wrappy (fn, cb) { } return ret } -} +} + + +/***/ }), + +/***/ 877: +/***/ ((module) => { + +module.exports = eval("require")("encoding"); + + +/***/ }), + +/***/ 491: +/***/ ((module) => { + +"use strict"; +module.exports = require("assert"); + +/***/ }), + +/***/ 361: +/***/ ((module) => { + +"use strict"; +module.exports = require("events"); + +/***/ }), + +/***/ 147: +/***/ ((module) => { + +"use strict"; +module.exports = require("fs"); + +/***/ }), + +/***/ 685: +/***/ ((module) => { + +"use strict"; +module.exports = require("http"); + +/***/ }), + +/***/ 687: +/***/ ((module) => { + +"use strict"; +module.exports = require("https"); + +/***/ }), + +/***/ 808: +/***/ ((module) => { + +"use strict"; +module.exports = require("net"); + +/***/ }), + +/***/ 37: +/***/ ((module) => { + +"use strict"; +module.exports = require("os"); + +/***/ }), + +/***/ 17: +/***/ ((module) => { + +"use strict"; +module.exports = require("path"); + +/***/ }), + +/***/ 781: +/***/ ((module) => { + +"use strict"; +module.exports = require("stream"); + +/***/ }), + +/***/ 404: +/***/ ((module) => { + +"use strict"; +module.exports = require("tls"); + +/***/ }), + +/***/ 310: +/***/ ((module) => { + +"use strict"; +module.exports = require("url"); + +/***/ }), + +/***/ 837: +/***/ ((module) => { + +"use strict"; +module.exports = require("util"); + +/***/ }), + +/***/ 796: +/***/ ((module) => { + +"use strict"; +module.exports = require("zlib"); + +/***/ }) + +/******/ }); +/************************************************************************/ +/******/ // The module cache +/******/ var __webpack_module_cache__ = {}; +/******/ +/******/ // The require function +/******/ function __nccwpck_require__(moduleId) { +/******/ // Check if module is in cache +/******/ var cachedModule = __webpack_module_cache__[moduleId]; +/******/ if (cachedModule !== undefined) { +/******/ return cachedModule.exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = __webpack_module_cache__[moduleId] = { +/******/ // no module.id needed +/******/ // no module.loaded needed +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ var threw = true; +/******/ try { +/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __nccwpck_require__); +/******/ threw = false; +/******/ } finally { +/******/ if(threw) delete __webpack_module_cache__[moduleId]; +/******/ } +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/************************************************************************/ +/******/ /* webpack/runtime/make namespace object */ +/******/ (() => { +/******/ // define __esModule on exports +/******/ __nccwpck_require__.r = (exports) => { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ })(); +/******/ +/******/ /* webpack/runtime/compat */ +/******/ +/******/ if (typeof __nccwpck_require__ !== 'undefined') __nccwpck_require__.ab = __dirname + "/"; +/******/ +/************************************************************************/ +var __webpack_exports__ = {}; +// This entry need to be wrapped in an IIFE because it need to be in strict mode. +(() => { +"use strict"; +// ESM COMPAT FLAG +__nccwpck_require__.r(__webpack_exports__); + +// EXTERNAL MODULE: ./node_modules/@actions/core/lib/core.js +var core = __nccwpck_require__(186); +// EXTERNAL MODULE: ./node_modules/@actions/github/lib/github.js +var github = __nccwpck_require__(438); +;// CONCATENATED MODULE: ./identifier.js +function getCommentPrefix(identifier) { + return ``; +} + +;// CONCATENATED MODULE: ./comment/issue_commenter.js +class IssueCommenter { + constructor(octokit, { owner, repo, number }) { + this.octokit = octokit; + this.owner = owner; + this.repo = repo; + this.number = number; + } + + createComment(comment) { + return this.octokit.issues.createComment({ + owner: this.owner, + repo: this.repo, + issue_number: this.number, + body: comment, + }); + } + + deleteComment(commentID) { + return this.octokit.issues.deleteComment({ + owner: this.owner, + repo: this.repo, + comment_id: commentID, + }); + } + + listComments(opts) { + return this.octokit.issues.listComments({ + owner: this.owner, + repo: this.repo, + issue_number: this.number, + page: opts.page, + per_page: opts.perPage, + }); + } + + updateComment(commentID, comment) { + return this.octokit.issues.updateComment({ + owner: this.owner, + repo: this.repo, + comment_id: commentID, + body: comment, + }); + } +} + +;// CONCATENATED MODULE: ./comment/commit_commenter.js +class CommitCommenter { + constructor(octokit, { owner, repo, commitSHA }) { + this.octokit = octokit; + this.owner = owner; + this.repo = repo; + this.commitSHA = commitSHA; + } + + createComment(comment) { + return this.octokit.repos.createCommitComment({ + owner: this.owner, + repo: this.repo, + commit_sha: this.commitSHA, + body: comment, + }); + } + deleteComment(commentID) { + return this.octokit.repos.deleteCommitComment({ + owner: this.owner, + repo: this.repo, + comment_id: commentID, + }); + } -/***/ }), + listComments(opts) { + return this.octokit.repos.listCommentsForCommit({ + owner: this.owner, + repo: this.repo, + commit_sha: this.commitSHA, + page: opts.page, + per_page: opts.perPage, + }); + } -/***/ 877: -/***/ ((module) => { + updateComment(commentID, comment) { + return this.octokit.repos.updateCommitComment({ + owner: this.owner, + repo: this.repo, + comment_id: commentID, + body: comment, + }); + } +} -module.exports = eval("require")("encoding"); +;// CONCATENATED MODULE: ./comment/commenter.js -/***/ }), -/***/ 357: -/***/ ((module) => { -"use strict"; -module.exports = require("assert");; +function getCommenter(octokit, { + owner, repo, number, commitSHA, +}) { + if ((number && commitSHA) || (!number && !commitSHA)) { + throw new Error('Either set the `number` or the `commit-sha` field.'); + } + if (number) { + return new IssueCommenter(octokit, { owner, repo, number }); + } + if (commitSHA) { + return new CommitCommenter(octokit, { owner, repo, commitSHA }); + } + return null; +} -/***/ }), +async function findMatchingComments(commenter, identifier) { + let fetchMoreComments = true; + let page = 0; + const matchingComments = []; + const commentPrefix = getCommentPrefix(identifier); -/***/ 614: -/***/ ((module) => { + while (fetchMoreComments) { + page += 1; + const comments = await commenter.listComments({ + page, + perPage: 100, + }); + fetchMoreComments = comments.data.length !== 0; + for (const comment of comments.data) { + if (comment.body.startsWith(commentPrefix)) { + matchingComments.push(comment); + } + } + } + return matchingComments; +} -"use strict"; -module.exports = require("events");; +async function findMatchingComment(commenter, identifier) { + const matchingComments = await findMatchingComments(commenter, identifier); + let matchingComment; + if (matchingComments && matchingComments.length > 0) { + matchingComment = matchingComments[matchingComments.length - 1]; + } + return matchingComment; +} -/***/ }), +;// CONCATENATED MODULE: ./modes.js -/***/ 747: -/***/ ((module) => { -"use strict"; -module.exports = require("fs");; -/***/ }), +// normal mode creates a comment when there is no existing comment that match identifier +// and updates the matching comment if found +async function normalMode(commenter, identifier, message) { + console.log(`Checking if a comment already exists for ${identifier}.`); + const matchingComment = await findMatchingComment(commenter, identifier); -/***/ 605: -/***/ ((module) => { + const comment = `${getCommentPrefix(identifier)}\n${message}`; -"use strict"; -module.exports = require("http");; + if (matchingComment) { + console.log(`Updating an existing comment for ${identifier}.`); + const resp = await commenter.updateComment(matchingComment.id, comment); + console.log(`Updated comment: ${resp.data.html_url}`); + return; + } -/***/ }), + console.log(`Creating a new comment for ${identifier}.`); + const resp = await commenter.createComment(comment); + console.log(`Created comment: ${resp.data.html_url}`); +} -/***/ 211: -/***/ ((module) => { +// recreate mode deletes existing comments that match the identifier +// and creates a new comment +async function recreateMode(commenter, identifier, message) { + console.log(`Finding matching comments for ${identifier}.`); + const matchingComments = await findMatchingComments(commenter, identifier); -"use strict"; -module.exports = require("https");; + for (const comment of matchingComments) { + console.log(`Deleting github comment ${comment.id}`); + await commenter.deleteComment(comment.id); + } -/***/ }), + console.log(`Creating a new comment for ${identifier}.`); + const comment = `${getCommentPrefix(identifier)}\n${message}`; + const resp = await commenter.createComment(comment); + console.log(`Created comment: ${resp.data.html_url}`); +} -/***/ 631: -/***/ ((module) => { +// append mode creates a comment when there is no existing comment that match identifier +// and appends message to a matching comment if found. +async function appendMode(commenter, identifier, message) { + console.log(`Checking if a comment already exists for ${identifier}.`); + const matchingComment = await findMatchingComment(commenter, identifier); -"use strict"; -module.exports = require("net");; + if (matchingComment) { + console.log(`Updating an existing comment for ${identifier}.`); + const comment = `${matchingComment.body}\n${message}`; + const resp = await commenter.updateComment(matchingComment.id, comment); + console.log(`Updated comment: ${resp.data.html_url}`); + return; + } -/***/ }), + console.log(`Creating a new comment for ${identifier}.`); + const comment = `${getCommentPrefix(identifier)}\n${message}`; + const resp = await commenter.createComment(comment); + console.log(`Created comment: ${resp.data.html_url}`); +} -/***/ 87: -/***/ ((module) => { +// replace mode replaces the content of an existing comment that matches the identifier +// with the message. +async function replaceMode(commenter, identifier, message) { + console.log(`Checking if a comment already exists for ${identifier}.`); + const matchingComment = await findMatchingComment(commenter, identifier); -"use strict"; -module.exports = require("os");; + const comment = `${getCommentPrefix(identifier)}\n${message}`; -/***/ }), + if (matchingComment) { + console.log(`Updating an existing comment for ${identifier}.`); + const resp = await commenter.updateComment(matchingComment.id, comment); + console.log(`Updated comment: ${resp.data.html_url}`); + return; + } -/***/ 622: -/***/ ((module) => { + console.log(`Creating a new comment for ${identifier}.`); + const resp = await commenter.createComment(comment); + console.log(`Created comment: ${resp.data.html_url}`); +} -"use strict"; -module.exports = require("path");; +// delete mode deletes an existing comment that matches the identifier +async function deleteMode(commenter, identifier) { + console.log(`Finding matching comment for ${identifier}.`); + const matchingComment = await findMatchingComment(commenter, identifier); -/***/ }), + if (matchingComment) { + console.log(`Deleting github comment ${matchingComment.id}`); + await commenter.deleteComment(matchingComment.id); + } +} -/***/ 413: -/***/ ((module) => { +;// CONCATENATED MODULE: ./index.js -"use strict"; -module.exports = require("stream");; -/***/ }), -/***/ 16: -/***/ ((module) => { -"use strict"; -module.exports = require("tls");; -/***/ }), +(async () => { + try { + const repository = core.getInput('repository'); + const [owner, repo] = repository.split('/'); + if (!owner || !repo) { + throw new Error(`Invalid repository: ${repository}`); + } -/***/ 835: -/***/ ((module) => { + const number = core.getInput('number'); + const commitSHA = core.getInput('commit-sha'); + const identifier = core.getInput('id'); + const fail = core.getInput('fail'); + const githubToken = core.getInput('github-token'); + const message = core.getInput('message'); -"use strict"; -module.exports = require("url");; + const appendComment = core.getInput('append'); + const replaceComment = core.getInput('replace'); + const recreateComment = core.getInput('recreate'); + const deleteComment = core.getInput('delete'); -/***/ }), + const octokit = github.getOctokit(githubToken); -/***/ 669: -/***/ ((module) => { + let commenter; + try { + commenter = getCommenter(octokit, { + owner, + repo, + number, + commitSHA, + }); + } catch (err) { + core.setFailed(err); + return; + } -"use strict"; -module.exports = require("util");; + const effectiveModes = [ + { name: 'recreate', flag: recreateComment }, + { name: 'append', flag: appendComment }, + { name: 'replace', flag: replaceComment }, + { name: 'delete', flag: deleteComment }, + ].filter((m) => m.flag === 'true'); -/***/ }), + if (effectiveModes.length > 1) { + const effectiveModeNames = effectiveModes.map((m) => m.name).join(', '); + core.setFailed(`Only one of ${effectiveModeNames} can be set to true.`); + return; + } -/***/ 761: -/***/ ((module) => { + let mode; + + switch (effectiveModes[0].name) { + case 'recreate': + mode = recreateMode; + break; + case 'append': + mode = appendMode; + break; + case 'replace': + mode = replaceMode; + break; + case 'delete': + mode = deleteMode; + break; + default: + mode = normalMode; + break; + } -"use strict"; -module.exports = require("zlib");; + await mode(commenter, identifier, message); -/***/ }) + if (fail === 'true') { + core.setFailed(message); + } + } catch (error) { + console.error(error); + core.setFailed(error.message); + } +})(); -/******/ }); -/************************************************************************/ -/******/ // The module cache -/******/ var __webpack_module_cache__ = {}; -/******/ -/******/ // The require function -/******/ function __nccwpck_require__(moduleId) { -/******/ // Check if module is in cache -/******/ if(__webpack_module_cache__[moduleId]) { -/******/ return __webpack_module_cache__[moduleId].exports; -/******/ } -/******/ // Create a new module (and put it into the cache) -/******/ var module = __webpack_module_cache__[moduleId] = { -/******/ // no module.id needed -/******/ // no module.loaded needed -/******/ exports: {} -/******/ }; -/******/ -/******/ // Execute the module function -/******/ var threw = true; -/******/ try { -/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __nccwpck_require__); -/******/ threw = false; -/******/ } finally { -/******/ if(threw) delete __webpack_module_cache__[moduleId]; -/******/ } -/******/ -/******/ // Return the exports of the module -/******/ return module.exports; -/******/ } -/******/ -/************************************************************************/ -/******/ /* webpack/runtime/make namespace object */ -/******/ (() => { -/******/ // define __esModule on exports -/******/ __nccwpck_require__.r = (exports) => { -/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { -/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); -/******/ } -/******/ Object.defineProperty(exports, '__esModule', { value: true }); -/******/ }; -/******/ })(); -/******/ -/******/ /* webpack/runtime/compat */ -/******/ -/******/ __nccwpck_require__.ab = __dirname + "/";/************************************************************************/ -/******/ // module exports must be returned from runtime so entry inlining is disabled -/******/ // startup -/******/ // Load entry module and return exports -/******/ return __nccwpck_require__(752); +})(); + +module.exports = __webpack_exports__; /******/ })() ; \ No newline at end of file From 15c9ce8c640bb5b4cb1baf60f4072723289a8ae9 Mon Sep 17 00:00:00 2001 From: Cateiru Date: Fri, 14 Jun 2024 15:33:02 +0900 Subject: [PATCH 8/8] updated README --- README.md | 47 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index a0e7242..18024bc 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,10 @@ If the workflow succeeds, the bot comments the details of the preview environmen # If a comment with the given id is not found, a new comment is created append: true + # Replaces the message of a comment that already exits with the given id. + # If a comment with the given id is not found, a new comment is created + replace: true + # Deletes all the existing comments matching the given id and # creates a new comment with the given message recreate: true @@ -63,9 +67,7 @@ If the workflow succeeds, the bot comments the details of the preview environmen delete: true ``` -**Note:** The `number` and `commit-sha` fields are mutually exclusive. Only one of them should be set in a job. If both or none are present, an error will be thrown and the job will fail. - -**Note**: The `append` and `recreate` fields are also mutually exclusive. If none of them are set, the job will continue in normal mode but if both are present an error will be thrown and the job will fail. +**Note**: `append`, `recreate`, `replace`, and `delete` fields are mutually exclusive. If more than one of them are set, an error will be thrown and the job will fail. ## Scenarios @@ -165,6 +167,45 @@ jobs: append: true ``` +### Create a comment and replace an identical comment + +This uses the `replace` flag to replace any existing comment created with the same id. + +```yml +on: + pull_request: + types: [opened] + +jobs: + deploy-preview: + runs-on: ubuntu-20.04 + name: Deploy preview + steps: + - name: Notify about starting this deployment + uses: hasura/comment-progress@v2.3.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + repository: "my-org/my-repo" + number: ${{ github.event.number }} + id: deploy-preview + message: "Starting deployment of this pull request." + + - name: Deploy preview + run: | + echo "deploy preview" + # long running step + + - name: Notify about the result of this deployment + uses: hasura/comment-progress@v2.3.0 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + repository: "my-org/my-repo" + number: ${{ github.event.number }} + id: deploy-preview + message: "Deployment of a preview for this pull request was successful." + replace: true +``` + ### Delete older/stale comment and add a new comment Take a case where you need to re-deploy a preview for your pull request and report the status of the redeployment as a new comment and at the same time delete the old comment containing stale information. `recreate` flag will help in achieving this scenario.