Ponz Dev Log

開発のことから合間に読んだ本の感想まで、マイルドに書きます

Trello APIとSlackで今週の頑張りをめちゃくちゃ褒めるボットを作る

モチベーション

仕事のタスク管理って基本めんどくさいですよね。僕はTrelloで仕事(+一部の業務外のToDo)のタスクを管理しているんですが、Trelloは期限やチェックリスト, コメント残しにカレンダーと機能が豊富でとても便利です。 ただ、年末の自分の評価シートを書いている時に、この案件に入ってから何かしら自分の作業効率って上がっているのかしらとふと思いました。その時は結局分からずじまいで悲しくなったので、できれば定量的に(週ごとに捌いたタスク数とか、修正にかかった時間とか)改善が把握できるBotが欲しいと思いつきました。あわよくば、モチベーションもあげたい。。。じゃあ今週頑張ったかを褒めちぎるBotを作ろう!!

実現したいこと

今回実現したいことを列挙するとこんな感じです。シンプルに2つだけにします。

  • 今週の完了したタスク数, タスク名をTrelloの完了リストから取得する
  • 完了済みタスク数と褒め言葉をSlackで自分宛に投げる

自分のスケジュール(毎週の進捗ミーティングやら検証環境へのリリースタイミング)や面倒くさがりの性格を考えて、自分でSlackコマンドを打つんじゃなくてスケジュール起動でSlack Botから通知を飛ばすようにしました。

Botの構成

構成図は割とシンプルになりました。

f:id:accelerk:20181231004654p:plain
Botの構成図

上の構成図の技術要素も並べるとこんな感じ。 極力労力をかけず/コードを書かずにサービスを組み合わせて実現させることを第一に実装します。

  • Node.js
    • スピード重視で慣れている言語で作ります。TypeScriptは使いません。
  • Trello API
    • 公式から出ているAPIでタスクを取得します。
  • Slack
    • 業務でも使ってるコミュニケーションツール。特定のタイミングで頑張った成果と褒め言葉を自分に投げる先です。
    • 一番手軽なWebhook経由でメッセージを投稿させます。
  • IBM Cloud Functions
    • こちらもスピード重視でCloudFoundryやIBM Kubernetes Serviceよりも手軽に上記の要素を実現できる方法として採用。
    • Slackにメッセージを飛ばすパッケージが事前に用意されていたので、
  • Serverless Framework
    • 関数のデプロイや依存するリソース管理に時間をかけたくないので、宣言的にリソース定義とデプロイするためのツールとして使用します。
    • IBM Cloud Functionsと連携する方法は自分の記事参照。 qiita.com
  • Continuous Delivery @IBM Cloud
    • TrelloやSlackのURL/Tokenを扱う以上、これらの情報をいちいち環境変数に指定してデプロイするのは面倒。
    • GitHubソースコードがコミットされることを検知してCI/CDパイプラインからリリースをかけます。
    • スケジュール起動や事前にIBM Cloud側で用意されているSlackパッケージはServerless Frameworkで定義してデプロイします。

できたもの

金曜22時になったら頑張りを通知してくれるようになりました!!

f:id:accelerk:20181231005204p:plain
Botから成果と褒め言葉が送られる

ソースコードはこちらに置いていますので、ご参考まで。 github.com

実装のポイント

実際にコードを書いたのは、Trelloから完了済みカードを取ってきて整形するところだけです。Trelloの特定のリストからカードを一式取ってくるだけなので、難しくはありません。以下実際のコードです。

("use strict");

const axios = require("axios");
const qs = require("querystring");

/**
 * Trelloのカードを操作する.
 */
class TrelloClient {
  constructor(params) {
    this.baseUrl = params.TRELLO_URL || "https://api.trello.com/1";
    this.apiKey = params.TRELLO_API_KEY || "API KEY";
    this.token = params.TRELLO_TOKEN || "TOKEN";
    this.listId = params.TRELLO_LIST || "LIST_ID";
  }

  /**
   * 完了済みタスクの一覧を取得する.
   * @param {String} listId 完了リストのID
   * @returns {Promise} 完了済みタスクのJSON配列
   */
  getCompletedTasks() {
    const reqParams = qs.stringify({
      key: this.apiKey,
      token: this.token,
      fields: "id,name,labels"
    });
    const TRELLO_URL_GET_COMPLETED_TASKS = `${this.baseUrl}/lists/${
      this.listId
    }/cards?${reqParams}`;
    return axios.get(TRELLO_URL_GET_COMPLETED_TASKS).then(response => {
      return response.data || {};
    });
  }
}

module.exports = TrelloClient;

params オブジェクトの各パラメータは serverless.yml に定義した値が渡ってきます。後は呼び元のメインの関数内でこのクラスをnewして使えば終わりです。全体で100行ちょっとしかないので軽いですね。

TrelloのAPIを叩く部分しか書か必要がない理由は、Slackへメッセージを投稿する部分は事前定義済みSlackパッケージを使うからです。atachmentsを使ったカラフルな凝ったメッセージ使えないですが、文字列連結すればいける範囲だったので無理せずそのまま使いました。

ハマりポイント

ContinuousDeliveryでServerless Frameworkを使ったデプロイするときは、CDのバージョンに注意

NPMの環境を指定してもNode.jsはv0.10系です。IBM SDKだとv6系しか入ってないのでなるべくv8系以上にしたいところ。v0.10系だと serverless パッケージがpostinstall時にでこけます。以下の記事を参考にしてNVMを使えば良さそうとのことだったので、v8系をNVM経由でインストールして解決。 developer.ibm.com

Serverless Frameworkからデプロイするときに認証エラーになる

Serverless Frameworkは .wskprops ファイルを参照してIBM Cloud Functionsにアクセスするようなのですが、どうも ibmcloud login でログインしても上手く生成されないようです。以下のようにして .wskprops を生成したらデプロイできるようになりました。

Deploy shellscrpit to work with IBM Cloud Function ...


これで来年の改善具合が見える化できるので楽しみです :)