概要
Githubでプルリクエストが作成されたらwebhookでGoogle Apps Scriptを実装し、レビュアーをランダムアサインします。
Githubのアクセストークン作成
Githubの[Personal access tokens] (https://github.com/settings/tokens)から作成します。
- Generate new tokenから新規作成
- Full control of private repositoriesの権限を許可
スプレッドシートを準備
新規でスプレッドシートを作成します。
リポジトリ名とレビューチーム名を入力します。
No.(A列) | リポジトリ名(B列) | チーム名(C列) |
---|---|---|
1 | hoge1 | team_hoge1 |
2 | hoge2 | team_hoge2 |
3 | hoge3 | team_hoge3 |
4 | hoge4 | team_hoge4 |
5 | hoge5 | team_hoge5 |
Google Apps Scriptを実装
スプレッドシートのメニューから「ツール -> スクリプトエディタ」を開いて以下のファイルを配置する。
以下の設定値は変更する。
スクリプトファイル名 | 定数名 |
---|---|
Spreadsheet.gs | SHEET_NAME |
Github.gs | OWNER |
Github.gs | ACCESS_TOKEN |
Main.gs
/*
* プルリク作成時にレビュアーをアサインする
* @param request HttpRequest
*/
function doPost(request) {
// JSON形式に変換
var jsonData = JSON.parse(request.postData.getDataAsString());
// プルリク作成時のみ実行する
if ("opened" == jsonData["action"] && jsonData["assignees"] != null) {
// リポジトリ名
var repository = jsonData["repository"]["name"];
// プルリク番号
var number = jsonData["pull_request"]["number"];
// プルリク作成者
var sender = jsonData["pull_request"]["user"]["login"];
// レビューするチーム名を取得
var teamName = fetchTeamName_(repository);
if (teamName != null) {
reviewAssign_(repository, teamName, sender, number);
}
}
}
Spreadsheet.gs
// シート名
var SHEET_NAME = "シート名";
/*
* スプレッドシートからチーム名を返却する
* @param repository リポジトリ名
* @return チーム名
*/
function fetchTeamName_(repository) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(SHEET_NAME);
// B列を全て取得する(ヘッダー行を考慮して-1をする)
var values = sheet.getRange(2, 2, sheet.getRange("B:B").getLastRow() - 1, 3).getValues();
for(var index = 0; index < values.length; index++) {
if (repository == values[index][0]) {
// リポジトリ名が一致したらチーム名を返却する
return values[index][1];
}
}
}
Github.gs
// OWNER
var OWNER = "xxxxxxxx";
// ACCESS_TOKEN
var ACCESS_TOKEN = "xxxxxxxxxxxxxxxxxxxxxxxx";
/*
* スプレッドシートからチーム名を返却する
* @param repository リポジトリ名
* @param teamName チーム名
* @param sender プルリク作成者
* @param number プルリク番号
*/
function reviewAssign_(repository, teamName, sender, number) {
// チームIDを取得する
var teamId = fetchTeamId_(repository, teamName);
if (teamId != null) {
// プルリク作成者を除いたチームメンバーを取得
var members = fetchReviewAssignMembers_(teamId, sender);
// レビュアーをランダムで選抜
var reviewer = members[Math.floor(Math.random() * members.length)];
reviewAssignRegistration_(repository, number, reviewer);
}
}
/*
* GithubAPIを作成する
* @param url URL
* @return GithubAPI
*/
function createGithubAPI_(url, repository) {
url = "https://api.github.com" + url;
url = url.replace(":owner",OWNER);
url = url.replace(":org",OWNER);
url = url.replace(":repo",repository);
return url;
}
/*
* リクエストパラメータを作成する
* @param method method
* @return リクエストパラメーター
*/
function params_(method) {
return params_(method,"");
}
/*
* リクエストパラメータを作成する
* @param method method
* @param payload payload
* @return リクエストパラメーター
*/
function params_(method, payload) {
var params =
{
"method": method,
"Content-Type": "application/json",
"muteHttpExceptions": true,
"payload": payload,
"headers": {
"Authorization":" token " + ACCESS_TOKEN
}
};
return params;
}
/*
* GithubAPIにアクセスしてチームIDを返却する
* @param repository リポジトリ名
* @param teamName チーム名
* @return チームID
*/
function fetchTeamId_(repository, teamName) {
// https://developer.github.com/v3/orgs/teams/#list-teams
var url = createGithubAPI_("/orgs/:org/teams", repository);
var params = params_("GET");
var response = JSON.parse(UrlFetchApp.fetch(url, params));
for(var index = 0; index < response.length; index++) {
if (response[index]["name"] == teamName) {
return response[index]["id"];
}
}
}
/*
* チームメンバーを取得してプルリク作成者を除外した一覧を返却する
* @param repository リポジトリ名
* @param teamName チーム名
* @param sender プルリク作成者
* @param number プルリク番号
* @return プルリク作成者以外のメンバー一覧
*/
function fetchReviewAssignMembers_(teamId, sender) {
// https://developer.github.com/v3/orgs/teams/#list-team-members
var url = createGithubAPI_("/teams/:id/members", "");
url = url.replace(":id",teamId);
var params = params_("GET");
var response = JSON.parse(UrlFetchApp.fetch(url, params));
var members = [];
for(var index = 0; index < response.length; index++) {
// プルリク作成者はレビュアーから除外
if (sender != response[index]["login"]) {
members[index] = response[index]["login"];
}
}
return members;
}
/*
* プルリクにレビュアーをアサインする
* @param repository リポジトリ名
* @param number プルリク番号
* @param reviewer レビュアー
*/
function reviewAssignRegistration_(repository, number, reviewer) {
// https://developer.github.com/v3/issues/assignees/#add-assignees-to-an-issue
var url = createGithubAPI_("/repos/:owner/:repo/issues/:number/assignees", repository);
url = url.replace(":number",number);
var payload = JSON.stringify({
"assignees" : reviewer
});
var params = params_("POST", payload);
var response = JSON.parse(UrlFetchApp.fetch(url, params));
}
スプレッドシートのAPIを公開
スクリプトエディタのメニューバーから公開できます。
- 公開 > ウェブアプリケーションとして公開
- プロジェクト バージョンを入力(例:v.1.0)
- 次のユーザーとしてアプリケーションを実行は自分を選択
- アプリケーションにアクセスできるユーザーは全員を選択
- 現在のウェブ アプリケーションの URLをGithubのWebhooksに設定
GithubのWebhooksを設定
Githubで自動レビュアーアサインを設定したいリポジトリのSettingsを開きます。
Webhooksでadd webhookを追加します。