feat: exclude hidden (minimized) comments from GitHub Issues and PRs (#368)

* feat: ignore minimized comments

* fix tests
This commit is contained in:
atsushi-ishibashi
2025-07-30 23:18:34 +09:00
committed by GitHub
parent 5bdc533a52
commit fd012347a2
5 changed files with 221 additions and 3 deletions

View File

@@ -46,6 +46,7 @@ export const PR_QUERY = `
login login
} }
createdAt createdAt
isMinimized
} }
} }
reviews(first: 100) { reviews(first: 100) {
@@ -69,6 +70,7 @@ export const PR_QUERY = `
login login
} }
createdAt createdAt
isMinimized
} }
} }
} }
@@ -98,6 +100,7 @@ export const ISSUE_QUERY = `
login login
} }
createdAt createdAt
isMinimized
} }
} }
} }

View File

@@ -134,7 +134,7 @@ export async function fetchGitHubData({
// Prepare all comments for image processing // Prepare all comments for image processing
const issueComments: CommentWithImages[] = comments const issueComments: CommentWithImages[] = comments
.filter((c) => c.body) .filter((c) => c.body && !c.isMinimized)
.map((c) => ({ .map((c) => ({
type: "issue_comment" as const, type: "issue_comment" as const,
id: c.databaseId, id: c.databaseId,
@@ -154,7 +154,7 @@ export async function fetchGitHubData({
const reviewComments: CommentWithImages[] = const reviewComments: CommentWithImages[] =
reviewData?.nodes reviewData?.nodes
?.flatMap((r) => r.comments?.nodes ?? []) ?.flatMap((r) => r.comments?.nodes ?? [])
.filter((c) => c.body) .filter((c) => c.body && !c.isMinimized)
.map((c) => ({ .map((c) => ({
type: "review_comment" as const, type: "review_comment" as const,
id: c.databaseId, id: c.databaseId,

View File

@@ -50,6 +50,7 @@ export function formatComments(
imageUrlMap?: Map<string, string>, imageUrlMap?: Map<string, string>,
): string { ): string {
return comments return comments
.filter((comment) => !comment.isMinimized)
.map((comment) => { .map((comment) => {
let body = comment.body; let body = comment.body;
@@ -96,6 +97,7 @@ export function formatReviewComments(
review.comments.nodes.length > 0 review.comments.nodes.length > 0
) { ) {
const comments = review.comments.nodes const comments = review.comments.nodes
.filter((comment) => !comment.isMinimized)
.map((comment) => { .map((comment) => {
let body = comment.body; let body = comment.body;
@@ -110,7 +112,9 @@ export function formatReviewComments(
return ` [Comment on ${comment.path}:${comment.line || "?"}]: ${body}`; return ` [Comment on ${comment.path}:${comment.line || "?"}]: ${body}`;
}) })
.join("\n"); .join("\n");
reviewOutput += `\n${comments}`; if (comments) {
reviewOutput += `\n${comments}`;
}
} }
return reviewOutput; return reviewOutput;

View File

@@ -10,6 +10,7 @@ export type GitHubComment = {
body: string; body: string;
author: GitHubAuthor; author: GitHubAuthor;
createdAt: string; createdAt: string;
isMinimized?: boolean;
}; };
export type GitHubReviewComment = GitHubComment & { export type GitHubReviewComment = GitHubComment & {

View File

@@ -252,6 +252,63 @@ describe("formatComments", () => {
`[user1 at 2023-01-01T00:00:00Z]: Image: ![](https://github.com/user-attachments/assets/test.png)`, `[user1 at 2023-01-01T00:00:00Z]: Image: ![](https://github.com/user-attachments/assets/test.png)`,
); );
}); });
test("filters out minimized comments", () => {
const comments: GitHubComment[] = [
{
id: "1",
databaseId: "100001",
body: "Normal comment",
author: { login: "user1" },
createdAt: "2023-01-01T00:00:00Z",
isMinimized: false,
},
{
id: "2",
databaseId: "100002",
body: "Minimized comment",
author: { login: "user2" },
createdAt: "2023-01-02T00:00:00Z",
isMinimized: true,
},
{
id: "3",
databaseId: "100003",
body: "Another normal comment",
author: { login: "user3" },
createdAt: "2023-01-03T00:00:00Z",
},
];
const result = formatComments(comments);
expect(result).toBe(
`[user1 at 2023-01-01T00:00:00Z]: Normal comment\n\n[user3 at 2023-01-03T00:00:00Z]: Another normal comment`,
);
});
test("returns empty string when all comments are minimized", () => {
const comments: GitHubComment[] = [
{
id: "1",
databaseId: "100001",
body: "Minimized comment 1",
author: { login: "user1" },
createdAt: "2023-01-01T00:00:00Z",
isMinimized: true,
},
{
id: "2",
databaseId: "100002",
body: "Minimized comment 2",
author: { login: "user2" },
createdAt: "2023-01-02T00:00:00Z",
isMinimized: true,
},
];
const result = formatComments(comments);
expect(result).toBe("");
});
}); });
describe("formatReviewComments", () => { describe("formatReviewComments", () => {
@@ -517,6 +574,159 @@ describe("formatReviewComments", () => {
`[Review by reviewer1 at 2023-01-01T00:00:00Z]: APPROVED\nReview body\n [Comment on src/index.ts:42]: Image: ![](https://github.com/user-attachments/assets/test.png)`, `[Review by reviewer1 at 2023-01-01T00:00:00Z]: APPROVED\nReview body\n [Comment on src/index.ts:42]: Image: ![](https://github.com/user-attachments/assets/test.png)`,
); );
}); });
test("filters out minimized review comments", () => {
const reviewData = {
nodes: [
{
id: "review1",
databaseId: "300001",
author: { login: "reviewer1" },
body: "Review with mixed comments",
state: "APPROVED",
submittedAt: "2023-01-01T00:00:00Z",
comments: {
nodes: [
{
id: "comment1",
databaseId: "200001",
body: "Normal review comment",
author: { login: "reviewer1" },
createdAt: "2023-01-01T00:00:00Z",
path: "src/index.ts",
line: 42,
isMinimized: false,
},
{
id: "comment2",
databaseId: "200002",
body: "Minimized review comment",
author: { login: "reviewer1" },
createdAt: "2023-01-01T00:00:00Z",
path: "src/utils.ts",
line: 15,
isMinimized: true,
},
{
id: "comment3",
databaseId: "200003",
body: "Another normal comment",
author: { login: "reviewer1" },
createdAt: "2023-01-01T00:00:00Z",
path: "src/main.ts",
line: 10,
},
],
},
},
],
};
const result = formatReviewComments(reviewData);
expect(result).toBe(
`[Review by reviewer1 at 2023-01-01T00:00:00Z]: APPROVED\nReview with mixed comments\n [Comment on src/index.ts:42]: Normal review comment\n [Comment on src/main.ts:10]: Another normal comment`,
);
});
test("returns review with only body when all review comments are minimized", () => {
const reviewData = {
nodes: [
{
id: "review1",
databaseId: "300001",
author: { login: "reviewer1" },
body: "Review body only",
state: "APPROVED",
submittedAt: "2023-01-01T00:00:00Z",
comments: {
nodes: [
{
id: "comment1",
databaseId: "200001",
body: "Minimized comment 1",
author: { login: "reviewer1" },
createdAt: "2023-01-01T00:00:00Z",
path: "src/index.ts",
line: 42,
isMinimized: true,
},
{
id: "comment2",
databaseId: "200002",
body: "Minimized comment 2",
author: { login: "reviewer1" },
createdAt: "2023-01-01T00:00:00Z",
path: "src/utils.ts",
line: 15,
isMinimized: true,
},
],
},
},
],
};
const result = formatReviewComments(reviewData);
expect(result).toBe(
`[Review by reviewer1 at 2023-01-01T00:00:00Z]: APPROVED\nReview body only`,
);
});
test("handles multiple reviews with mixed minimized comments", () => {
const reviewData = {
nodes: [
{
id: "review1",
databaseId: "300001",
author: { login: "reviewer1" },
body: "First review",
state: "APPROVED",
submittedAt: "2023-01-01T00:00:00Z",
comments: {
nodes: [
{
id: "comment1",
databaseId: "200001",
body: "Good comment",
author: { login: "reviewer1" },
createdAt: "2023-01-01T00:00:00Z",
path: "src/index.ts",
line: 42,
isMinimized: false,
},
],
},
},
{
id: "review2",
databaseId: "300002",
author: { login: "reviewer2" },
body: "Second review",
state: "COMMENTED",
submittedAt: "2023-01-02T00:00:00Z",
comments: {
nodes: [
{
id: "comment2",
databaseId: "200002",
body: "Spam comment",
author: { login: "reviewer2" },
createdAt: "2023-01-02T00:00:00Z",
path: "src/utils.ts",
line: 15,
isMinimized: true,
},
],
},
},
],
};
const result = formatReviewComments(reviewData);
expect(result).toBe(
`[Review by reviewer1 at 2023-01-01T00:00:00Z]: APPROVED\nFirst review\n [Comment on src/index.ts:42]: Good comment\n\n[Review by reviewer2 at 2023-01-02T00:00:00Z]: COMMENTED\nSecond review`,
);
});
}); });
describe("formatChangedFiles", () => { describe("formatChangedFiles", () => {