From 94f0998581cb14903318950325bef8c060c04abe Mon Sep 17 00:00:00 2001 From: Mario Campos Date: Thu, 29 Oct 2026 11:32:57 -0500 Subject: [PATCH] Avoid creating resolved comments without an existing warning Use a boolean --create-if-missing flag, supplied by the composite action by default and omitted for resolution updates. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .github/actions/post-comment/action.yml | 6 ++++++ .github/workflows/pr-checks.yml | 1 + pr-checks/post-comment.test.ts | 28 ++++++++++++++++++++++++- pr-checks/post-comment.ts | 10 +++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/.github/actions/post-comment/action.yml b/.github/actions/post-comment/action.yml index 8055bf21d..bf8a39b48 100644 --- a/.github/actions/post-comment/action.yml +++ b/.github/actions/post-comment/action.yml @@ -9,6 +9,10 @@ inputs: body: description: "Full comment markdown." required: true + create-if-missing: + description: "Create a comment if no matching marker exists. Set to 'false' to update existing comments only." + required: false + default: "true" issue-id: description: > The issue or pull request number to post/update the comment on. @@ -25,11 +29,13 @@ runs: env: BODY: ${{ inputs.body }} MARKER: ${{ inputs.marker }} + CREATE_IF_MISSING: ${{ inputs.create-if-missing != 'false' && '--create-if-missing' || '' }} GH_TOKEN: ${{ inputs.token }} ISSUE_ID: ${{ inputs.issue-id || github.event.pull_request.number }} run: | npx tsx ./pr-checks/post-comment.ts \ --body "$BODY" \ --marker "$MARKER" \ + $CREATE_IF_MISSING \ --issue-id "$ISSUE_ID" \ --repository "$GITHUB_REPOSITORY" diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index eda085049..7398391d3 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -313,6 +313,7 @@ jobs: uses: ./.github/actions/post-comment with: marker: "post-comment:CHANGELOG.md" + create-if-missing: "false" body: | ⚠️ `CHANGELOG.md` has been modified in this PR. Please do not modify `CHANGELOG.md` directly. Instead, create a change-note file in `unreleased-change-notes/`. The `CHANGELOG.md` diff --git a/pr-checks/post-comment.test.ts b/pr-checks/post-comment.test.ts index 7e02c4900..63e0f6caa 100644 --- a/pr-checks/post-comment.test.ts +++ b/pr-checks/post-comment.test.ts @@ -49,11 +49,17 @@ describe("parseOptions", async () => { assert.deepEqual(options, { body: "hello", marker: "marker", + createIfMissing: false, issueId: 42, repository: { owner: "github", repo: "codeql-action" }, }); }); + await it("enables creation when --create-if-missing is supplied", () => { + const options = parseOptions([...validFlags, "--create-if-missing"]); + assert.equal(options.createIfMissing, true); + }); + await it("rejects a missing --body", () => { assert.throws( () => parseOptions(withoutFlag("--body")), @@ -206,6 +212,7 @@ describe("findExistingComment", async () => { const baseOptions: Options = { body: "hello", marker: "marker", + createIfMissing: true, issueId: 42, repository: { owner: "owner", repo: "repo" }, }; @@ -220,6 +227,25 @@ function assertCommentContent( } describe("setComment", async () => { + await it("does not create a resolved comment when no comments exist", async () => { + const { client, comments } = fakeClient([]); + + await setComment(client, { ...baseOptions, createIfMissing: false }); + + // Resolution does not introduce a warning that was never posted. + assert.deepEqual(comments, []); + }); + + await it("leaves unrelated comments unchanged when creation is disabled", async () => { + const originalComments = [{ id: 7, body: "unrelated" }]; + const { client, comments } = fakeClient(originalComments); + + await setComment(client, { ...baseOptions, createIfMissing: false }); + + // Unrelated comments neither trigger resolution nor get overwritten. + assert.deepEqual(comments, originalComments); + }); + await it("uses the supplied marker without affecting other comments", async () => { const marker = "custom-warning"; const { client, comments } = fakeClient([ @@ -308,7 +334,7 @@ describe("setComment", async () => { const body = "`CHANGELOG.md` is not modified in this PR. No changelog action is needed."; - await setComment(client, { ...baseOptions, body }); + await setComment(client, { ...baseOptions, body, createIfMissing: false }); // The resolved state replaces the warning on the same marked comment. assert.equal(comments.length, 1); diff --git a/pr-checks/post-comment.ts b/pr-checks/post-comment.ts index e254221eb..bcb598872 100644 --- a/pr-checks/post-comment.ts +++ b/pr-checks/post-comment.ts @@ -5,10 +5,12 @@ Creates or updates a pull request comment identified by a marker. The marker is supplied via `--marker` (or the `.github/actions/post-comment` action's `marker` input) and must be non-empty. Supply a plain-text identifier; the CLI wraps it in a hidden HTML comment, prepends it to `--body`, and uses it to find the comment on later runs. +Supply `--create-if-missing` to allow creation; omit it to update existing comments only. Example: ```sh GH_TOKEN= npx tsx ./pr-checks/post-comment.ts \ + --create-if-missing \ --body "The changelog needs updating." \ --marker "my-bot" \ --issue-id 123 \ @@ -29,6 +31,8 @@ export interface Options { body: string; /** Plain-text identifier wrapped in a hidden HTML comment. */ marker: string; + /** Whether to create a comment when no matching marker exists. */ + createIfMissing: boolean; /** The issue/pull request number to post/update the comment on. */ issueId: number; /** The repository to operate on. */ @@ -46,6 +50,7 @@ export function parseOptions(argv?: string[]): Options { options: { body: { type: "string" }, marker: { type: "string" }, + "create-if-missing": { type: "boolean", default: false }, "issue-id": { type: "string" }, repository: { type: "string" }, }, @@ -76,6 +81,7 @@ export function parseOptions(argv?: string[]): Options { return { body: values.body, marker: values.marker, + createIfMissing: values["create-if-missing"], issueId: Number(values["issue-id"]), repository: { owner, repo }, }; @@ -126,6 +132,10 @@ export async function setComment( marker, ); if (existingCommentId === undefined) { + if (!options.createIfMissing) { + console.info("No existing comment found; skipping creation."); + return; + } console.info("No existing comment found; creating a new comment."); await client.rest.issues.createComment({ ...repository,