LoginSignup
1
1

More than 5 years have passed since last update.

既存のビルド用スクリプトをSlack Botと連携させる話。

Last updated at Posted at 2016-12-17

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を連携する方法を紹介してみました。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1