Help us understand the problem. What is going on with this article?

GitHub + Jenkins で、全てのプルリクエストに対してレビューとテストを必須にする

More than 1 year has passed since last update.

最近関わった某OSSの真似をして、GitHubプロジェクトでプルリクエスト(PR)のレビューと自動テストを必須にしたいと思い、ドキュメントを適当にググりながら設定してたのですが、書いてる内容が古かったりしてやたらこんがらがり、1日仕事になってしまいました。
ということで、自分はこう設定したというメモを残します。まぁこれもほっとくとすぐ古くなりそうですが。
やりたいことは、以下の通り。

  • masterブランチPR発行時、然るべき人にレビューのリクエストが飛ぶようにする
  • 同時に、Jenkinsでテストも実行される
  • レビューとテスト、両方が通らないとmasterにマージできないようにする

まずはレビューを必須に

レビューを必須にするのは、GitHubだけで設定可能です。以下説明。
GitHubプロジェクトを作るところは省略します。ここでは、bonotake/rvtest なるリポジトリをこさえたとします。

コードオーナーを設定する

現在のGitHubは、プロジェクト内のコードのそれぞれにオーナーを設定できます。これは、CODEOWNERSなるファイルを所定の場所(以下の例では.github以下)に置くことで有効になります。
詳しくは公式ドキュメント(英語)を参考にしてもらうとして、ここではこんな感じでファイルを書きます。こう書くと、リポジトリ内の全てのコードのオーナーにGitHubアカウントbonotakeが設定されます。ここには個人アカウントのほか、Organizationアカウントの場合はその中で作ったチームも指定できます。
スクリーンショット 2017-11-23 18.27.09.png

そして、このファイルをmasterブランチにコミットしてプッシュ。
その他、一揃い必要な(PRする必要のない)ファイルは一緒に、今のうちにプッシュしときます。
以降の設定すると、masterへの直接プッシュは(設定解除しない限り)基本できなくなるので。

masterブランチをプロテクトする

GitHubの、プロジェクトのページに飛んで、"Settings"をクリック。
左側のメニューから”Branches"を選びます。
Protected Branchesなる欄があるので、そこの”Choose a branch..."でmasterを選択。
"Branch protection for master"なるページに遷移するので、そこで、

  1. "Protect this branch" にチェック
  2. サブアイテム"Require pull request reviews before merging"にチェック
  3. さらにその下の"Require review from Code Owners"にチェック
  4. とりあえず画面下の"Save changes"をクリック

これで、masterブランチに対するPRが発行されると、コードオーナーにレビューがリクエストされて、そのオーナーのうちの誰かがレビュー・承認しない限り、PRをマージできなくなります。

試しにPRしてみると、こんな感じ。
スクリーンショット 2017-11-23 19.02.19.png
"Code owner review required"となって、bonotake にレビューがリクエストされます。
ついでにいうと、このとき bonotake にはリクエストメールが飛びます。
でbonotakeがこのPRのページを開くと、右上に"Add your review"のボタンが。
スクリーンショット 2017-11-23 19.06.30.png

押すと、レビューが入力できるウィンドウが現れます。

スクリーンショット 2017-11-23 19.08.37.png
コメントを入れられるフォームと、その下に3つの選択肢が出ますが、

  • Comment: とりあえずコメント
  • Approve: PR承認
  • Request changes: PR却下

です。
ここのフォームにコメント入力すると全体へのコメントになりますけど、コードの行ごとにコメント入れることもできます。
で、承認すると、こんな感じでマージ可能に。
スクリーンショット 2017-11-23 19.15.56.png

自動テストも必須に

こっからはJenkinsも使います。Jenkinsサーバそのもののセットアップは省略。

GitHub側:botアカウントの作成

JenkinsがアクセスするためのbotアカウントをGitHubに作成します。
そして、プロジェクトの"Settings"から、"Collaborators"メニューを選択、作ったbotアカウントをcollaboratorに追加します。
botアカウントにinvitationメールが送られるので、そっち側でログインし直してaccept、ログアウトして、元のアカウントでログインし直します。

GitHub側:Webhookの設定

"Settings"から、"Webhooks"メニューを選択。
"Add webhook"ボタンを押して、遷移してで出てきたフォームに入力していきます。
スクリーンショット 2017-11-23 23.30.48.png

  • Payload URL: "http://[Jenkinsサーバ]/ghprbhook/"を入力
  • Which event would you like to trigger this webhook?: "Let me select individual events."を選択

さらに、その下に出てくる項目で、

  • "Pull request"にチェック
  • "Push"のチェックを外す

とします。
スクリーンショット 2017-11-23 19.32.21.png
最後に、”Add webhook"ボタンを押します。

ここで注意なんですが、Jenkinsサーバにアカウントを設定して、ログインしないと各種操作ができない設定にしている場合、上記の設定をしてもダメな場合があります。
そのときは、最初に入れるURLを"http://[ユーザID]:[パスワード]@[Jenkinsサーバ]/ghprbhook/"とするとうまくいきました。
セキュリティ的にどうなの、という気がしなくもないですが、これ以外のよりセキュアな方法が見つからず…… ありました。
上では空欄にしてたんですが、Secretの欄に、適当な文字列を入れてください。長めのランダムな文字列が良いと思います。
この文字列を「合言葉」として、Jenkins側にも設定すれば、ユーザIDとパスワードをURLに直書きする必要はないです。
あと、パスワードの代わりにトークンを用いる方法もあるようです。詳しくはこちらの記事を参照。

Jenkins側:botアカウントの設定

今度はJenkinsの設定。
あらかじめ、Git plugin, GitHub plugin, GitHub Pull Request Builder plugin の3種はインストールしておきます。(「Jenkinsの管理」→「プラグインの管理」からできます。)
そして、さっき作ったbotアカウントをJenkins側に設定します。
「Jenkinsの設定」→「システムの設定」を選択し、遷移した画面の「GitHub Pull Request Builder」欄で

  • GitHub Server API URL: "https://api.github.com" と入力
  • Credentials:
    1. 「追加」ボタン→「Jenkins」をクリック
    2. 現れたダイアログの「ユーザー名」「パスワード」に、さっき作ったbotのアカウント名とパスワードを入力、「追加」ボタンをクリック
    3. プルダウンで、botアカウントが選べるようになるので、選択。
    4. 「Test Credentials...」で、GitHubに接続できるか試せます。ここは省略しますが、一通り試しといたほうがいいでしょう。
  • Description: なんか区別のつく文字列を。ここでは"bot"とだけ入力。

[追記]さっきGitHubのWebhookで"Secret"に文字列を入れた場合、Credentialsの欄、"Shared Secret"のところに同じ文字列を入力します。[追記終わり]

以上やって、「保存」ボタンをクリック。

Jenkins側:ジョブの設定

続いて、ジョブを作ります。とりあえず今回は「フリースタイル・プロジェクトのビルド」でジョブを作成。
ジョブの設定画面で、

  • GitHub projectにチェック
  • 「ソースコード管理」で"Git"を選択
    • 「リポジトリURL」欄に、リポジトリのURL(https://github.com/bonotake/rvtest.git とか)を入力
    • 「高度な設定…」ボタンを押して、「Refspec」欄に "+refs/pull/*:refs/remotes/origin/pr/*" と入力
    • 「ビルドするブランチ」欄を空欄にここに${ghprbSourceBranch}(PRのソースになってるブランチを指定)と入れます。本来は${sha1}(PRを指定)と入れれば良いはずなんですが、僕の環境ではどうしてもうまく動きませんでした。
  • 「ビルド・トリガ」で"GitHub Pull Request Builder"にチェック
    • GitHub API Credentials に "https://api.github.com:bot" (コロン以降はさっきの"Description"に入れた文字列)を選択
    • 更に、"Use github hooks for build triggering" にチェック。ここにチェック入れなかった場合は、cronでJenkins側から定期的にポーリングされます。さっきのGitHub側のWebhookが要らなくなる代わり、Jenkins側の負荷が多少増えるし、PR発行とJenkins起動にタイムラグが発生する場合があるので、ここではチェックを入れます。
    • 「高度な設定」を開き、"White list" にPRしそうなGitHubユーザのアカウント名をあらかじめ入力。ここで指定した人からのPRでのみJenkinsが走ります。
    • → あるいは、"List of organizations. Their members will be whitelisted"にOrganizationアカウントを指定すれば、そのOrganisationに所属する任意のユーザのPRからJenkinsが起動します。
    • → あるいは、"Build every pull request automatically without asking (Dangerous!)."にチェックを入れれば、どんな人のPRからでもJenkinsが走るように。ただし、悪意あるユーザが変なPRをすれば、そのコードでJenkinsサーバを自由に動かせてしまうので、要注意。
    • 同じく「高度な設定」、"Whitelist Target Branches:"に master と入力。これで、masterブランチに対するPRだけがJenkinsビルドの対象になります。
  • 「ビルド」で「ビルド手順の追加」をクリック、「シェルの実行」を選択
    • ここに、具体的に実行するテストスクリプトを入力します。詳細は割愛。各人ご自由に。

以上終わったら、「保存」をクリック。

GitHub側:実際にPRをしてみる

実はまだ設定終わってないんですけど、いっぺんPRをやってみないと先に進めないという、若干バッドノウハウ感の漂う手順が存在するので、とりあえずPRします。内容はとりあえずなんでもいいです。
うまくいくと、このPRでJenkinsが起動して、ステータスがPRの画面に表示されます。
スクリーンショット 2017-11-23 22.35.09.png
こんな感じで、×がついてる(テスト失敗)んですが、その結果は関係なく、レビューが通っていればマージできる状態。
これを、Jenkinsのビルドが失敗すればマージできない状態にします。

GitHub側:テストを必須に

"Settings"から"Branches"メニューを開き、"Protected branches"のところ、先にmasterが選択されてますが、その右横のEditボタンを押します。
ここで、さっきチェックしなかったRequire status checks to pass before mergingにチェック。
"Status checks found in the last week for this repository"のところ、"default"という選択肢が出てますが、これがJenkinsのビルドによるチェックです。この欄が、一回Jenkinsを起動させないと現れないので、まず先にPRをしてみる必要があるのでした。
ということで、この"default"にチェック。右横に"Required"の文字が現れます。
スクリーンショット 2017-11-23 23.11.13.png
画面下の"Save changes"ボタンを押し、先程のPRに戻ってみると、表示がちょっと変わっています。
スクリーンショット 2017-11-23 23.16.49.png

Administratorならマージできるんですが、基本はダメよ状態に。
ここで、ちゃんとテストの通るコミットをしなおしてやると、

スクリーンショット 2017-11-23 23.24.01.png

無事マージできるようになりましたとさ。

[追記]
でも、テストやってるのに表示が"default"って何だかわからないし、テスト失敗してるのに"Finished."って出るのも何だか変だし……と思われるかもしれません。
その場合、ジョブの設定で「ビルド・トリガ」欄の"GitHub Pull Request Builder"以下にある"Trigger Setup..."ボタンを押して、出て来る入力フォームに以下の要領で入力してください。

  • Commit Status Context: "default"の代わりに表示するジョブの名称
  • Commit Status Build Result: ジョブの実行結果(SUCCESS/ERROR/FAILURE)のそれぞれに応じて表示するメッセージ(「追加」ボタンで各メッセージを追加できます)

例えばこんな感じ。

スクリーンショット 2017-11-24 11.04.59.png

ジョブの名称を"test"にして、あと、SUCCESS/ERROR/FAILUREそれぞれにメッセージを変えて入れてます。
で、これを設定後、改めて適当にPRをし(汗)、Require status checks... のところの設定をやり直してください("default"のチェックを外し、"test"にチェックを入れる)。
ジョブごとに名称やメッセージを変えられるので、複数のジョブを定義して、複数のテストを並列実行させ、それぞれの成功を必須にする、なんてこともできます。

注意してほしいのですが、この設定はジョブ単位でやってください。システム単位でもできますが(「Jenkinsの管理」→「システムの設定」)、まともに動作しないので触らない方が無難です。

参考記事とか

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした