2014年9月21日日曜日

RedmineとRedmine WebHook Pluginを改造してバルク編集のHTTP通知を可能に

南旺理工: Redmineのチケット更新をURLへ通知してくれるプラグイン2種の比較 またはハドソンの思い出
http://nanorico.blogspot.com/2014/09/redmineurl2.html
で心配していたとおり、Redmine WebHook Pluginがやっぱりバルク編集に対応していない。

チケット一覧でチケットを右クリックでステータスを変更する技はウチの社員も愛用しているので、対応していないのはまずい。

なので、改修。



updates_notifierプラグインの作者さんの手法
Added new hook: controller_issues_bulk_edit_after_save · f88c6ca · hiddentao/redmine-1 · GitHub
https://github.com/hiddentao/redmine-1/commit/f88c6ca01e89246b5bcd62fa26cc651ee33ba212
と同様に、Redmineのapp/controllers/issues_controller.rbのbulk_updateメソッドにcontroller_issues_bulk_edit_after_saveフックを追加。環境はRedmine 2.5.2。283行目から

(変更前)
if issue.save
  saved_issues << issue

(変更後)
if issue.save
  saved_issues << issue
  # 2014.09.21 HIROTA ADD BEGIN
  call_hook(:controller_issues_bulk_edit_after_save, { :params => params, :issue => issue, :journal => issue.current_journal})
  # 2014.09.21 HIROTA ADD END

そして、Redmine WebHook Pluginのリスナにcontroller_issues_bulk_edit_after_saveメソッドを追加。内容はcontroller_issues_edit_after_saveメソッドのまるまるコピー。

Redmineを再起動。

ついに、Redmineの本体コードの改造に手を出してしまいました…。

ただし、注記を追加しない更新のとき、非バルク編集ではRedmineはjournal.notesに""を格納しますが、バルク編集ではnullという違いがなぜかあるので、受け取り側で考慮が必要です。Hubotであれば
if notes isnt ''
とかしないで
if notes
とすればまとめて扱えるということです。

Hubotスクリプトは、Redmineへのチケット登録・更新をIRCへ通知する部分だけはできあがりました。

# Description:
#   Redmine WebHook Receiver
#
# Dependencies:
#   None
#
# Configuration:
#   None
#
# Commands:
#   None
#
# URLS:
#   /redmine.json

module.exports = (robot) ->
  robot.router.post "/redmine.json", (req, res) ->
    redminekey = 'あなたのRedmine APIキー'
    room = '#inside'
    payload = req.body.payload
    action = payload.action
    url = payload.url
    issue = payload.issue
    issueid = issue.id
    orderdate = issue.start_date
    orderdate6 = "#{orderdate.substr(2,2)}#{orderdate.substr(5,2)}#{orderdate.substr(8,2)}"
    jobnumber = ''
    customerloginid = ''
    robot.http("http://localhost:8000/redmine/issues/#{issueid}.json?key=#{redminekey}")
      .header('Content-Type', 'application/json')
      .get() (err, res, body) ->
        unless err
          data = JSON.parse(body)
          custom_fields = data.issue.custom_fields
          for custom_field in custom_fields
            if custom_field.name is 'No.'
              jobnumber = custom_field.value
            else if custom_field.name is 'ID'
              customerloginid = custom_field.value
          jobcode = "#{orderdate6}-#{jobnumber}#{customerloginid}"
          #str = JSON.stringify(req.body)
          if action is 'opened'
            author = issue.author
            prefix = "#{jobcode} #{author.lastname} #{author.firstname} "
            robot.messageRoom room, "#{prefix}ថែមការងាហើយ : #{url}"
          else if action is 'updated'
            journal = payload.journal
            author = journal.author
            prefix = "#{jobcode} #{author.lastname} #{author.firstname} "
            details = journal.details
            for detail in details
              prop = detail.prop_key
              if prop is 'status_id'
                robot.messageRoom room, "#{prefix}#{issue.status.name} : #{url}"
              else if prop is 'description'
                robot.messageRoom room, "#{prefix}កែបង្គាប់ហើយ : #{url}"
                robot.messageRoom room, "#{issue.description}"
              else
                robot.messageRoom room, "#{prefix}កែការងារហើយ : #{url}"
            notes = journal.notes
            if notes
              robot.messageRoom room, "#{prefix}ថែមទំនាក់ទំនងហើយ : #{url}"
              robot.messageRoom room, "#{notes}"
          #robot.messageRoom room, "#{str}"
    res.send "OK"

CoffeeScriptまるでわかってないんで、慣れたひとからしたらあるまじき泥臭いコードを書いている気がします。

あと、クメール語合ってるかも、プチュム明けに社員に聞いてみます。

カスタムフィールドもJSONに入れこんでくれるようプラグインを改造したいとおもいましたが、やり方がまるでわかんなかったんで、ご覧のとおり、REST APIで取りにいくようにしています。

0 件のコメント:

コメントを投稿