diff --git a/package-lock.json b/package-lock.json index 0e46702892..814b40ffe0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1201,6 +1201,17 @@ "node": ">= 18" } }, + "node_modules/@octokit/graphql-schema": { + "version": "15.26.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql-schema/-/graphql-schema-15.26.0.tgz", + "integrity": "sha512-SoVbh+sXe9nsoweFbLT3tAk3XWYbYLs5ku05wij1zhyQ2U3lewdrhjo5Tb7lfaOGWNHSkPZT4uuPZp8neF7P7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "graphql": "^16.0.0", + "graphql-tag": "^2.10.3" + } + }, "node_modules/@octokit/openapi-types": { "version": "24.2.0", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz", @@ -4462,6 +4473,39 @@ "dev": true, "license": "MIT" }, + "node_modules/graphql": { + "version": "16.10.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.10.0.tgz", + "integrity": "sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" + } + }, + "node_modules/graphql-tag": { + "version": "2.12.6", + "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", + "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "graphql": "^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, + "node_modules/graphql-tag/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, "node_modules/has-bigints": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", @@ -8576,6 +8620,7 @@ "@actions/github": "^6.0.0" }, "devDependencies": { + "@octokit/graphql-schema": "^15.26.0", "@playwright/test": "1.52.0-next" }, "engines": { diff --git a/packages/playwright-dashboard/package.json b/packages/playwright-dashboard/package.json index 024b493669..81a18829c5 100644 --- a/packages/playwright-dashboard/package.json +++ b/packages/playwright-dashboard/package.json @@ -23,6 +23,7 @@ "@actions/github": "^6.0.0" }, "devDependencies": { + "@octokit/graphql-schema": "^15.26.0", "@playwright/test": "1.52.0-next" } } diff --git a/packages/playwright-dashboard/src/ghaMarkdownReporter.ts b/packages/playwright-dashboard/src/ghaMarkdownReporter.ts index 34b3447153..98dccd7ef6 100644 --- a/packages/playwright-dashboard/src/ghaMarkdownReporter.ts +++ b/packages/playwright-dashboard/src/ghaMarkdownReporter.ts @@ -20,6 +20,7 @@ import * as core from '@actions/core'; import MarkdownReporter from './markdownReporter'; import type { MetadataWithCommitInfo } from 'playwright/src/isomorphic/types'; +import type { IssueCommentEdge, Repository } from '@octokit/graphql-schema'; function getGithubToken() { const token = process.env.GITHUB_TOKEN || core.getInput('github-token'); @@ -44,45 +45,75 @@ class GHAMarkdownReporter extends MarkdownReporter { } core.info(`Posting comment to PR ${prHref}`); - await this.collapsePreviousComments(prNumber); - await this.addNewReportComment(prNumber, report); + const prNodeId = await this.collapsePreviousComments(prNumber); + if (!prNodeId) { + core.warning(`No PR node ID found, skipping GHA comment. PR href: ${prHref}`); + return; + } + await this.addNewReportComment(prNodeId, report); } private async collapsePreviousComments(prNumber: number) { - const { data: comments } = await octokit.rest.issues.listComments({ - ...context.repo, - issue_number: prNumber, - }); - for (const comment of comments) { - if (comment.user?.login === 'github-actions[bot]' && comment.body?.includes(magicComment)) { - core.info(`Minimizing comment: ${comment.html_url}`); - await octokit.graphql(` - mutation { - minimizeComment(input: {subjectId: "${comment.node_id}", classifier: OUTDATED}) { - clientMutationId + const { owner, repo } = context.repo; + const data = await octokit.graphql<{ repository: Repository }>(` + query { + repository(owner: "${owner}", name: "${repo}") { + pullRequest(number: ${prNumber}) { + id + comments(last: 100) { + nodes { + id + body + author { + login + } + } } } - `); + } } - } + `); + const comments = data.repository.pullRequest?.comments.nodes?.filter( + comment => comment?.author?.login === 'github-actions[bot]' && comment.body?.includes(magicComment)); + const prId = data.repository.pullRequest?.id; + if (!comments?.length) + return prId; + const mutations = comments.map((comment, i) => + `m${i}: minimizeComment(input: { subjectId: "${comment!.id}", classifier: OUTDATED }) { clientMutationId }`); + await octokit.graphql(` + mutation { + ${mutations.join('\n')} + } + `); + return prId; } - private async addNewReportComment(prNumber: number, report: string) { + private async addNewReportComment(prNodeId: string, report: string) { const reportUrl = process.env.HTML_REPORT_URL; const mergeWorkflowUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; - const { data: response } = await octokit.rest.issues.createComment({ - ...context.repo, - issue_number: prNumber, - body: formatComment([ - magicComment, - `### [Test results](${reportUrl}) for "${context.payload.workflow_run?.name}"`, - report, - '', - `Merge [workflow run](${mergeWorkflowUrl}).` - ]), - }); - core.info(`Posted comment: ${response.html_url}`); + const body = formatComment([ + magicComment, + `### [Test results](${reportUrl}) for "${context.payload.workflow_run?.name}"`, + report, + '', + `Merge [workflow run](${mergeWorkflowUrl}).` + ]); + + const response = await octokit.graphql<{ addComment: { commentEdge: IssueCommentEdge } }>(` + mutation { + addComment(input: {subjectId: "${prNodeId}", body: """${body}"""}) { + commentEdge { + node { + ... on IssueComment { + url + } + } + } + } + } + `); + core.info(`Posted comment: ${response.addComment.commentEdge.node?.url}`); } private pullRequestFromMetadata() {