Jenkins GitHub PluginをGitBucketで利用する
JenkinsとGitBucketの連携にGitHub Pluginが使えるか調べてみました。GitBucket APIはGitHubと互換性があるので、理論上はGitHub Pluginが使えるはずです。
結論
GitHub互換のURL形式でリダイレクトを設定することで、GitHub PluginでもGitBucketのWebhookを受けてジョブを実行できました。
ただし、GitHub PluginでできることはGitBucket Pluginとほぼ同じです。GitHub PluginのメリットはPipelineに対応していること、CIのステータスを設定できることでしょうか。
方法
ジョブ設定のGit URLに https://gitbucket.example.org/user/repo.git
の形式を指定します。これによってGitHub PluginがWebhookを認識できるようになります。
実際にはこのURLでgit fetchできないため、GitBucketのフロントにリバースプロキシを入れて、以下のリダイレクトを設定します。
リダイレクト元 | リダイレクト先 |
---|---|
https://gitbucket.example.org/user/repo.git |
https://gitbucket.example.org/git/user/repo.git |
https://gitbucket.example.org/user/repo.git/... |
https://gitbucket.example.org/git/user/repo.git/... |
Nginxの場合は以下の設定になります。
location ~ ^/[^/]+/[^/]+\.git.*$ { return 301 https://gitbucket.example.org/git$request_uri; } location / { proxy_pass http://gitbucket:8080; #client_max_body_size 略 #proxy_set_header 略 }
なぜデフォルトでGitHub Pluginが動作しないのか
なぜリダイレクトを設定しないとGitHub Pluginがジョブを実行しないのか調べてみました。
GitBucketからJenkinsへのWebhookの送信は以下の流れで行われます。
- GitBucketがpushイベントのWebhookを
https://gitbucket.example.org/jenkins/github-webhook/
にPOSTする。 - Jenkins GitHub PluginがWebhookを受信する。
- Jenkins GitHub PluginはWebhookからリポジトリ情報を取り出す。
- Jenkins GitHub Pluginはリポジトリ情報に対応するジョブを探して実行する。
GitHub PluginがGit URLを解析する実装を見ると、以下のように http://host/user/repo
の形式になっていました。
private static final Pattern[] URL_PATTERNS = { /** * The first set of patterns extract the host, owner and repository names * from URLs that include a '.git' suffix, removing the suffix from the * repository name. */ Pattern.compile("git@(.+):([^/]+)/([^/]+)\\.git"), Pattern.compile("https?://[^/]+@([^/]+)/([^/]+)/([^/]+)\\.git"), Pattern.compile("https?://([^/]+)/([^/]+)/([^/]+)\\.git"), Pattern.compile("git://([^/]+)/([^/]+)/([^/]+)\\.git"), Pattern.compile("ssh://(?:git@)?([^/]+)/([^/]+)/([^/]+)\\.git"), /** * The second set of patterns extract the host, owner and repository names * from all other URLs. Note that these patterns must be processed *after* * the first set, to avoid any '.git' suffix that may be present being included * in the repository name. */ Pattern.compile("git@(.+):([^/]+)/([^/]+)/?"), Pattern.compile("https?://[^/]+@([^/]+)/([^/]+)/([^/]+)/?"), Pattern.compile("https?://([^/]+)/([^/]+)/([^/]+)/?"), Pattern.compile("git://([^/]+)/([^/]+)/([^/]+)/?"), Pattern.compile("ssh://(?:git@)?([^/]+)/([^/]+)/([^/]+)/?") };
ということはジョブ設定のGit URLを http://host/user/repo
形式にする必要があります。GitBucketのGit URLは http://host/git/user/repo
なのでGitHubと互換性がないのです。
リバースプロキシのレイヤではなくGitBucketのScalatraでリダイレクトできそうな感じです。Jenkinsに限らず、GitHubと同じ形式のURLでgit fetchできることはメリットがあると思います。Pull Requestを送ってみようかな。
もともと解決したかったこと
GitBucket Pluginを使うとPull Requestをマージした契機でジョブが実行されない問題があります。この問題はGitBucket PluginでもGitHub Pluginでも解決できませんでした。そもそもGitBucketはPull Requestをマージした時にpushイベントを投げないようです。
(23:35追記)Multibranch Pipelineを使うと、Pull Requestのマージを契機にジョブを実行できました。ざっくり以下の方法になります。
- GitHub互換URLでアクセスできるようにリダイレクトを設定する(上述)
- GitBucketでWebhookを設定する。
https://git.example.org/jenkins/github-webhook/
に対してpushイベントとpull requestイベントを送信する。 - Jenkinsの設定でGitHub EnterpriseにGitBucket API(
https://git.example.org/api/v3
)を指定する。 - JenkinsでMultibranch Pipelineジョブを作成し、ブランチソースにGitHubを追加する。その際にAPI endpointにGitBucketを指定する。
詳しくは別の記事にします。