GeekFactory

int128.hatenablog.com

HubotによるJIRAチケット作成の自動化

チケット駆動開発を行う上で障壁になることの一つに「チケット作成が面倒でだんだんやらなくなる」という課題があります。

Jim Coplien先生は紙の付箋を強く推奨しています*1し、私も分かりやすいアナログの方が好きです。しかし、JIRAにはディスプレイさえあればどこでもタスクボードを確認できる、バーンダウンをすぐに確認できるといったメリットがあります。何よりエンジニアはツールを導入したりハックしたりするのが好きですしね。このような理由でデジタルなツールを利用している現場も多いと思います。

本稿では、JIRAを使う上で面倒なチケットの作成をHubotで自動化する方法を考えます。

スプリント計画のフロー

私が以前にいたチームでやっているフローを書きます。現在いるチームでも同じフローを導入しようとしています。

このチームでは、プロダクトバックログリスト(PBL)をGoogleスプレッドシートで管理しています。バックログの相対見積もりやタスク計画も同じスプレッドシートを使っています。スプレッドシートは共同編集できるので、企画からリリースまでチーム全員がリアルタイムに共同作業を進めるにはスプレッドシートが最適ですね。

そんなわけで、プロダクトバックログリストは下表のような形式にしています。

バックログ KPI ステータス 相対見積 タスク
HubotによるJIRAチケット作成の
自動化をブログに書く
ブクマ数 READY 3 設計1
執筆1
推敲1
過去記事のまとめを書く 直帰率の改善 NEW - -

ここでは、1番目のバックログに着手する場合を考えてみましょう。1番目のバックログに対して、JIRAには以下のチケットを追加します。

  • ストーリー「HubotによるJIRAチケット作成の自動化をブログに書く」
    • サブタスク「設計」 残り1時間
    • サブタスク「執筆」 残り1時間
    • サブタスク「推敲」 残り1時間

手作業で行う場合は、JIRAの画面からポチポチとチケットを追加していくことになります。チーム全員で手分けしてやればできますが、とても根気の要る作業です。

Hubotによる自動化

私は考えました。Hubotに話しかけるだけでJIRAにチケットが追加されたら幸せになれそうだと。

@hubot create PROJECT backlog HubotによるJIRAチケット作成の自動化をブログに書く,設計1,執筆1,推敲1

そうすれば、ちょっとしたタスクもチケットに残すようになり、見える化が進んでチームが助け合うようになるのではないかと。

@hubot create PROJECT backlog Hubot勉強会
@hubot create PROJECT backlog Docker勉強会

スプレッドシートバックログとタスクを上記の形式に変換する数式を書いてあげれば、スプレッドシートからチャットに貼り付けるだけでバックログを作成できる仕組みを整備できますね。

そこで、JIRAのREST APIを利用してバックログを作成してくれるHubotスクリプトを書いてみました*2。使い方はREADME.mdを参照してください。

github.com

チケット作成BOTの導入効果

BOTを導入する前は、JIRAをポチポチする作業に10分×チーム人数ぐらいの時間が掛かっていました。BOTを導入することで、わずか数秒で終わるようになりました。より本質的な、バックログやタスクの内容に対する議論に時間を使えるようになりました。

また、チケット作成の作業コストが小さくなったので、レトロスペクティブの内容をバックログに入れるといった改善サイクルを回せるようになってきました。定着するまでには時間が掛かりそうです。

総合的に考えると、チームの貴重な時間を節約できてよかったと思います。

*1:No JIRA!!!とシャウトしてたw

*2:Hubotのスクリプトはどんな形(npm?GitHub?)で公開するとみんなが使いやすくなるのかな。詳しい人ぜひ教えてください。

docker-gitbucketでExternal DBやPrefixなどを設定する

DockerでGitBucketを立ち上げる時は f99aq8ove/docker-gitbucket というイメージを利用しています。GitBucket最新版への追随が早いので重宝しています。

github.com

このたびPRがマージされたので、環境変数でExternal DBやPrefixなどを設定できるようになりました。例えば、下記のdocker-compose.ymlはPostgreSQLを利用します。

version: "2"

services:
  gitbucket:
    image: f99aq8ove/gitbucket
    environment:
      GITBUCKET_OPTS: --prefix=/gitbucket
      GITBUCKET_DB_URL: jdbc:postgresql://db/gitbucket
      GITBUCKET_DB_USER: gitbucket
      GITBUCKET_DB_PASSWORD: gitbucket
    links:
      - db
    volumes:
      - gitbucket-data:/gitbucket
  db:
    image: postgres:9.4
    environment:
      POSTGRES_USER: gitbucket
      POSTGRES_PASSWORD: gitbucket

volumes:
  gitbucket-data:
    driver: local

Multibranch PipelineによるJenkinsとGitBucketの連携

JenkinsのMultibranch Pipelineを利用するとCIで以下ができるようになります。

  • ビルドの設定を Jenkinsfile に書いてバージョン管理できる。
  • リポジトリへのpushやPull Requestのマージを契機にジョブを実行できる。
  • パイプラインでビルドフローを分かりやすく記述できる。

(2017/10/3追記) GitBucketの公式Wikiに設定方法を書きました。

github.com

以下の情報は古いため、GitBucketの公式Wikiを参照してください。

JenkinsとGitBucketを連携させるにはGitBucket Pluginを使う方法がありますが、GitBucketの仕様によりPull Requestのマージを契機にジョブを実行できない制約があります。Multibranch Pipelineを使うとPull Requestのマージを契機にジョブを実行できたので、設定方法をまとめてみました。

前提

GitBucketにGitHub互換のURLでアクセスできるようにリダイレクトを設定する必要があります。GitBucketの手前にリバースプロキシを入れて、リダイレクトの設定を書くのが簡単でしょう。詳しくは下記の記事を参照してください。

int128.hatenablog.com

(10/7追記)上記の記事の内容だと、OrganizationsのリポジトリにPipelineを設定しようとするとエラーになりました。GitBucketでは /api/v3/users/:name でOrganizationの情報を取得できないためのようです。

GitBucketのワークアラウンド

まとめるとGitBucketで以下に対応する必要があります。

  • GitHub互換URLでgit fetchするためのリダイレクト
    • リダイレクト元: /:user/:repo.git*
    • リダイレクト先: /git/:user/:repo.git* (先頭に /git を付加する)
  • Organizationsの情報を/usersで取得できるようにする
    • /api/v3/users/:user がエラーを返したら /api/v3/orgs/:user を試す。それでもエラーの場合はあきらめる。

nginxを下記のように設定すれば動くようになります。

# nginx.conf
server {
  listen 80;
  server_name git.example.org;
  client_max_body_size 10M;
  # GitHub互換URLでgit fetchするためのリダイレクト
  location ~ ^/[^/]+/[^/]+\.git.*$ {
    return https://git.example.org/git$request_uri;
  }
  # Organizationsの情報を/usersで取得できるようにする
  location ~ ^/api/v3/users/(.*)$ {
    proxy_intercept_errors on;
    error_page 404 = /api/v3/orgs/$1;
    # 以下はlocation /と同じ
    proxy_pass http://gitbucket:8080;
    proxy_set_header Host $host;
  }
  location / {
    proxy_pass http://gitbucket:8080;
    proxy_set_header Host $host;
    # 以下はNginxより手前にSSLロードバランサがある場合の設定
    proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
    proxy_set_header X-Forwarded-Host $host:$http_x_forwarded_port;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For $http_x_forwarded_for;
  }
}

(10/10追記)Pull Requestを送ってみたので、将来のバージョンでは改良されるかもしれません。

github.com

GitBucketの設定

GitBucketにjenkinsユーザを作成します。適当なパスワードを設定しておきます。Normalユーザで構いません。

f:id:int128:20161006220520p:plain

リポジトリのWebhookを設定します。Jenkinsが https://jenkins.example.org で動いている場合は https://jenkins.example.org/github-webhook/ がWebhook URLになります。最後のスラッシュは必要です。

f:id:int128:20161006220733p:plain

リポジトリにJenkinsfileを作成します。ここでは以下の内容にします。

node {
  stage('Fetch') {
    checkout scm
  }
  stage('Build') {
    sh 'env'
  }
}

Jenkinsの設定

Jenkinsの設定画面を開き、GitHub Enterprise ServersでGitBucket APIを追加します。GitBucketが https://git.example.org で動いている場合は https://git.example.org/api/v3APIのURLになります。

f:id:int128:20161006145853p:plain

JenkinsからGitBucketにアクセスできるようにjenkinsユーザの認証情報を追加します。パスワードはGitBucketのjenkinsユーザのものです。

f:id:int128:20161006221103p:plain

JenkinsでMultibranch Pipelineジョブを作成します。

f:id:int128:20161006214437p:plain

Branch sourceにGitHubを追加します。まず、API endpointでGitBucketを選び、Ownerにユーザ名を入力すると、リポジトリ一覧が表示されるようになります。Scan credentialsには先ほど追加したjenkinsユーザを指定します。

f:id:int128:20161006214700p:plain

ジョブを作成すると、自動的にブランチ一覧を取得するジョブが実行されます。GitBucketへのアクセスに問題がなければmasterブランチが表示されるはずです。

リポジトリへのPushによるビルド実行

リポジトリのmasterブランチを更新してみましょう。ここでは、GitBucketの画面からREADME.mdを編集してコミットします。

Webhookの設定で問題がなければ、Jenkinsのジョブが実行されるはずです。

f:id:int128:20161006222007p:plain

masterブランチのジョブでFull Stage Viewを選ぶと、パイプラインのステータスを確認できます。

f:id:int128:20161006222257p:plain

Pull Requestのマージによるビルド実行

リポジトリにPull Requestを作成してみましょう。ここでは、GitBucketの画面から新しいブランチを作成し、README.mdをコミットします。そして、ブランチ一覧の画面からPull Requestを作成します。

f:id:int128:20161006224056p:plain

GitBucketの画面からPull Reqeustをマージします。Jenkinsを確認すると、マージを契機にジョブが実行されているはずです。

f:id:int128:20161006223054p:plain

GitBucketのリポジトリ設定でProtected Branchを設定することで、CIを通ったブランチしかマージできないように品質ゲートを設けることも可能です。

まとめ

Multibranch Pipelineを使うとTravis CIやCircle CIのようなモダンなCIを実現できます。よさそうなので実戦投入してみよう。