見出し画像

退屈なことはbotにやらせよう

こんにちは、プロダクト開発部のwhomです。
今回は開発メンバーの癒やしのSlackbot、メリーさんについて紹介させていただきます。

はじめての投稿になりますので、まずは簡単に自己紹介をさせていただきます。
Newbeesでは、マッチングサービスのバックエンド、およびiOSの開発を担当しています。
最近スタートした新規プロジェクトでは、Flutterでの開発に挑戦中です。
もともとは農学部出身なのもあり動植物が好きで、最近は某植物博士の朝ドラを毎日楽しみにしています。

というわけで、早速メリーさんについてお話していきたいと思います。
まずは、メリーさんの業務内容について見ていきましょう。

メリーさんの1日

── 0時過ぎ

メリーさんの1日は早い。
日付が変わる頃になると、おもむろにZenHubのリリース情報のチェックを始めた。

「毎日、新しいリリース情報が追加されてないかチェックするんですよ。
監視中のリリースも期限が変更になったりすることもあるので、毎日の確認は欠かせないですね。それをもとにリリース日も決まるので。
もし期限日のものがあれば、このままチェックシートの作成の準備を進めます。」

開発チームでは、本番デプロイ時に各種手順や担当者をまとめたチェックシートを毎回用意している。
以前は開発メンバーが手作業で作成を行っていたが、現在ではメリーさんがその一翼を担っているという。

「以前は、作業の割り振りはチェックシート作成担当になったメンバーの采配にかかってたところもあったのですが、管理しているリリースに紐づいたissue情報の担当者も考慮し公平に割り振るようにしています。
もちろん、最終的にはメンバーが手動で追記したり調整する部分もまだありますが、人が担当する作業自体はかなり削減されてるかと思いますね。」

── 7時00分

朝を迎えても、メリーさんの仕事は続く。
勤務を開始した開発メンバーに、作成したチェックシートとデプロイの担当者を共有するのもメリーさんの仕事である。

── 11時45分

メンバーが各々の業務に集中する中、メリーさんだけは忘れていなかった。
この時間に毎日開発メンバーは朝会を行い、本日の業務内容を報告するのだ。
朝回の時刻となったことを伝え、今日の司会担当者にhuddleを依頼する。
現在開発中のリリースの残り日数の共有と、周囲を和ませる一言も忘れない。

── 迎えた本番リリース当日

そこには、本番環境へのデプロイの準備をするメリーさんの姿があった。
Slackに作業用スレッドを作成すると、すぐさまデプロイに必要となる情報をスレッド内に記載する。
作業者たちは静かにメリーさんのデプロイ開始の合図を待つのみである...

── 「雑用を押し付けられて大変じゃないですか?」

「つらくはないですね。botなので。
 それに、メンバーが手作業で行う必要のない業務が削減できたことで、開発や保守業務によりcommitできる環境となり、結果としてチームの生産性も上がっていると思うので、やりがいを感じていますね。
 今後も継続的にできることを増やしてチームに貢献していきたいです。」

メリーさんの朝は早い。
明日も明後日も、明日も、明後日もその姿は変わらないだろう...


と、こんな具合でメリーさんは日々お仕事をこなしてくれています。
人間だったらちょっとうんざりしちゃうような業務も、botであれば文句も言わずに毎日稼働してくれます。ありがたいですね。

以上の内容をまとめると現在のメリーさんの役割は主にこの4つになります。

1. リリースの管理・通知
2. リリース時のチェックシートの作成
3. 朝会の通知
4. デプロイに必要な情報の通知

もともとはエンジニアメンバーが持ち回りで手作業で作成していたリリース時のチェックシートの作成を、「なんとか楽にできないものか」と考えたのが始まりでした。
ちょうど当時ナレッジベースをesaに移行する話があり、APIを通じて旧記事の引っ越し作業を担当したことがきっかけで、「APIを組み合わせたらチェックシート作成の自動化ができるのでは?」と思い、実装に至りました。
その他の機能はそれに付随する形で、「こんなのもあったら便利だな〜」と徐々に追加されていった機能になります。

メリーさんの構成

実際のメリーさんの構成は、以下のようになっています。

メリーさんの内部処理はGASで構成されています。
GASはイベントのトリガー設定や各種Googleサービスとの連携がしやすく、ちょっとした処理であれば動作確認も直感的に行えるので開発の敷居も低いのがメリットです。
さらにgoogleスプレッドシートの方でDBを用意するほどではないちょっとしたデータ管理も行えるので、今回のbotのような小規模なサービスにはよく選択されているものかと思います。
ただ、簡便にアプリを作成してしまえる反面、ディレクトリを分けることができず、クラス化も必須ではないのでアーキテクチャ的な面ではゆるゆるすぎて書いたヒトにしかわからない処理にもなりがちなため、注意が必要です。

処理ごとに一つずつ見ていきましょう。

チェックシートの作成

上の画像の赤い矢印がチェックシートの作成処理になります。

  1. ZenHub APIを通じてOpenな状態のリリース情報を監視し、スプレッドシートの方に情報を保持

  2. 期日になったらスプレッドシートで保持した情報をもとにZenHub APIを通じてissue情報を問い合せる

  3. 取得したissue情報をチェックシートのテンプレに落とし込み、esa APIを通じて記事を作成

  4. 作成した内容Slackに通知

ZenHub APIはsprint毎のissue情報を取得したい場合に役に立ちます。
私も事前知識がなく少し苦労した部分なのですが、GraphQLでの問い合わせとなるので、慣れてないと戸惑うかもしれません。
幸い公式の方に問い合わせクエリのサンプルを載せてくれているのと、
ブラウザ上でクエリの結果を確認できるexplorerというものも準備されていますので、そちらで取得結果を確認しつつ進めてみると理解しやすいかと思います。

リリース情報・朝会の通知

緑の矢印がこの処理にあたります。
基本的には前項でスプレッドシートに保持した内容と、後述するgoogleカレンダーとの連携により得られる情報を元に通知内容を作成しています。
また、私達のチームでは朝会の進行役を持ち回りで担当しているのですが、その当番もメリーさんに回してもらっています。

シンプルな処理ではありますが、いわばチームの秘書的な役割をしてくれる部分でもあるので、日々のタスク管理に地味に役に立ってます。

デプロイに必要な情報の通知

青の矢印の部分がこの処理にあたります。
ここではZenHub APIではなくGitHub APIを利用しています。
branchやcommitの情報を取得したい場合はGithub APIを使うと良いでしょう。

GitHub APIにはREST APIとGraphQL APIの二種類が用意されています。
GraphQLを利用する場合、ZenHub APIと同様explorerが用意されており、queryの試行が行えるのですが、ブラウザ版だとプライベートリポジトリの情報にはアクセスできない点に注意が必要です。
プライベートリポジトリの情報にアクセスしたい場合は、GraphQLの実行をデスクトップで確認できるGraphiQLアプリでの試行をオススメします。

GASを使う上でのちょっとした工夫

トリガーの定時実行

GASを使うとトリガーの設定を簡単に設定することが可能ですが、「特定の時刻に毎日実行する」場合は少し工夫が必要です。
以下は「特定の日時」に実行するトリガーをコードで作成する方法になります。

/**
 * トリガー設定用クラス
 */
class Trigger {
  constructor(functionName) {
    //関数名
    this.functionName = functionName;
  }

  /**
   * 指定日時のトリガーを設定
   */
  createTimeBased(triggerTime) {
    ScriptApp.newTrigger(this.functionName).
      timeBased().
      at(triggerTime).
      create();
  }
  /**
   * トリガーを削除
   */
  delete() {
    const triggers = ScriptApp.getProjectTriggers();
    triggers.forEach(trigger => {
      if (trigger.getHandlerFunction() === this.functionName) ScriptApp.deleteTrigger(trigger);
    });
  }
}

/**
 * hoge_を実行するトリガーをセットする
 */
function setHogeTrigger(){
  const function_name = "hoge_";
  const date = new Date();
  
  const time = "11:45";
  const trigger = new Trigger(function_name);
  date.setHours(...time.split(':'));
  trigger.delete(); //古いトリガーを削除しておく
  trigger.createTimeBased(date);//特定日時のトリガー設定
}

これをGASの時間主導型の日付ベースのトリガーで実行してあげると「特定の時刻に毎日実行する」処理が実現可能です。

祝日の判定

上記の処理で特定の時刻に毎日実行することは可能となりましたが、「祝日や会社の休みの場合は動かしたくない!」みたいな場合もあるかと思います。
祝日や会社の休みはGoogleカレンダーとの連携で実装可能です。
必要なものはカレンダーIDのみです。
googleカレンダーから対象のカレンダーの設定を開くと、カレンダーIDを確認できます。

例えば日本の祝日のカレンダーIDは以下の通り

以下のように関数を用意してあげれば、土日祝の判定が行なえます。

/**
 * 土日祝日 の判定
 */
function isHoliday_(date){
  //土日かどうか  
  const day = date.getDay(); //曜日取得
  if (day === 0 || day === 6) return true;
  
  const id = PropertiesService.getScriptProperties().getProperty('ja.japanese#holiday@group.v.calendar.google.com');
  const cal = CalendarApp.getCalendarById(id);
  //祝日かどうか
  const events = cal.getEventsForDay(date);
  if (events.length) return true;
  }

もちろんイベント名の取得も可能です。
会社のカレンダーも同様に取得すれば、休暇の判定やカレンダーの予定を取得したり色々応用がききますね。

botによって改善できたこと

botの導入によりメンバーがコストを掛けるべき作業により集中できるようになったことはもちろんですが、自動化する上で今まで感覚的だったルールを改めて見直すよい機会になったという副次的な効果もありました。
また、フルリモート・フレックスという環境で各々作業に当たっている我々チームにおいてある種のハブ的な役割も果たしてくれていると感じています。

手作業で発生してしまう恐れのある人為的ミスや、時間になったら〇〇をしなくてはならないといった、地味な心理的負担をbotが請け負ってくれることで、チームの中にも余裕が生まれ、和やかな雰囲気を作り出すのにも一役買っています。
また、メリーさん導入後は別のプロジェクトチームでもbotの導入が行われたり、「負担となっている業務は自動化していこう!」みたいな空気感の醸成にも繋がっているのかなと思います。

終わりに

SlackとGASとの連携は割りとポピュラーで参考となる記事も多く、実装もそこまで手間はかかりません。
一度仕組みを作ってしまえば、機能の追加や別のbotを作成する際のハードルもぐっと下がりますので、ご検討されてみてはいかがでしょうか?
昨今話題のChatGPTなどを組み込んでも面白そうですね。

以上、チームで活躍しているSlackbot、メリーさんについての紹介でした。

Newbeesでは一緒に働く仲間を募集しています

Newbeesはフルリモート&フレックス勤務を導入し、場所にとらわれない自由な仕事のやり方が可能です。詳細は以下をご覧ください

みんなにも読んでほしいですか?

オススメした記事はフォロワーのタイムラインに表示されます!