29
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[GAS] GoogleAppsScriptでGitHubの通知をSlackのDMに投稿するようにした話

Last updated at Posted at 2018-04-28

:star: 追記

公式でほぼ同じ機能が使えるようになったので、こちらの方法がオススメです
"Scheduled reminders" でGitHub上のやり取りをSlackに通知させよう!

:star: Hello!

**株式会社Patheeのフロントエンド&サーバーサイドエンジニアの@mikan3rdです。
普段は自社サービスの
Pathee**やCMSの開発を担当しています。

2018年4月より新サービス**Patheeパートナーツール**をリリースしたことがきっかけで
社内のGit管理をBitBucketからGitHubに移行しました!

これまでBitBucketのwebhookを使ってPullRequestの通知を行っていたのですが、
GitHubへの移行に伴い、この通知も改善しようということになりました。

:star: 目標

今回は、前々から触ってみようと思っていたGoogleAppsScriptを使って
GitHubで@mentionのついたコメントがあった時、
それぞれのSlackのダイレクトメッセージに送るようにしたいと思います。

スクリーンショット 2018-04-28 19.20.59.png

:star: なんで Google Apps Script?

  • 無料だから
  • サーバーを立てなくていいから
  • 社内でGoogleDriveをよく利用しているから(ユーザーが増えたりした時に管理しやすい)
  • JavaScriptで書けると思っていたから(ちょっと違った)

:star: 手順

  • GoogleDriveからGASを追加
  • GASでアプリケーションのURLを発行
  • GitHubでWebhookの設定をする
  • GASでpostリクエストを受け取る
  • Slackでwebhookの設定をする
  • GASからSlackに通知する
  • GitHubのユーザーネームをSlackのユーザーネームに変換する
  • GitHubのコメントをSlackに通知する

:pencil: GoogleDriveからGASを追加

  • GoogleAppsScriptを初めて使う場合、アプリの追加が必要です
  • 新規 => その他 => アプリを追加 を選択
スクリーンショット 2018-04-27 18.18.57.png

drive.google.com_drive_u_0_my-drive(Laptop with MDPI screen).png

  • 接続を押すと追加されます

:pencil: GASでアプリケーションのURLを発行

  • 新規 => その他 に Google Apps Script が追加されています
スクリーンショット 2018-04-27 18.44.23.png
  • 公開 => webアプリケーションとして導入 を選択

script.google.com_a_pathee.com_d_10D49GvMrFM-LVnxaXgHf7UFO_bmWAZmyDizf_BrtZcuA5qEJp8QcIn8V_edit_usp=drive_web&folder=0AEb1iLa_cltmUk9PVA&splash=yes(Laptop with MDPI screen).png

  • 「次のユーザーとしてアプリケーションを実行」を選択
  • 「アプリケーションにアクセスできるユーザー」で「全員(匿名ユーザーを含む)」を選択

script.google.com_a_pathee.com_d_10D49GvMrFM-LVnxaXgHf7UFO_bmWAZmyDizf_BrtZcuA5qEJp8QcIn8V_edit_usp=drive_web&folder=0AEb1iLa_cltmUk9PVA&splash=yes(Laptop with MDPI screen) (1).png

  • 「現在のウェブアプリケーションのURL」をコピーしておきます

script.google.com_a_pathee.com_d_10D49GvMrFM-LVnxaXgHf7UFO_bmWAZmyDizf_BrtZcuA5qEJp8QcIn8V_edit_usp=drive_web&folder=0AEb1iLa_cltmUk9PVA&splash=yes(Laptop with MDPI screen) (2).png

:pencil: GitHubでWebhookの設定をする

  • 権限が「Owner」の場合「Setttings」が表示されるので選択します
  • Webhooksの右上のAdd webhook を選択します

github.com_organizations_pathee_settings_hooks_new(Laptop with MDPI screen).png

  • Payload URLに先ほどコピーしたGASのURLを貼り付けます
  • Content typeをapplication/jsonに変更します
  • Secretは今回は不要です
  • 「Send me everything」 または 「Let me select individual events」で必要なイベントを選択します
  • 「Add webhook」でGitHubのwebhookの設定は完了です

:pencil: GASでpostリクエストを受け取る

  • GitHubからはmethod=POSTでリクエストが送られてきます
  • 参考: GitHub Webhooks Guide
  • GASではdoPostと記述するとpostリクエストを受け取ります
  • JSON.parse(e.postData.getDataAsString())とすることで受けとったJSONを辞書型objectに変換します
  • console.log()Google Cloud Platformのログに出力されます

// POSTリクエストを受け取る
function doPost(e) {
  var data = JSON.parse(e.postData.getDataAsString());

  // Google Cloud Platform のログで確認できる
  // https://console.cloud.google.com/logs
  console.log(data);
}
  • 試しにGitHub上でコメントなどをしてみると、ログが確認できるはずです
スクリーンショット 2018-04-27 20.22.21.png

:pencil: Slackでwebhookの設定をする

  • Slackのアプリ追加ページでincoming-webhooksを検索し、選択します。
  • https://slack.com/apps

IncomingWebhooks

  • デフォルトで通知が送られるチャンネルを選択して追加します

corp-pathee.slack.com_apps_new_A0F7XDUAZ-incoming-webhooks(Laptop with MDPI screen).png

  • 名前やアイコンは自由に設定してください
  • Webhook URL をコピーしておきます

corp-pathee.slack.com_services_BAC351L5U(Laptop with MDPI screen).png

:pencil: GASからSlackに通知する

  • slackのwebhookにリクエストを送るfunctionを作ります
  • link_names: 1することで、text内のユーザーネームをリンク化できます
  • channel: '@username'で、その人のslackbotにメッセージが届きます
  • 新しいユーザーなど、一部の場合は@usernameだと認識されない場合があるようです
  • そのユーザーについては@userIDにするとちゃんと届きます
  • 参考:Slack APIでユーザー宛のメンションができなくなったので対策した

var SLACK_WEBHOOK_URL = 'webhookURLを貼り付ける';

// Slackのwebhookにリクエストを送る
function callSlackWebhook() {  
  var params = {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify({
      channel: '@mikan3rd', // 自分のslackのユーザーネームに変えてください
      text:'テストおおおおおおおおおおおおおおお',
      link_names: 1,
    })
  };
  var response = UrlFetchApp.fetch(SLACK_WEBHOOK_URL, params);
  console.log("response:", response);
  return response;
}

  • GASの上部で実行する関数を選択し、▶︎ボタンを押すと関数が実行され、Slackにメッセージが届くはずです
スクリーンショット 2018-04-27 20.54.55.png

:pencil: GitHubのユーザーネームをSlackのユーザーネームに変換する

  • GitHubのユーザー名をSlackのユーザー名に変換する必要があります
  • 次のようにgithubとslackのユーザー名の辞書型objectを用意しましょう
  • @usernameでは通知できないユーザーは@userIDも記述します

var USER_NAME_LIST = [
  {github: '@mikan3rd', slack: '@hiroki-ota'},
  {github: '@hoge',     slack: '@fuga',       slackId: '@U3VSP6T0C'}
];
  • また、GASにはJavascriptのfindメソッドがないため、様々な関数が使えるようになるUnderscoreというライブラリを追加します
  • ライブラリはリソース => ライブラリ から追加できます
  • 「ライブラリを追加」にプロジェクトキーM3i7wmUA_5n0NSEaa6NnNqOBao7QLBR4jを入力して追加を押すとライブラリが使えるようになります
  • 次のように書くことで、_をUnderScoreとして使うことができます

// ライブラリUndserScoreを使えるようにする
var _ = Underscore.load();
  • GitHubから送られてきたデータにコメントがある場合、コメント内の@mentionをslackのユーザーネームに置き換える処理を実装します
  • 先ほどのUSER_NAME_LISTに一致するものがあった場合、userListに追加するようにしました

// ダイレクトメッセージを送るusernameを格納する通知リスト
var userList = [];

// GitHubのコメントをslackに通知する関数
function notifyslack(data) {
  
  // commentがない場合は通知しない
  if (!data.comment) {
    return;
  }

  // コメント内の@mentionをslackのユーザーネームに置き換える
  var comment = data.comment.body.replace(/@[a-zA-Z0-9_\-]+/g, convertAndAddUserName);
  console.log(comment);

}


// GitHubのユーザーネームをSlackのユーザーネームに変換して送信先に追加する関数
function convertAndAddUserName(githubName) {

  // UnderscoreのfindメソッドでUSER_NAME_LISTに対応するものがあるか探す
  var user = _.find(USER_NAME_LIST, function(user) {return user.github === githubName});

  if (user) {

    // slackIDが定義されている場合は優先して使う
    var slackName = user.slackId || user.slack

    // slackの通知リストに追加
    userList.push(slackName);

    // <@username>とするとslackでリンク化される
    return '<' + slackName + '>';
  }

  return githubName;
}

:pencil: GitHubのコメントをSlackに通知する

  • これまでの関数をつなげれば、GithubのリクエストをGASで受け取り、ユーザーネームを変換して、slackに通知する機能は完成です
// ライブラリUndserScoreを使えるようにする
var _ = Underscore.load();

var SLACK_WEBHOOK_URL = 'webhookURLを貼り付ける';

var USER_NAME_LIST = [
  {github: '@mikan3rd', slack: '@hiroki-ota'},
  {github: '@hoge',     slack: '@fuga',       slackId: '@U3VSP6T0C'}
];

// ダイレクトメッセージを送るusernameを格納する通知リスト
var userList = [];


// POSTリクエストを受け取る
function doPost(e) {
  var data = JSON.parse(e.postData.getDataAsString());
  notifyslack(data);
}


// GitHubのコメントをslackに通知する関数
function notifyslack(data) {

  // commentがない場合は通知しない
  if (!data.comment) {
    return;
  }

  // コメント内の@mentionをslackのユーザーネームに置き換える
  var comment = data.comment.body.replace(/@[a-zA-Z0-9_\-]+/g, convertAndAddUserName);
  
  // userListのユーザーそれぞれにダイレクトメッセージを送る
  for each(var user in userList) {
    callSlackWebhook(user, comment);
  } 
}


// GitHubのユーザーネームをSlackのユーザーネームに変換して送信先に追加する関数
function convertAndAddUserName(githubName) {

  // UnderscoreのfindメソッドでUSER_NAME_LISTに対応するものがあるか探す
  var user = _.find(USER_NAME_LIST, function(user) {return user.github === githubName});

  if (user) {

    // slackIDが定義されている場合は優先して使う
    var slackName = user.slackId || user.slack

    // slackの通知リストに追加
    userList.push(slackName);

    // <@username>とするとslackでリンク化される
    return '<' + slackName + '>';
  }

  return githubName;
}


// Slackのwebhookにリクエストを送る
function callSlackWebhook(user, comment) {  
  var params = {
    method: 'post',
    contentType: 'application/json',
    payload: JSON.stringify({
      channel: user,
      text: comment,
      link_names: 1,
    })
  };
  var response = UrlFetchApp.fetch(SLACK_WEBHOOK_URL, params);
  console.log("response:", response);
  return response;
}

:star: おまけ

  • GitHubから送られてくるactionにはassigned/review_request/approve/mergeなど様々なものがあるので、さらにカスタマイズしていくとこんな感じの賑やかな通知ができます
スクリーンショット 2018-04-28 19.15.27.png

:star: 感想

今回、初めてGASを触ってみたのですが、普段のフロントエンドの開発ではES6で書いているので、

  • constが使えない
  • 文字出力がテンプレートリテラルでできない
  • アロー関数が使えない

のは違和感がありました。また、

  • Javascriptの基本的なメソッド(includesとか)で使えないものがある
  • for..inでObjectの繰り返し処理できない
  • 正規表現の先読み/後読みが対応していない
  • リクエストのheaderが取得できない
  • console.log()がその場で確認できない(Logger.log()を使う)

など、普通のJavaScriptでできることができない部分もありました。

GASはあくまで"JavaScriptっぽく"書ける、ということだったんですね。

それでも、やりたいことは一通り実装することができたので、
Googleスプレッドシートと連携したスクリプトを書きたい時や、
「サーバーレスでちょっとした処理を作りたい!」という時には良いと思います!

:star: 次回

GASでGitHubのAPIを叩いてレビュアーをランダムで選ぶスクリプトを作ったので紹介しようと思います。

29
26
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
26

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?