Slackからビルド作業を行いたいケースが多々ありますが、既存のビルドスクリプトがシェルスクリプトで構築されているようなことがあります。今回はそういったスクリプトをSlack Botと連携させる方法を紹介してみようと思います。
Botでビルド用のスクリプトをキック・監視する
Botのスクリプトは以下になります。ビルドのプロセスをスレッドで走らせつつ、シェルスクリプトの標準入力を読み出し、"MSG: "という行があった場合はその内容をSlackに投稿します。
#!/usr/bin/env ruby
# coding: utf-8
require 'net/http'
require 'uri'
require 'erb'
include ERB::Util
require 'json'
require 'slack'
class BuildBot
def initialize
@token = ENV['SLACK_TOKEN']
@building = false
@task_label = '待機'
Slack.configure {|config|
config.token = ENV['SLACK_TOKEN']
}
@client = Slack.realtime
ready()
puts 'ready.'
@client.start
end
# Slackに投稿する
def post(msg)
channel = 'XXXX' # 特定のチャンネルに投稿先を固定する
param = {
token: @token,
channel: channel,
text: ' ' + msg,
username: 'build-bot(experimental)',
icon_url: 'http://1.bp.blogspot.com/-OTqeO3wl5xU/VOsJndzmvaI/AAAAAAAArqY/eMQywXd1btc/s800/cat1_smile.png'
}
Slack.chat_postMessage(param)
end
# 引数で指定されたコマンドをスレッド上で実行する
# コマンドの出力を一行ずつ読み込み、"MSG:"で始まる文字列の場合は、
# その内容をSlackに投稿する。
def execute_command_on_thread(cmd)
begin
Thread.new do
@building = true # コマンドを再入させないためのlock的な変数
start = Time.now
IO.popen(cmd, "r+") do |proc|
while (line = proc.gets)
msg = line.chomp
puts msg # debug
post($1.gsub(/<BR>/, "\n")) if msg =~ /^MSG:(.*)$/
end
end
finish = Time.now
post('ビルドが完了しました! \(^_^)/')
msg = ':information_source: ビルド時間は `' + (finish - start).round(2).to_s + '秒` でした。'
post(msg)
@building = false
@task_label = '待機'
end
rescue Exception => e
puts e.message
puts e.backtrace.inspect
end
end
def ready
start_time = Time.now.to_i
@client.on :message do |data|
# 実行開始時に少し前の投稿データを読み込んでしますため、
# 現在時刻より前のものはスキップする。
post_time = data["ts"].sub(/\..*$/, "").to_i
next if post_time < start_time
text = data["text"] # 入力されたテキストを取得する
if text =~ /^ビルドして/
if @building == true
post(':warning: いまビルド中です。 (>_<)')
next
end
@task_label = 'ビルド中'
post('ビルドを開始します!')
execute_command_on_thread("cd ~/foo ; /bin/bash ./build_script.sh")
end
end
end
end
BuildBot.new
スクリプトは以下のようになります。既存のビルドスクリプトの場合であっても、echo 'MSG: ...'
という処理を追加してゆくことで、上記のSlack Botと連携できる形になります。
#!/bin/sh
echo 'MSG: ビルド開始します。'
# ...何かビルド処理...
echo 'MSG: ビルド完了しました!'
まとめ
既存のビルド用スクリプトとSlack Botを連携する方法を紹介してみました。