HubotをLingr上で使ってみた

HubotをREMPチームで使っているLingrで使ってみたのでその際のメモ。

Hubotはgithub社が作ったnode.jsで実装されたbotフレームワークでチャットサービス上で稼働させるbotを稼働させることができます。
特定のチャットサービスに依存しないので、IRCGoogle Talk, Skypeや今回試してみたLingrでも稼働させることができます。*1

メリットとしては、botに作業をさせる、あるいはチャット上の特定のワードに反応する処理をcoffee scriptあるいはJavaScriptを使って実装することでます。また、その時の実装にNode.jsの豊富なライブラリ(npm)を利用できます。

Hubotの導入

Hubotを稼働させるには、

  • Node.js
  • coffee script
  • Redis

が必要になります。既に上記一式が稼働できるものとして...

$ npm install -g hubot
$ npm install -g coffee-script
$ hubot --create remp_hubot
Creating a hubot install atg remp_hubot
(略)

とすることで、hubotを稼働させるための一式が --create オプションで指定したディレクトリ以下に作成されます。ディレクトリの中身は以下の様な具合になっています。

$ cd remp_hubot
$ ll
total 48
-rw-r--r--   1 hideack  staff    36  4 22 09:05 Procfile
-rw-r--r--   1 hideack  staff  5903  4 22 09:05 README.md
drwxr-xr-x   4 hideack  staff   136  4 22 09:05 bin
-rw-r--r--   1 hideack  staff     3  4 22 09:05 external-scripts.json
-rw-r--r--   1 hideack  staff    40  4 22 09:05 hubot-scripts.json
-rw-r--r--   1 hideack  staff   609  4 22 09:05 package.json
drwxr-xr-x  15 hideack  staff   510  4 22 09:05 scripts

試しにローカルで稼働させてみます。先ほどhubotコマンドで作成したディレクトリ配下で、

$ bin/hubot

と実行するとチャットサービスを介さず直にHubotを操作できます。お約束のping-pongをした様子。

LingrとHubotを接続する

Hubotは稼働させることができましたが、まだチャットサービスで接続できていないので次にLingrと接続します。hubot-lingrというAdapterが既にnpmに登録されていますので、これを活用します。

先ほどのhubotコマンドで作成したhubotディレクトリの配下で、

$ npm install hubot-lingr --save

でインストールをすることができます。これで接続に必要なHubot Adapterが準備されます。

次にLingrに接続するためにLingr botの設定をLingrで行います。Lingrの開発者向けメニューのbot作成画面で必要事項を入力させます。

hubot-lingrを利用してHubotとLingrを接続する場合、Lingr上のチャットルームでの発言をHubot側に通知させるためにHTTPのCallback URLを指定する必要があります。このAdapterを入れてHubotを起動した場合、/hubot/lingrというHTTPパスがLingrからのコールバックを受けられる様になります。

この設定が完了するとbotのID及び、Secretキーが発行されるので、これを以下の2つの様な環境名で定義します。

この設定が行えた状況でHubotを起動します。次はLingrと接続を行うので -a オプションでアダプターを設定します。

$ bin/hubot -a lingr

hubotが無事に起動すれば、次にLingr上でHubotを稼働させたいRoomでbotを招待します。

上のフォームで先に作成したbotのIDを入力します。

無事に招待が完了し、且つ、Lingr上で発言された内容がHubot側にコールバックされる状態となっていれば、LingrのRoom上で発言した内容にHubotが反応するはずです。

以上の様な手順でLingr上でHubotを稼働させることができる様になりました。

*1:Hubot Adapterという層でチャットサービスとの接続が吸収される

minaで過去にデプロイしたreleaseディレクトリを整理する

2回調べたので記録。

mina でデプロイを行った場合、以下の様にデプロイ先のホストでは管理されます。

lrwxrwxrwx  current -> releases/86/
-rw-rw-r--  last_version
drwxrwxr-x  releases/
drwxrwxr-x  scm/
drwxrwxr-x  shared/
drwxrwxr-x  tmp/

で、この releases ディレクトリには1から始まる数字のディレクトリが掘られて、デプロイする度に順次増えていきます。

単純にデプロイを繰り返しているとこれが増える一方なので、

$ bundle exec mina deploy:cleanup
-----> Cleaning up old releases (keeping 5)
Connection to 10.0.***.*** closed.
Elapsed time: 14.00 seconds

deploy:cleanup というタスクを使うことで直近の5世代分のデプロイ結果を残してそれ以外のものをデプロイ先から削除することができます。

ライブコーディングアプリ「Casto」ができるまで ep.2

もう既に@まとめエントリを書いていてくれるのですが、別の視点でまとめてみようかなと思いまして書いてみます。ということで、ep.2。

"Casto"(キャスト)は一言でまとめると「リアルタイムで更新できるGist」といった形のWebアプリケーションです。

  • ブラウザへ配信したいファイルをドラッグ&ドロップでライブコーディング開始
  • 手元のファイルを編集するだけで編集内容を同じURLを見ている全ユーザに配信

を実現しています。作り始めた経緯は@のエントリを見ていただくことにして、Casto自体はnode.jsのRendrと呼ばれるライブラリ*1とSTORYBOARDSに用意したAPIで構成されています。

サーバー, APIの構成を含め、Castoは下の様な構成になっています。

Rendr

概要と印象

今回はRendrを使ったわけですが、特徴としては、

  • フロント側、サーバ側でbackbone.jsのモデル、ビューが共用される
  • 最初のアクセス時のサーバサイドでのHTML生成がbackbone.jsのmodel, viewを使って行われる
  • ブラウザ側にサーバサイド側で作られたHTMLが描画されて以降は一般的なbackbone.jsアプリと同様の動き方をする
  • DataAdapterという仕組みがあって、modelを介してRendrサーバを経由して任意のAPIへリクエストをフォワードできる
  • ドメインが異なるアプリケーションであってもRendrが一枚入ることでアプリケーションに併せて柔軟に外部APIが制御できる

といったところが挙げられます。まだ、今回利用した範囲もRendrの一部の機能ですが、以下の様な印象を持ちました。

  • サーバーサイドのテンプレートエンジンとフロントサイドのテンプレートエンジンが共用できるのはメリット大きそう
  • 当たり前ですが、node.jsなのでJavaScriptで完結する。加えてbackbone.jsのmodel, viewがサーバサイドでも利用できるのでフロントサイド, サーバサイドの作業を統一できる
  • SPAアプリでよくある「サーバーサイドの言語でDOMの枠を作る」→「backbone.jsのViewでDOMの中を埋める」が無い

ただ、ドキュメントがWeb上に少なかったり、サンプルも少ないので最初動かすまでは少し苦労しましたし、今もブラッシュアップに四苦八苦はしています...。

サーバーの準備

構成管理と構築

REMPSTORYBOARDSを現在はVPSに集約していて、VPSの上にLXCを構築して各アプリケーションを稼働させています。それぞれのLXCはChefを利用して構成管理されています。
既にSTORYBOARDSではアプリケーション自体はRuby(Padrino)で構築されていますが、一部node.jsを導入していたため、その際に準備したcookbookを利用してさっくりとコンテナを作りました。
コンテナさえ稼働させてしまえば、フロント側に用意したnginxでプロキシさせて、LXC上で稼働させたRendrサーバにつなげることで今回稼働させるサーバの準備をそれほど手間なく準備させることができました。

デプロイ

コンテナが準備できれば、あとはRendrアプリをデプロイとなって、こちらの手段もnpmのパッケージで閉じる形にしたかったのですが、リリース世代を管理したりデプロイ手順の整備にREMPやSTORYBOARDSで利用して慣れているRubyのデプロイツールであるminaを利用しました。このあたりの話は以前のブログのエントリを参照ください。CastoでRubyを利用したのは唯一この部分のみとなります。

他のnode.jsアプリのデプロイ方法もいくつか参考にしたのですが、Capistranoを利用しているケースを散見したので、方法としては妥当だったかなと思っています。

Rendrアプリの永続化

Rendrサーバ(node.jsアプリ)を単純に立ちあげたのみだとそのプロセスが死んでしまった際にそのままとなってしまうため、foreverを利用して永続化させる様にしました。

加えて、grunt-foreverというgruntプラグインを利用すると、

grunt.loadNpmTasks('grunt-forever');
grunt.initConfig(
forever: {
app: {
options: {
index: 'index.js',
logDir: 'log'
}
}
}
});

といった設定を足すだけで、

grunt.registerTask('startProduction', ['forever:app:start']);

といったタスクを定義することができる様になって、foreverを利用したサーバ起動・停止が簡単に行える様になります。

いま持っている課題

エラーページでのテンプレートの利用

404ページを用意して、404ステータスエラーが生じた時はこの様なページを表示させようとしたのですが、エラーハンドリングを行った際に任意のビューを利用したページ表示をさせたく、index.jsで、

var server = rendr.createServer({
dataAdapterConfig: config.api,
errorHandler: function (err, req, res, next){
if (err.status == 404) {
// [TODO] ここで任意のビューを利用して404ページを描画させたい!!
}

とすればよさそうなのですが、今もRendr自体のソースを読みながら手探り中です。


と、あれこれ書きましたが、チームでRendrという新しいライブラリを利用して手早くアプリケーションが構築できて、且つメリット・デメリットも多く発見できたこと。個人的には今回初のnode.jsアプリだったのですが、そのサーバサイド側の準備からRendrを利用した際のAPI接続がまずは一通り把握できたことはとても良かったと思います。

更にブラッシュアップはチームで継続していくつもりですので、是非使ってみて感想あれば是非、twitterアカウントIssues · hikarock/casto · GitHubでお知らせください。

*1:あえて作者がフレームワークと呼んでいないのでこの呼び方で。