https://github.com/yoshihara/sudukuri-esa という、決まった時刻に、esaの特定カテゴリの前日(=前日の ${特定カテゴリ}/yyyy/mm/dd/
カテゴリ配下)の記事のタイトルや本文をSlackに投稿するスクリプトを作りました。CircleCIのschedule機能を使っています。
(リポジトリ名については最下部の余談に)
上記リポジトリをcloneし、必要な情報を .env
に書き、CircleCIの「ADD PROJECTS」からjobをセットアップすると有効になります。後述しますが .env
にAPIトークンも入れるので、実運用はprivate リポジトリにする必要があります。。。
jobをセットアップすると、
- 毎日
.circleci/config.yml
にて指定した時間に - esaの
${ESA_TEAMNAME}
にある${ESA_ROOT_CATEGORY}/yyyy/mm/dd/
カテゴリにある記事のmarkdownを- (
yyyy/mm/dd
は実行時の前日)
- (
- slackの
${SLACK_CHANNEL_NAME}
で示されるチャンネルに投稿します
記事の間には :heavy_minus_sign:
での区切り線が入ります。esaの1記事=Slackの1発言になっています(つまり、巨大な1つの発言ではなく複数の発言を連続して行っています)
※ ${...}
は .env
ファイルで指定します
※ .env
では上記の他に esaのAPI tokenとSlackのWebhook URLが必要です(リポジトリに .env.sample
があるのでそちらをご参照ください)
動作としては↓のような感じになります。
いきなり本題に入ったので、ここからは経緯や余談について説明します。
作ることにした経緯
以前まで、会社ではテキストベースの日報を内製アプリで書いており、そのアプリは日報を保存するとslackの特定のチャンネルにその日報の中身が投稿される仕組みでした。そのチャンネルで未読を読めば、全員の日報に目が通せるという状態だったわけです。
ある時、esa.io(以下、esa)にて日報を書くことになりました。このとき、前アプリでのSlackへの投稿機能はesaでの記事投稿時の通知でまかなえると思っていました。が、esaの通知だと記事本文はSlackのattachments扱いになって途中から折り畳まれるため、全文を読むためには Read more
というリンクをSlack上でクリックする必要があります。日報は基本的にそんなに長文にならないのでSlackで折り畳まれるメリットもあまり感じられず、「以前のようになるべくクリック無しで日報を読みたい」というニーズがありました。
というわけでちゃちゃっと解決できないかな、と考えて作ったものがこちらになります。
解決方法決定
最初は別にサーバを立ててesaにWebhook登録してその別サーバでデータを作って改めてSlackに通知する、みたいなのを考えました。が、最終的にCircleCIのworkflowsでcronを使って解決することにしました。理由としては、
- まとめて読みたいだけなので通知タイミングはあまり重要ではない
- なるべくメンテするものを減らしたい
- (個人的に)使ってみたい
というあたりです。GCPとか使っても良かったかもしれない。
会社では始業前に投稿されるようにしていて、始業してからざっと前日の日報を眺めることができるようになりました。以前までとはタイミングなどが違うのですが、概ね満足してもらっている(ぽい)です。
実装の話
さっくりとRubyで実装しました。当たり前ですが、Rubyインストール済みのimageを使えばRubyインストールを考えなくていいのが楽ですね。なお、ローカルでの動作確認用に .ruby-version
もリポジトリには入っています。https://circleci.com/docs/2.0/local-cli/ あたりを使ってローカルでCircleCI環境動かすようにしておけば、このファイルも不要そう。
最初はだらーっと一つのファイルにコードを書いていたのですが、途中からまあまあ長くなってきたので lib/
配下にクラス作って整理しました。そのあたりの履歴も全部圧縮してしまった(最初はSlackでどう見えるかの実験も兼ねていたので色々べったり書いてしまっていてgitのlogを残せなかった)のですが…最初から設定を外出しにしておくの、程度によるけど低コストな場合はこういうこともあるので最初から外出ししようと思いました。
余談:リポジトリ名などの命名について
リポジトリ名は「esaの404のページとかを見るにteam=家っぽい(違ったらすみません)」→「teamの中にはたくさんの記事がある」→「このスクリプトはesaの記事を集める」→「巣作りでは」という感じでつけました。しかし今回のケースだと毎日実行されるので、つまり毎日巣作りしていることに( ⁰⊖⁰)流しのエサ…。