GitLabのメンションをGoogleAppsScriptを使ってSlackに通知したい

# はじめに
Qiita初投稿になります。
日々の仕事の中で作ったものなどを備忘録として、またシェアできたらいいなと思っています。

# きっかけ
私の会社ではGitのホスティングサービスにGitLabを使っており、またコミュニケーションツールとしてSlackを使っています。

仕事内容のやり取りはissueで管理していますが、issueのコメントで自分宛てにメンションが来た場合、メール通知はされるものの即時で見ることができず、少し不便を感じていました。

そこでお手軽にGASを使って通知できるような仕組みを作れないかググっていたところ、GitHubで同じことをしている方がいました。

[[GAS] GoogleAppsScriptでGitHubの通知をSlackのDMに投稿するようにした話](https://qiita.com/mikan3rd/items/30ac861df31756722ad5)

こちらを参考にさせていただきGitLab版のものを作ってみることにしました。

# GASの作り方やSlackのWebhookの設定
参考にさせていただいた方がすごく丁寧に解説してくださっていますので、割愛します。
[[GAS] GoogleAppsScriptでGitHubの通知をSlackのDMに投稿するようにした話](https://qiita.com/mikan3rd/items/30ac861df31756722ad5)

# GASのスクリプト
先で紹介している方のスクリプトを全面的に参考にさせていただいています。
ほとんどそのまま使用させていただきましたが、動かなかった部分やGitLab独自のPOSTデータの部分などは修正しました。
また投稿するメッセージ部も少しカスタマイズしてます。

GitlabのWebhookの内容は公式ドキュメントを参考にしました。
[Webhooks | GitLab Comment on issue](https://docs.gitlab.com/ee/user/project/integrations/webhooks.html#comment-on-issue)

参考記事で詳しく解説されていますが、基本的な流れは以下のとおりです。
1. GitLabからjsonデータを受け取る
2. リストにいるユーザ宛のメンションが含まれていればSlackユーザネームに変換
3. メッセージ内容を組み立ててSlackに送信
 
```JavaScript
var _ = Underscore.load();
var SLACK_WEBHOOK_URL = 'https://hooks.slack.com/services/xxxxxxxxxxxxxxxxxxxxx';

var USER_NAME_LIST = [
  {gitlab: '@hoge', slack: '@hoge_1'},
  {gitlab: '@fuga', slack: '@fuga_1', slackId: '@UHXXXXXX'},
];

function doPost(e) {
  var data = JSON.parse(e.postData.getDataAsString());
  notifySlack(data);
}

function notifySlack(data) {

  // コメントがない場合は通知しない
  if (!data.object_attributes.note) {
    return;
  }
  
  // ユーザネームがマッチしない場合は通知しない
  var names = data.object_attributes.note.match(/@[a-zA-Z0-9_.\-]+/g);
  if (!names) {
    return;
  }
  
  for (var i in names) {
    message = '#' + data.issue.iid + ' ' + data.issue.title + "\n";
    message += data.object_attributes.url + "\n" + data.object_attributes.note;
    callSlackWebhook(convertUserName(names[i]), message);
  }
}

function convertUserName(gitlabName) {
  var user = _.find(USER_NAME_LIST, function(user) {return user.gitlab === gitlabName});

  if (user) {
    var slackName = user.slackId || user.slack
    return slackName;
  }

  return gitlabName;
}

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;
}
```

# GitLabの設定
GASを公開したらGitLabのWebhookを有効にします。
プロジェクトの`設定 > Webhooks`から今回使うWebhookを作ります。

- `URL` -> GASのアプリケーションURLを入力
- `Trigger` -> 今回はCommentのみチェック

`Add Webhook`ボタンで保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396830/192633f8-593e-aab1-84ff-4f46d4f9739d.png)

# 完成
ここまでできたらGitLabのissueにメンションをつけてコメントしてみます。
SlackBotから通知が来たら成功です！
複数人にメンションされている場合も当てはまる全員に通知されます。
![コメント 2020-05-21 191855.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396830/e71711fd-5e5e-d8fc-ded5-e8e489e018a2.png)

# さいごに
通知内容はもう少し工夫できると思うので今後も気が向いたときにカスタマイズしてみたいです。

普段GitLabを使っていて、GitHubの記事は結構あるけどGitLabの記事はあんまりないな…と思っていましたが、GitHubにできることはGitLabでも大抵のことはできるので、ちょっと工夫すれば色々できると思います。

Webhookもかなり情報が取れるので、他にも業務に役立ちそうなものを思いついたら作ってみたいです。

# 追記（2020/5/25）
マージリクエストのコメントも拾えたら便利かなと思いましたので`notifyslack()`のメッセージ部分をマージリクエストにも対応させてみました。
他にもコミット、コードスニペットでのコメントも拾えるようですが、ウチではissueとマージリクエストのコメントが拾えれば良いのでこのかたちにしました。

```javascript
for (var i in names) {
  var message = '';
  if (data.object_attributes.noteable_type == 'Issue') {
    message += '【issue】#' + data.issue.iid + ' ' + data.issue.title + "\n";
  } else if (data.object_attributes.noteable_type == 'MergeRequest') {
    message += '【MergeRequest】!' + data.merge_request.iid + ' ' + data.merge_request.title + "\n";
  }
  message += data.object_attributes.url + "\n" + data.object_attributes.note;
  callSlackWebhook(convertUserName(names[i]), message);
}
```