diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5cd1d35..bb42ed4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -109,6 +109,17 @@ jobs: - if: steps.fc6.outputs.comment-id != 703352283 run: exit 1 + - name: Find the last comment by body-includes and author + uses: ./ + id: fc7 + with: + issue-number: 1 + comment-author: peter-evans + body-includes: search string 1 + direction: last + - if: steps.fc7.outputs.comment-id != 771260630 + run: exit 1 + package: if: github.event_name == 'push' && github.ref == 'refs/heads/master' needs: [test] diff --git a/README.md b/README.md index bb4a254..51fee78 100644 --- a/README.md +++ b/README.md @@ -4,11 +4,11 @@ A GitHub action to find an issue or pull request comment. -The action will output the comment ID of the first comment matching the search criteria. +The action will output the comment ID of the comment matching the search criteria. ## Usage -### Find a comment containing the specified string +### Find the first comment containing the specified string ```yml - name: Find Comment @@ -19,7 +19,7 @@ The action will output the comment ID of the first comment matching the search c body-includes: search string 1 ``` -### Find a comment by the specified author +### Find the first comment by the specified author ```yml - name: Find Comment @@ -30,7 +30,7 @@ The action will output the comment ID of the first comment matching the search c comment-author: peter-evans ``` -### Find a comment containing the specified string AND by the specified author +### Find the first comment containing the specified string AND by the specified author ```yml - name: Find Comment @@ -42,6 +42,18 @@ The action will output the comment ID of the first comment matching the search c body-includes: search string 1 ``` +### Find the last comment containing the specified string + +```yml + - name: Find Comment + uses: peter-evans/find-comment@v1 + id: fc + with: + issue-number: 1 + body-includes: search string 1 + direction: last +``` + ### Action inputs | Name | Description | Default | @@ -51,10 +63,11 @@ The action will output the comment ID of the first comment matching the search c | `issue-number` | The number of the issue or pull request in which to search. | | | `comment-author` | The GitHub user name of the comment author. | | | `body-includes` | A string to search for in the body of comments. | | +| `direction` | Search direction, specified as `first` or `last` | `first` | #### Outputs -The `comment-id` and `comment-body` of the first matching comment found will be output for use in later steps. +The `comment-id` and `comment-body` of the matching comment found will be output for use in later steps. They will be empty strings if no matching comment was found. Note that in order to read the step outputs the action step must have an id. diff --git a/action.yml b/action.yml index ecd00b4..5cf34ad 100644 --- a/action.yml +++ b/action.yml @@ -13,9 +13,12 @@ inputs: description: 'The GitHub user name of the comment author.' body-includes: description: 'A string to search for in the body of comments.' + direction: + description: 'Search direction, specified as `first` or `last`' + default: first outputs: comment-id: - description: 'The id of the first matching comment found.' + description: 'The id of the matching comment found.' runs: using: 'node12' main: 'dist/index.js' diff --git a/dist/index.js b/dist/index.js index ab5083a..da72567 100644 --- a/dist/index.js +++ b/dist/index.js @@ -46,6 +46,12 @@ Object.defineProperty(exports, "__esModule", ({ value: true })); const core = __importStar(__webpack_require__(186)); const github = __importStar(__webpack_require__(438)); const util_1 = __webpack_require__(669); +function findCommentPredicate(inputs, comment) { + return ((inputs.commentAuthor + ? comment.user.login === inputs.commentAuthor + : true) && + (inputs.bodyIncludes ? comment.body.includes(inputs.bodyIncludes) : true)); +} function findComment(inputs) { var e_1, _a; return __awaiter(this, void 0, void 0, function* () { @@ -56,32 +62,45 @@ function findComment(inputs) { repo: repo, issue_number: inputs.issueNumber }; - try { - for (var _b = __asyncValues(octokit.paginate.iterator(octokit.issues.listComments, parameters)), _c; _c = yield _b.next(), !_c.done;) { - const { data: comments } = _c.value; - // Search each page for the comment - const comment = comments.find(comment => { - return ((inputs.commentAuthor - ? comment.user.login === inputs.commentAuthor - : true) && - (inputs.bodyIncludes - ? comment.body.includes(inputs.bodyIncludes) - : true)); - }); - if (comment) { - return { - id: comment.id, - body: comment.body - }; + if (inputs.direction == 'first') { + try { + for (var _b = __asyncValues(octokit.paginate.iterator(octokit.issues.listComments, parameters)), _c; _c = yield _b.next(), !_c.done;) { + const { data: comments } = _c.value; + // Search each page for the comment + const comment = comments.find(comment => findCommentPredicate(inputs, comment)); + if (comment) { + return { + id: comment.id, + body: comment.body, + user: { + login: comment.user.login + } + }; + } + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b); } + finally { if (e_1) throw e_1.error; } } } - catch (e_1_1) { e_1 = { error: e_1_1 }; } - finally { - try { - if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b); + else { + // direction == 'last' + const comments = yield octokit.paginate(octokit.issues.listComments, parameters); + comments.reverse(); + const comment = comments.find(comment => findCommentPredicate(inputs, comment)); + if (comment) { + return { + id: comment.id, + body: comment.body, + user: { + login: comment.user.login + } + }; } - finally { if (e_1) throw e_1.error; } } return undefined; }); @@ -94,7 +113,8 @@ function run() { repository: core.getInput('repository'), issueNumber: Number(core.getInput('issue-number')), commentAuthor: core.getInput('comment-author'), - bodyIncludes: core.getInput('body-includes') + bodyIncludes: core.getInput('body-includes'), + direction: core.getInput('direction') }; core.debug(`Inputs: ${util_1.inspect(inputs)}`); const comment = yield findComment(inputs); diff --git a/src/main.ts b/src/main.ts index f89817f..098ee86 100644 --- a/src/main.ts +++ b/src/main.ts @@ -8,11 +8,24 @@ interface Inputs { issueNumber: number commentAuthor: string bodyIncludes: string + direction: string } interface Comment { id: number body: string + user: { + login: string + } +} + +function findCommentPredicate(inputs: Inputs, comment: Comment): boolean { + return ( + (inputs.commentAuthor + ? comment.user.login === inputs.commentAuthor + : true) && + (inputs.bodyIncludes ? comment.body.includes(inputs.bodyIncludes) : true) + ) } async function findComment(inputs: Inputs): Promise { @@ -24,25 +37,43 @@ async function findComment(inputs: Inputs): Promise { repo: repo, issue_number: inputs.issueNumber } - for await (const {data: comments} of octokit.paginate.iterator( - octokit.issues.listComments, - parameters - )) { - // Search each page for the comment - const comment = comments.find(comment => { - return ( - (inputs.commentAuthor - ? comment.user.login === inputs.commentAuthor - : true) && - (inputs.bodyIncludes - ? comment.body.includes(inputs.bodyIncludes) - : true) + + if (inputs.direction == 'first') { + for await (const {data: comments} of octokit.paginate.iterator( + octokit.issues.listComments, + parameters + )) { + // Search each page for the comment + const comment = comments.find(comment => + findCommentPredicate(inputs, comment) ) - }) + if (comment) { + return { + id: comment.id, + body: comment.body, + user: { + login: comment.user.login + } + } + } + } + } else { + // direction == 'last' + const comments = await octokit.paginate( + octokit.issues.listComments, + parameters + ) + comments.reverse() + const comment = comments.find(comment => + findCommentPredicate(inputs, comment) + ) if (comment) { return { id: comment.id, - body: comment.body + body: comment.body, + user: { + login: comment.user.login + } } } } @@ -56,7 +87,8 @@ async function run(): Promise { repository: core.getInput('repository'), issueNumber: Number(core.getInput('issue-number')), commentAuthor: core.getInput('comment-author'), - bodyIncludes: core.getInput('body-includes') + bodyIncludes: core.getInput('body-includes'), + direction: core.getInput('direction') } core.debug(`Inputs: ${inspect(inputs)}`)