eslint-rule-benchmark
Version:
Benchmark ESLint rules with detailed performance metrics for CI and plugin development
191 lines (189 loc) • 4.99 kB
JavaScript
import { graphql } from '@octokit/graphql'
import fs from 'node:fs/promises'
import { isGithubPullRequest } from './is-github-pull-request.js'
const BOT_COMMENT_MARKER = '<!-- eslint-rule-benchmark-report -->'
async function publishGithubComment(markdownReport) {
if (!isGithubPullRequest()) {
return
}
try {
let context = await getPullRequestContext()
if (!context) {
return
}
let gql = createGraphQLClient()
let { pullRequestNodeId, botCommentInfo } = await findBotComment(
gql,
context,
)
let reportBodyWithMarker = `${BOT_COMMENT_MARKER}
${markdownReport}`
if (botCommentInfo) {
try {
await updateBotComment(gql, botCommentInfo.id, reportBodyWithMarker)
} catch (error) {
let errorValue = error
console.error(
'Failed to update comment via GraphQL:',
errorValue.message,
)
}
} else {
if (!pullRequestNodeId) {
console.error('Cannot create comment, Pull Request Node ID not found.')
return
}
try {
await createBotComment(gql, pullRequestNodeId, reportBodyWithMarker)
} catch (error) {
let errorValue = error
console.error(
'Failed to create comment via GraphQL:',
errorValue.message,
)
}
}
} catch (error) {
console.error('Failed to post comment:', error)
}
}
async function findBotComment(gql, context) {
let botCommentInfo = null
let pullRequestNodeId = null
let cursor = null
let hasNextPage = true
while (hasNextPage) {
try {
let queryResult = await gql(
`
query (
$owner: String!
$repo: String!
$prNumber: Int!
$cursor: String
) {
repository(owner: $owner, name: $repo) {
pullRequest(number: $prNumber) {
id
comments(first: 100, after: $cursor) {
pageInfo {
endCursor
hasNextPage
}
nodes {
id
databaseId
body
author {
login
}
}
}
}
}
}
`,
{
prNumber: context.pullRequestNumber,
repo: context.repository,
owner: context.owner,
cursor,
},
)
pullRequestNodeId ??= queryResult.repository.pullRequest.id
let { comments } = queryResult.repository.pullRequest
let commentsNodes = comments.nodes
for (let commentNode of commentsNodes) {
if (commentNode.body.includes(BOT_COMMENT_MARKER)) {
botCommentInfo = {
databaseId: commentNode.databaseId,
id: commentNode.id,
}
hasNextPage = false
break
}
}
if (hasNextPage) {
;({ hasNextPage } = comments.pageInfo)
cursor = comments.pageInfo.endCursor
}
} catch (error) {
let errorValue = error
console.error('Failed to fetch comments via GraphQL:', errorValue.message)
throw error
}
}
return { pullRequestNodeId, botCommentInfo }
}
async function getPullRequestContext() {
try {
let eventPayloadString = await fs.readFile(
process.env['GITHUB_EVENT_PATH'],
'utf8',
)
let eventPayload = JSON.parse(eventPayloadString)
let pullRequestNumber = eventPayload.pull_request.number
let [owner, repository] = process.env['GITHUB_REPOSITORY'].split('/')
if (!pullRequestNumber || !owner || !repository) {
console.warn(
'GitHub PR Commenter: Could not determine PR number, owner, or repo.',
)
return null
}
return {
pullRequestNodeId: '',
pullRequestNumber,
repository,
owner,
}
} catch (error) {
let errorValue = error
console.error('Failed to read GitHub event payload:', errorValue.message)
return null
}
}
async function createBotComment(gql, pullRequestNodeId, body) {
await gql(
`
mutation ($subjectId: ID!, $body: String!) {
addComment(input: { subjectId: $subjectId, body: $body }) {
commentEdge {
node {
id
}
}
}
}
`,
{
subjectId: pullRequestNodeId,
body,
},
)
}
async function updateBotComment(gql, commentId, body) {
await gql(
`
mutation ($commentId: ID!, $body: String!) {
updateIssueComment(input: { id: $commentId, body: $body }) {
issueComment {
id
}
}
}
`,
{
commentId,
body,
},
)
}
function createGraphQLClient() {
let githubToken = process.env['GITHUB_TOKEN']
return graphql.defaults({
headers: {
authorization: `token ${githubToken}`,
},
})
}
export { publishGithubComment }