読者です 読者をやめる 読者になる 読者になる

スプーキーズのちょっとTech。

SPOOKIES社内のより技工的な、専門的なブログページです。

GitLabとBacklogの連携

記事を書いて寝かしておいたら、忘れてしまって冬になってしまった西塚です。

最近、冷えますが、皆様いかがお過ごしでしょうか。

今回もスプーキーズで利用している開発サービスの話です。

GitLabとBacklogの連携

labs.spookies.co.jp

以前の記事でも紹介しましたが、スプーキーズではGitLabとBacklogを利用しています。

Backlogが提供しているGitリポジトリを利用していないので、そのメリットであるGitのCommitとタスクを関連付けるということが出来ません。

そこで、WebHookとAPIを利用してこれを独自実装しています。

GitLab ⇒ Backlog

GitLabのCommit情報やMergeRequest(PullRequest)から、対応するタスクを参照する機能は、GitLabの設定で実現することができます。

今まではその機能を知らずに、GitLabのViewをカスタマイズすることで実現してましたが、サーバ移行時に設定を見なおしていたら、この機能を発見しました。

GitLab設定

標準はJIRAまたはRedmine用の設定なのですが、Backlogも近い(URL)形式となっているので、設定を応用できます。

  ## External issues trackers
  issues_tracker:
    # redmine:
    #   title: "Redmine"
    #   ## If not nil, link 'Issues' on project page will be replaced with this
    #   ## Use placeholders:
    #   ##  :project_id        - GitLab project identifier
    #   ##  :issues_tracker_id - Project Name or Id in external issue tracker
    #   project_url: "http://redmine.sample/projects/:issues_tracker_id"
    redmine:
      title: "Backlog"
      project_url: "https://xxx.backlog.jp/projects/:issues_tracker_id"
      issues_url: "https://xxx.backlog.jp/view/:id"
      new_issue_url: "https://xxx.backlog.jp/add/:issues_tracker_id"

一時期、GitLabのソースを改変していた時期もあったのですが、マージやメンテが面倒だったりするので、設定だけの方式に切り替えてます。

上記設定により、GitLab の Issue タブを押した際、新規課題を押した際に、Backlogに遷移します。

また、コミットメッセージやプルリクエスト(GitLabではマージリクエスト)に、Backlogの課題IDをつけるように運用しています。

これにより、GitLabからそのBacklog課題へのリンクが自動的に生成されます。このコミットは、どのような課題を解決するために改修したのかがすぐに辿れるようになっています。

Backlog ⇒ GitLab

Backlogの課題からGitLabのCommit情報を参照する為に、Commitされた際にその内容をBacklogにコメントに追加することで実現しています。

GitLab にコミットメッセージもしくは、ブランチ名に課題IDを入れることで自動的に該当する課題にコメントが付加されます。

f:id:rhymester19:20151015171431p:plain

ちなみに、GitHub から Backlog はこんな感じ。

f:id:rhymester19:20151015171448p:plain

Ruby のプログラムで、GitLabのコミットをWebHookで拾って、Backlog API を利用して、該当課題にコメントつけています。

  def parse_json(json)
    event = JSON.parse(json, :object_class => HookBaseObject)
    event.extend(PushEvent)
    event.repository.extend(Repository)
    if event.commits
      event.commits.each { |commit| commit.extend(Commit) }
    end
    event
  end

  def git_push_to_backlog(event)
    description = event.repository.description
    return unless description

    # ex. [master]xxx@xxx.git.backlog.jp:/SANDBOX/sandbox.git
    matches = description.scan /(?:\[(\S+)\])?(\S+?@\S*git.backlog.jp:\S+\.git)/

    Dir.chdir(event.repository.local_path) do
      begin
        matches.each do |branch, url|
          if branch
            system('git', 'push', '-f', url, branch)
          else
            system('git', 'push', '-f', '--mirror', url)
          end
        end
      rescue => error
        log_error(error)
      end
    end
  end

  def build_comment(commit, event, signature)
    comment = ''
    branch_name = event.ref_name
    branch_url = event.repository.branch_page_url(branch_name)
    comment << "**Author:** #{commit.author.name}\n"
    comment << "**Branch:** [#{branch_name}](#{branch_url})\n"
    comment << "**Commit:** [#{commit.id[0,7]}](#{commit.url})\n"
    comment << "\n"
    comment << commit.message.gsub(/^/, '>') + "\n"
    comment << "\n"
    comment << signature
  end

@ つけることで、メンバーにお知らせしたり、 @+1h で時間をつけたり、 #fix で課題を完了させたり、 もしています。

ついでに、Slack にも連携してるので、誰が何の課題をしていて、どんなコミットしたのかは一目瞭然です。

いまは、HubotもBacklogに連携すべく、ゴニョゴニョしていますが、これはまた別の機会に。

それでは。もう少し寝てきます。