book000 / copilot-review-enforcer

0 stars 0 forks source link

CopilotがレビューしたコメントがすべてresolvedされるまでエラーとするCI #1

Open book000 opened 2 hours ago

book000 commented 2 hours ago

以下で resolved の状態とレビュー者は取得できる

query FetchReviewComments($owner: String!, $repo: String!, $pullRequestNumber: Int!) {
  repository(owner: $owner, name: $repo) {
    pullRequest(number: $pullRequestNumber) {
      reviewThreads(last: 100) {
        nodes {
          isResolved
          comments(first: 1) {
            nodes {
              author {
                login
              }
            }
          }
        }
      }
    }
  }
}
{
  "data": {
    "repository": {
      "pullRequest": {
        "reviewThreads": {
          "nodes": [
            {
              "isResolved": false,
              "comments": {
                "nodes": [
                  {
                    "author": {
                      "login": "copilot-pull-request-reviewer"
                    }
                  }
                ]
              }
            },
            {
              "isResolved": true,
              "comments": {
                "nodes": [
                  {
                    "author": {
                      "login": "copilot-pull-request-reviewer"
                    }
                  }
                ]
              }
            }
          ]
        }
      }
    }
  }
}
book000 commented 1 hour ago

トリガーは、pull_request opened, reopenイベント、pull_request_review_commentのcreated, edited, deletedイベントかな copilotがレビュアーにいなかったら追加する機能も欲しい。

あとは、pull_request_target synchronizeで、Copilotをレビュアーに追加する機能も。これはオンオフできていいと思う

book000 commented 1 hour ago

main.mjs

``

import { graphql } from "@octokit/graphql";

// GitHub Token for authentication const GITHUB_TOKEN = process.env.GITHUB_TOKEN;

if (!GITHUB_TOKEN) { console.error("GITHUB_TOKEN is not set."); process.exit(1); }

// Fetch review comments function async function fetchReviewComments(owner, repo, pullRequestNumber) { const query = query FetchReviewComments($owner: String!, $repo: String!, $pullRequestNumber: Int!) { repository(owner: $owner, name: $repo) { pullRequest(number: $pullRequestNumber) { reviewThreads(last: 100) { nodes { isResolved comments(first: 1) { nodes { author { login } } } } } } } } ;

try { const response = await graphql(query, { owner, repo, pullRequestNumber, headers: { authorization: Bearer ${GITHUB_TOKEN}, }, });

return response;

} catch (error) { console.error("Error fetching review comments:", error.message); process.exit(1); } }

// Main function async function checkUnresolvedComments( owner, repo, pullRequestNumber, targetLogin ) { const data = await fetchReviewComments(owner, repo, pullRequestNumber);

const reviewThreads = data.repository.pullRequest.reviewThreads.nodes;

// Filter unresolved comments by the target author const unresolvedComments = reviewThreads.filter( (thread) => !thread.isResolved && thread.comments.nodes.some( (comment) => comment.author.login === targetLogin ) );

if (unresolvedComments.length > 0) { console.error( Found ${unresolvedComments.length} unresolved comments by ${targetLogin}. ); process.exit(1); // Abnormal termination } else { console.log(All comments by ${targetLogin} are resolved.); process.exit(0); // Normal termination } }

// Command-line arguments const [owner, repo, pullRequestNumber, targetLogin] = process.argv.slice(2);

if (!owner || !repo || !pullRequestNumber || !targetLogin) { console.error( "Usage: node script.js " ); process.exit(1); }

checkUnresolvedComments( owner, repo, parseInt(pullRequestNumber, 10), targetLogin );