diff --git a/.cspell.json b/.cspell.json index ae85a2a..407d2d2 100644 --- a/.cspell.json +++ b/.cspell.json @@ -4,7 +4,7 @@ "ignorePaths": ["**/*.json", "**/*.css", "node_modules", "**/*.log"], "useGitignore": true, "language": "en", - "words": ["dataurl", "devpool", "outdir", "servedir", "typebox"], + "words": ["dataurl", "devpool", "outdir", "servedir", "typebox", "gentlementlegen"], "dictionaries": ["typescript", "node", "software-terms"], "import": ["@cspell/dict-typescript/cspell-ext.json", "@cspell/dict-node/cspell-ext.json", "@cspell/dict-software-terms"], "ignoreRegExpList": ["[0-9a-fA-F]{6}"] diff --git a/src/comment.ts b/src/comment.ts index 170c884..33bfa6a 100644 --- a/src/comment.ts +++ b/src/comment.ts @@ -5,10 +5,30 @@ import { sanitizeMetadata } from "./util"; const HEADER_NAME = "UbiquityOS"; +export interface CommentOptions { + /* + * Should the comment be posted as send within the log, without adding any sort of formatting. + */ + raw?: boolean; + /* + * Should the previously posted comment be reused instead of posting a new comment. + */ + updateComment?: boolean; +} + +export type PostComment = { + (context: Context, message: LogReturn | Error, options?: CommentOptions): Promise; + lastCommentId?: number; +}; + /** * Posts a comment on a GitHub issue if the issue exists in the context payload, embedding structured metadata to it. */ -export async function postComment(context: Context, message: LogReturn | Error, raw = false) { +export const postComment: PostComment = async function ( + context: Context, + message: LogReturn | Error, + options: CommentOptions = { updateComment: true, raw: false } +) { let issueNumber; if ("issue" in context.payload) { @@ -23,19 +43,29 @@ export async function postComment(context: Context, message: LogReturn | Error, } if ("repository" in context.payload && context.payload.repository?.owner?.login) { - const body = await createStructuredMetadataWithMessage(context, message, raw); - await context.octokit.rest.issues.createComment({ - owner: context.payload.repository.owner.login, - repo: context.payload.repository.name, - issue_number: issueNumber, - body: body, - }); + const body = await createStructuredMetadataWithMessage(context, message, options); + if (options.updateComment && postComment.lastCommentId) { + await context.octokit.rest.issues.updateComment({ + owner: context.payload.repository.owner.login, + repo: context.payload.repository.name, + comment_id: postComment.lastCommentId, + body: body, + }); + } else { + const commentData = await context.octokit.rest.issues.createComment({ + owner: context.payload.repository.owner.login, + repo: context.payload.repository.name, + issue_number: issueNumber, + body: body, + }); + postComment.lastCommentId = commentData.data.id; + } } else { context.logger.info("Cannot post comment because repository is not found in the payload.", { payload: context.payload }); } -} +}; -async function createStructuredMetadataWithMessage(context: Context, message: LogReturn | Error, raw = false) { +async function createStructuredMetadataWithMessage(context: Context, message: LogReturn | Error, options: CommentOptions) { let logMessage; let callingFnName; let instigatorName; @@ -85,5 +115,5 @@ async function createStructuredMetadataWithMessage(context: Context, message: Lo } // Add carriage returns to avoid any formatting issue - return `${raw ? logMessage?.raw : logMessage?.diff}\n\n${metadataSerialized}\n`; + return `${options.raw ? logMessage?.raw : logMessage?.diff}\n\n${metadataSerialized}\n`; } diff --git a/tests/comment.test.ts b/tests/comment.test.ts new file mode 100644 index 0000000..6ebb5fd --- /dev/null +++ b/tests/comment.test.ts @@ -0,0 +1,59 @@ +import { describe, expect, it, jest } from "@jest/globals"; +import { Logs } from "@ubiquity-os/ubiquity-os-logger"; +import { Context, postComment } from "../src"; + +describe("Post comment tests", () => { + it("Should reuse a message if the reuse option is true", async () => { + const logger = new Logs("debug"); + const createComment = jest.fn(() => ({ + data: { + id: 1234, + }, + })); + const updateComment = jest.fn(() => ({ + data: { + id: 1234, + }, + })); + jest.unstable_mockModule("@octokit/core", () => ({ + Octokit: jest.fn(() => ({ + rest: { + issues: { + createComment, + updateComment, + }, + }, + })), + })); + const { Octokit } = await import("@octokit/core"); + const ctx = { + payload: { + issue: { + number: 1, + }, + repository: { + owner: { + login: "ubiquity-os", + }, + name: "plugin-sdk", + }, + }, + logger, + octokit: new Octokit(), + } as unknown as Context; + await postComment(ctx, logger.ok("test"), { updateComment: true }); + await postComment(ctx, logger.ok("test 2"), { updateComment: true }); + expect(createComment).toHaveBeenCalledWith({ + owner: "ubiquity-os", + repo: "plugin-sdk", + issue_number: 1, + body: expect.anything(), + }); + expect(updateComment).toHaveBeenCalledWith({ + owner: "ubiquity-os", + repo: "plugin-sdk", + comment_id: 1234, + body: expect.anything(), + }); + }); +}); diff --git a/tests/sdk.test.ts b/tests/sdk.test.ts index 80f3274..657882a 100644 --- a/tests/sdk.test.ts +++ b/tests/sdk.test.ts @@ -219,9 +219,9 @@ describe("SDK worker tests", () => { ! test error \`\`\` - `,