GitHub の Review のコメントが取得できたのでスプレッドシートに出力する

こおりやまです

前回、こちらで GitHubのReviewコメントを抽出するクエリーを作成したので、そのクエリーを利用してスプレッドシートにレビュー、コメント情報を出力してみました。

GitHub GraphQL API を利用してReview のコメントを抽出してみた
こおりやまです 以前、こちらのブログでPull requests のコメント取得しましたが、Reviewコメントが取得できていなくクエリを再検討しました。 GitHub GraphQL API を利用してPull requests のコメントを抽出してみたこおりやまです 以前、こちらのブログでGitHubGraphQL APIをさわってどのような情報を取得できるのか確認していたのですが、Pull requests のコメント取得が必要になりGoogleAppsScript(GAS)から呼び出しスプレッドシートに出力してみました。 GitHub GraphQL API をさわってみ…

コードはこんな感じ。細かい部分は過去のブログにて確認お願いします。

/***********************************************
 * 設定情報
 ***********************************************/
var ACCESS_TOKEN = "トークン情報";
var ENDPOINT = "https://api.github.com/graphql";
var REPOSITORY_NAME = "リポジトリ名";
var REPOSITORY_OWNER = "オーナー情報";
var LABELS = "ラベル";

/***********************************************
 * GitHubからPRの一覧取得
***********************************************/
function getGitHubPullRequestList(endCursor) {

  // 次ページの検索情報
  var pageCursor = "";
  if(endCursor != ""){
    // 次ページを検索させるための情報
    pageCursor = ",after: \"" + endCursor + "\""
  }


  // 作成日降順、ラベルを特定
//          pullRequests(first: 50' + pageCursor + ', labels: "' + LABELS + '", orderBy: {field: CREATED_AT, direction: DESC}) {\
  var query = '\
    {\
      repository(name: "' + REPOSITORY_NAME + '", owner: "' + REPOSITORY_OWNER + '") {\
          pullRequests(first: 50' + pageCursor + ', labels: "' + LABELS + '", orderBy: {field: CREATED_AT, direction: DESC}) {\
          edges {\
            node {\
              url\
              title\
              createdAt\
              updatedAt\
              number\
              author {\
                login\
              }\
            }\
          }\
          pageInfo {\
            hasNextPage\
            endCursor\
          }\
        }\
      }\
    }';
  
 
  var options = {
    'method' : 'post',
    'contentType' : 'application/json',
    'headers' : {
      'Authorization' : 'Bearer ' +  ACCESS_TOKEN
     },
    'payload' : JSON.stringify({query:query})
  };

  // fetch 情報を取得
  var response = UrlFetchApp.fetch(ENDPOINT, options); 

  // Json形式で返却
  return JSON.parse(response.getContentText());;
}


/***********************************************
 * GitHubからPRの一覧取得
***********************************************/
function getGitHubPullRequest(number) {

  // 対象の1PR情報取得
  var query = '\
    {\
      repository(name: "' + REPOSITORY_NAME + '", owner: "' + REPOSITORY_OWNER + '") {\
        pullRequest(number: ' + number + ') {\
          url\
          title\
          closed\
          createdAt\
          author {\
            login\
          }\
          reviews(first: 25) {\
            edges {\
              node {\
                state\
                bodyText\
                author {\
                  login\
                }\
                comments(first: 25) {\
                  edges {\
                    node {\
                      bodyText\
                      author {\
                        login\
                      }\
                      originalCommit {\
                        abbreviatedOid\
                        authoredDate\
                      }\
                    }\
                  }\
                }\
              }\
            }\
          }\
          comments(last: 25) {\
            nodes {\
              bodyText\
            }\
          }\
        }\
      }\
    }';
 
  var options = {
    'method' : 'post',
    'contentType' : 'application/json',
    'headers' : {
      'Authorization' : 'Bearer ' +  ACCESS_TOKEN
     },
    'payload' : JSON.stringify({query:query})
  };

  // fetch 情報を取得
  var response = UrlFetchApp.fetch(ENDPOINT, options); 

  // Json形式で返却
  return JSON.parse(response.getContentText());;
}



/***********************************************
 * main
 * GitHubからPRの一覧取得
***********************************************/
function main(){
  Logger.log("開始");
  
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('シート1');  
  var iRow = 2;
  var nextPageCursor = "";

  do{
    var allDocuments = getGitHubPullRequestList(nextPageCursor);
    var edges = allDocuments.data.repository.pullRequests.edges;  
    var changeRow = 0;
    var values = sheet.getRange("A:A").getValues();

    edges.forEach(function(edge){
      // Logger.log(edge);
      
      // 該当情報が存在する?
      iRow = findValueRowNo(values, edge.node.number);
      if (iRow<1){
        // 存在しないので新規行作成
        iRow = sheet.getLastRow()+1;
        Logger.log("New:" + edge.node.number + ' Row:' + iRow);
      }
      sheet.getRange(iRow, 1, 1, 6).setValues([[edge.node.number,
                                                 edge.node.title,
                                                 edge.node.url,
                                                 edge.node.author.login,
                                                 edge.node.createdAt,
                                                 edge.node.updatedAt]]);


      var pullRequest = getGitHubPullRequest(edge.node.number);
      var pullRequestReviewEdges = pullRequest.data.repository.pullRequest.reviews.edges;
      
      // sheet.getRange(iRow, 6).setValue(JSON.stringify(pullRequestReviewEdges));
      //前回の抽出結果とコメント数が異なる場合
      if (sheet.getRange(iRow, 1).getValue() == "" ||
          sheet.getRange(iRow, 7).getValue() != pullRequestReviewEdges.length){
        changeRow++;

        //レビュー出力
        var iCol = 8;
        var reviewNo = 1;
        var reviewTitle = "";
        // レビュー数
        sheet.getRange(iRow, 7).setValue(pullRequestReviewEdges.length);
        pullRequestReviewEdges.forEach(function(v){
            if(v.node.bodyText!=""){
              reviewTitle = '[review' + reviewNo + ']\n';
              sheet.getRange(iRow, iCol).setValue(reviewTitle+'@'+v.node.author.login + '\n' + v.node.bodyText.replace(/\s+(\r?\n)+/g,"\n"));
              iCol++;
            }else{
              reviewTitle = '[review' + reviewNo + ']\n';
            }
            // コメント部分出力
            v.node.comments.edges.forEach(function(c){
              sheet.getRange(iRow, iCol).setValue(reviewTitle + '[comment]\n'+'@'+c.node.author.login + '\n' + c.node.bodyText.replace(/\s+(\r?\n)+/g,"\n"));
              iCol++;
            });
            reviewNo++;
        });
      }
    });

     // 次ページがあるか、最終行のカーソル情報を取得
    nextPageCursor = allDocuments.data.repository.pullRequests.pageInfo.endCursor;
    var hasNextPage = allDocuments.data.repository.pullRequests.pageInfo.hasNextPage;
    Logger.log("新規/更新:" + (changeRow) + ' endCursor:' + nextPageCursor + ' hasNextPage:' + hasNextPage);
    // hasNextPage=false;

  // 次ページがなくなるまでループ
  }while(hasNextPage == true)
  
  Logger.log("終了");
}
// APIだと遅いので検索する
function findValueRowNo(values, value) {
  for (var i in values) {    
    if (values[i][0] == value) {
      return parseInt(i)+1;
    }
  }
  return -1;
}

処理とては、対象のPRの一覧を取得し、IDを利用して詳細情報を参照してレビュー、コメント情報をスプレッドシートへ出力しています。

結果は以下のレイアウトとし、コメント内容にレビュー、コメント情報を追記していくこととします。

実行結果はこんな感じ、もう少し情報を追加したいかと思いますが、とりあえず欲しい情報は抽出できたのでよしとします。

ただ、スプレッドシートに出力するため、API呼び出し回数が多くなり速度面がきになりますが、別途時間ある時に改善してみようかと思います。

ではでは