GitHubでMergeされたらBacklogもRailsで自動更新する


GitHubとBacklogどちらも更新状態を同じに保つのを手動で操作するのは面倒だと思ったので、
APIを使って、自動更新ができるようにしてみました。

## 今回の仕様

### GitHubでMergeされたら次を実行

* 課題担当者を「StgUp待ち」ユーザーに切り替える。

　　※「StgUp待ち」という名前のBacklogユーザーを作って
　　　どのタスクが完了していてStg環境にあげていいのかを分かるように運営している為。

* 処理済ステータスに切り替える
* コメントに、プルリクURLとMergeユーザー名を投稿
* マージされたことを実装担当者にBacklogのお知らせ機能で通知


### 注意点
今のところ下記条件では更新されない仕様

* ProjectIDを含むBacklogIDがプルリクエストのタイトルに含まれていない場合
* Backlogの課題が既に、担当者切替予定のユーザー(StgUp待ち)または処理済みステータスになっていた場合。


## 実装環境

### Heroku
https://dashboard.heroku.com

### Rails
ruby '2.1.2'
rails '4.1.4'

### GitHub Webhook
Github上で起きたアクションの度に指定したurlに情報をpostしてくれるWebhook機能を利用。
https://developer.github.com/webhooks/


### Backlog API2

API バージョン２ を使いました
http://developer.nulab-inc.com/ja/docs/backlog/api/2/update-issue



## Rails Code

```ruby:hooks_controller.rb
class HooksController < ApplicationController

  # MergeされたらBacklogを更新
  def change_backlog_status
    render :nothing => true
    if params[:pull_request].present?
      # PullRequests 内容
      title = params[:pull_request]["title"]
      merged = params[:pull_request]["merged"]
      backlog_id = title.scan(/#{Backlog::PJT_KEY}-\d+/)
      backlog_id = backlog_id[0]
      puts "backlog_id: #{backlog_id}------>"

      if title.present? && merged == true
        puts "merged: true------>"
        # Backlogコメント内容
        pull_request_url = params[:pull_request]["html_url"]
        merge_user = params[:pull_request]["merged_by"]["login"]
        comment_text = "▼コードがdevelopにマージされました。 \n ・GitHub: #{pull_request_url} \n ・MergeUser: #{merge_user}"
        # 更新
        backlog_change(backlog_id, comment_text)
      end
    end
  end

  private
    # BacklogAPI: http://developer.nulab-inc.com/ja/docs/backlog/api/2/get-space

    def get_backlog_data(get_url)
      api_url = "#{Backlog::URL}#{get_url}?apiKey=#{Backlog::API_KEY}"
      response = Net::HTTP.get(URI(api_url))
      JSON.parse(response)
    end

    def get_http(api_url)
      uri = URI(api_url)
      http = Net::HTTP.new(uri.host, uri.port)
      http.use_ssl = true
      http.verify_mode = OpenSSL::SSL::VERIFY_NONE
      http
    end

    # コメントを担当者だった人にお知らせ
    def notifications(backlog_id, user_id)
      # コメントID取得: http://developer.nulab-inc.com/ja/docs/backlog/api/2/get-comments
      get_url = "/api/v2/issues/#{backlog_id}/comments"
      comments = get_backlog_data(get_url)
      comment_id = comments.first["id"]
      puts "comment_id: #{comment_id}----->"

      # コメントをお知らせ: http://developer.nulab-inc.com/ja/docs/backlog/api/2/add-comment-notification
      update_url = "/api/v2/issues/#{backlog_id}/comments/#{comment_id}/notifications"
      api_url = "#{Backlog::URL}#{update_url}?apiKey=#{Backlog::API_KEY}"
      http = get_http(api_url)
      params = {"notifiedUserId"=>[user_id]}.to_param
      response = http.send_request('POST', api_url, params)
    end

    # Backlog更新
    def backlog_change(backlog_id, comment_text)
      # 更新: http://developer.nulab-inc.com/ja/docs/backlog/api/2/update-issue
      update_url = "/api/v2/issues/#{backlog_id}" # PATCH
      api_url = "#{Backlog::URL}#{update_url}?apiKey=#{Backlog::API_KEY}"
      http = get_http(api_url)
      # 更新前担当者ID取得
      issues = get_backlog_data("/api/v2/issues/#{backlog_id}")
      user_id = issues["assignee"]["id"]
      puts "user_id: #{user_id}------>"
      # 内容：StgUp待ちユーザーに/処理済(id:3)へ/comment:PullRequests URL + Mergeユーザー名を投稿
      params = {"assigneeId"=>Backlog::STG_USER, "statusId"=>3, "comment"=>comment_text}.to_param
      response = http.send_request('PATCH', api_url, params)

      # お知らせ
      notifications(backlog_id, user_id)
    end
end
```

## 参考にした記事やコードメモφ(・・*)

* Rails 4.0だとCSRFトークンでエラーになる - Qiita http://qiita.com/naoty_k/items/b40b13735fd7f06f8cb7

* HTTP参考：https://github.com/rohit9889/http-requestor/blob/master/lib/http_requestor.rb

* 初心者でも15分で公開できるHerokuのはじめかた — Mobage Developers Blog 
 http://developers.mobage.jp/blog/how-to-use-for-beginners-heroku