GeekFactory

int128.hatenablog.com

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を実現できます。よさそうなので実戦投入してみよう。