GAS でプルリク毎に変更されたファイル一覧をスプレッドシートに保存する

# やりたいこと

不具合分析をするにあたり、バグが混入していたファイル（不具合修正で修正されたファイル）を取得し、バグが入り込みやすファイルを把握したい

具体的には、GitHub で不具合修正に使ったブランチからのプルリクを参照して、変更されているファイルの一覧をスプレッドシードに保存したい

ということで、GAS（Google Apps Script）で GitHub GraphQL API を叩いて上記の内容を実装してみました


# スプレッドシート

**ブランチ名取得用スプレッドシート**
不具合修正に使用したブランチ名は予めわかっていて、スプレッドシートで下記のように管理されていることとします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/871926/3fc240bd-f168-66c6-bb5e-036062be33d7.png)
ブランチ名に「bug」と入れるようにしているので、いちいちスプレッドシートで把握する必要はなかったかも

**出力用スプレッドシート**
出力用には、「ブランチ名」「変更されたファイルパス」「変更日時（Close された日時）」が保存できるようにしておきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/871926/44372c39-4fb4-5ed8-7939-3aebe8b19c30.png)


# 前準備
GitHub API にアクセスするためのトークンを、GAS のパラメータ保存しておきます

* GitHub の [Personal Access Token](https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token) を取得する
* GAS のプロジェクトを作成する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/871926/d597bc73-1c18-8698-09de-498743609768.png)

* 適当に名前を付けて、取得したトークンを保存する
  * ファイル　>　プロジェクトのプロパティ　>　スクリプトのプロパティ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/871926/4dcf18e1-48bf-65fb-f61b-9aeb4b1f8ffe.png)


# GAS
プログラムの流れは以下のような感じです

* 不具合修正用のブランチ名を取得
* 出力用スプレッドシートと比較して、未取得のブランチ名を把握
* GitHub GraphQL API を叩いて変更ファイル一覧を取得
* スプレッドシートに出力

```javascript
function get_fixed_file_from_GitHub(){
  // BugチケットID を取得
  const bugListSsUrl = "https://docs.google.com/spreadsheets/d/**********";
  const sh = SpreadsheetApp.openByUrl(bugListSsUrl).getSheetByName('シート1');
  const lastRow = sh.getLastRow()
  const bugBranches = sh.getRange(2, 1, lastRow - 1).getValues();
  
  // 出力先スプレッドシート
  const outputSsUrl = "https://docs.google.com/spreadsheets/d/++++++++++";
  const sh2 = SpreadsheetApp.openByUrl(outputSsUrl).getSheetByName('シート1');
  let lastRow2 = sh2.getLastRow()
  const storedBranches = sh2.getRange(2, 1, lastRow2).getValues();
    
  for ( const bugBranche of bugBranches ){
    // まだ登録されていないバグなら以下を実行
    if( !storedBranches.some( id => id[0] === bugBranche[0] ) ){

　　   // プルリクから修正したファイルを取得
      let fixedFiles = get_fixed_files( bugBranche[0] );
    
      // スプレッドシートに保存
      for (const fixedFile of fixedFiles.files ) {
        const outputArray = [bugBranche, fixedFile, fixedFiles.closedAt]
        lastRow2 = lastRow2 + 1;
        sh2.getRange(lastRow2, 1, 1, outputArray.length).setValues([outputArray]);
      }
    }
  }
}

// GitHubのプルリクから、修正されたファイル一覧を取得する
function get_fixed_files(bugBranch) {
  const accessToken = PropertiesService.getScriptProperties().getProperty("GITHUB_TOKEN");
  const endpoint = "https://api.github.com/graphql";
  
  const query = `
  {
    organization(login: "**********"){
      repository(name: "+++++++++"){
        pullRequests(states: [MERGED], headRefName: "${bugBranch}", last: 20){
          nodes{
            closedAt
            files(first: 20){
              nodes{
                path
              }
            }
          }
        }
      }
    }
  }
  `;
  
  const option = {
    method: "post",
    contentType: "application/json",
    headers: {
    Authorization: `bearer ${accessToken}`,
    },
    payload: JSON.stringify({ query: query }),
  };

  const response = UrlFetchApp.fetch(endpoint, option);
  const json = JSON.parse(response.getContentText());
  const nodes = json.data.organization.repository.pullRequests.nodes[0].files.nodes;
  const closedAt = json.data.organization.repository.pullRequests.nodes[0].closedAt;
  const files = [];

  for (const node of nodes ) {
    files.push(node.path);
  }
  
  return {files: files, closedAt: closedAt};
}
```

# さいごに

上記の GAS を定期実行させることで、修正されたファイル一覧が日々保存されるようになりました。

あとは、この一覧からファイル毎やディレクトリ毎などにいい感じに自動集計させてみたいなと思っていたりします。