JenkinsとGerritの連携させてCIっぽい仕組みを作る

CI環境

OpenStackのようなCI/CD環境を自前で作りたいと思っていろいろ調べてみたので備忘録として残しておく。使うプロダクトはGerritとJenkinsと、そのバックエンドのMariaDBの3つ。GerritとJenkinsは、ともにJavaVMの上で稼働させる。

  1. Gerrit - ソースコードレビューに利用
  2. Jenkins - ソースコードの自動ビルド&自動チェックに利用

母艦

仮想マシン(CIサーバ)

  • CPU x 1 / Memory 2048MB
  • CentOS Linux release 7.1.1503
  • IPAddress: 10.0.2.10/24
  • java-1.7.0-openjdk-1.7.0.79-2.5.5.1.el7_1.x86_64
  • jenkins-1.596.2-1.1.noarch
  • gerrit-2.10.3.1.war
  • mariadb-server-5.5.41-2.el7_0.x86_64

Jenkins

事前準備

インストールに利用するwgetと、Jenkinsを起動させるためのjdkを、あらかじめインストールしておく。

---
$ sudo yum install wget
$ sudo yum install java-1.7.0-openjdk
---

インストール

JenkinsのRPMパッケージをインストールする。パッケージはCentOS7としては標準提供されていないが、公式サイトが提供しているJenkinsのリポジトリを利用することにより、Jenkins公式RPMパッケージをインストールすることができる。

---
$ sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat-stable/jenkins.repo
$ sudo rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key
$ sudo yum install jenkins
---

起動

systemctlコマンドでJenkinsの起動と、OSリブート時の自動起動設定を行う。chkconfigではsystemdのサービス適用外というメッセージが出るが、ここではsystemdのサービスに載せないので気にせず進める。

---
$ chkconfig --list jenkins

Note: This output shows SysV services only and does not include native
      systemd services. SysV configuration data might be overridden by native
      systemd configuration.

      If you want to list systemd services use 'systemctl list-unit-files'.
      To see services enabled on particular target use
      'systemctl list-dependencies [target]'.

jenkins         0:off   1:off   2:off   3:on    4:off   5:on    6:off
---

RPMパッケージをインストールすると、RunLevel:3で自動起動onとなっているので、特になにもしない。続いてサービスを手動で起動する。

---
$ sudo service jenkins start
---

確認

Jenkinsはデフォルト状態で起動させると、ダッシュボードとして0.0.0.0:8080にアクセスすることにより利用できる。

http://10.0.2.0:8080

これで、ひとまずJenkinsが正常にインストールされたことが確認できた。

Gerrit

事前準備

Gerritが利用するデータベースをインストールする

Gerritが利用できるデータベースは、公式サイトのドキュメントによると以下の通り。

ここではMySQL(CentOS7なのでMariaDB)を利用する。

---
$ sudo yum install mariadb
$ sudo yum install mariadb-server
$ sudo systemctl enable mariadb
$ sudo systemctl start mariadb
$ sudo mysqladmin -u root password 'changeme'
---

MariaDBのインストールが完了したら、続いてGerritが利用するデータベースとユーザを作成する。

---
MariaDB [(none)]> CREATE USER 'gerrit2'@'localhost' IDENTIFIED BY 'changeme';
MariaDB [(none)]> CREATE DATABASE reviewdb;
MariaDB [(none)]> GRANT ALL ON reviewdb.* TO 'gerrit2'@'localhost';
MariaDB [(none)]> FLUSH PRIVILEGES;
---

※Gerritを起動させるためにはjdkが必要だが、これはJenkinsのインストール時に既にインストール済みなので割愛。

Gerritユーザ(gerrit2)を作成する

Gerritが利用するユーザアカウント(gerrit2)を作成する。

---
$ sudo adduser gerrit2
---

インストール

Gerritをダウンロードする。

---
$ sudo su - gerrit2
$ wget https://gerrit-releases.storage.googleapis.com/gerrit-2.10.3.1.war
---

起動

ここでは サイト名:review_site のGerritサイトを初期化する。

---
$ java -jar gerrit-2.10.3.1.war init -d /home/gerrit2/review_site

*** Gerrit Code Review 2.10.3.1
***

Create '/home/gerrit2/review_site' [Y/n]? Y

*** Git Repositories
***

Location of Git repositories   [git]:

*** SQL Database
***

Database server type           [h2]: mysql

Gerrit Code Review is not shipped with MySQL Connector/J 5.1.21
**  This library is required for your configuration. **
Download and install it now [Y/n]? Y
Downloading http://repo2.maven.org/maven2/mysql/mysql-connector-java/5.1.21/mysql-connector-java-5.1.21.jar ... OK
Checksum mysql-connector-java-5.1.21.jar OK
Server hostname                [localhost]:10.0.2.10
Server port                    [(mysql default)]:
Database name                  [reviewdb]:
Database username              [gerrit2]:
gerrit2's password             :
              confirm password :

*** Index
***

Type                           [LUCENE/?]:

*** User Authentication
***

Authentication method          [OPENID/?]:

*** Review Labels
***

Install Verified label         [y/N]? y

*** Email Delivery
***

SMTP server hostname           [localhost]:
SMTP server port               [(default)]:
SMTP encryption                [NONE/?]:
SMTP username                  :

*** Container Process
***

Run as                         [gerrit2]:
Java runtime                   [/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.45-30.b13.el7_1.x86_64/jre]:
Copy gerrit-2.10.3.1.war to /home/gerrit2/review_site/bin/gerrit.war [Y/n]? Y
Copying gerrit-2.10.3.1.war to /home/gerrit2/review_site/bin/gerrit.war

*** SSH Daemon
***

Listen on address              [*]:
Listen on port                 [29418]:

Gerrit Code Review is not shipped with Bouncy Castle Crypto SSL v151
  If available, Gerrit can take advantage of features
  in the library, but will also function without it.
Download and install it now [Y/n]? Y
Downloading http://www.bouncycastle.org/download/bcpkix-jdk15on-151.jar ... OK
Checksum bcpkix-jdk15on-151.jar OK

Gerrit Code Review is not shipped with Bouncy Castle Crypto Provider v151
** This library is required by Bouncy Castle Crypto SSL v151. **
Download and install it now [Y/n]? Y
Downloading http://www.bouncycastle.org/download/bcprov-jdk15on-151.jar ... OK
Checksum bcprov-jdk15on-151.jar OK
Generating SSH host key ... rsa... dsa... done

*** HTTP Daemon
***

Behind reverse proxy           [y/N]? N
Use SSL (https://)             [y/N]? N
Listen on address              [*]:
Listen on port                 [8080]: 8081
Canonical URL                  http://localhost:8081/: http://10.0.2.10:8081

*** Plugins
***

Install plugin commit-message-length-validator version v2.10.3.1 [y/N]? y
Install plugin download-commands version v2.10.3.1 [y/N]? y
Install plugin replication version v2.10.3.1 [y/N]? y
Install plugin reviewnotes version v2.10.3.1 [y/N]? y
Install plugin singleusergroup version v2.10.3.1 [y/N]? y

Initialized /home/gerrit2/review_site
...
---

Gerritがデフォルトで開くポートは8080で、Jenkinsが利用しているポートとバッティングする。そこで、GerritをPort:8081で起動するよう明示的に指定してGerritを起動させることにした。

ちなみに、サービスの起動・停止・再起動はサイト(review_site)以下にインストールされている bin/gerrit.sh スクリプトを利用して行う。

---
/home/gerrit2/review_site/bin/gerrit.sh stop|start|restart
---

最後に自動起動設定を行う。gerrit.shはchkconfigコマンドに対応した記述となっている。

---
$ exit    # gerrit2ユーザからexitする
$ ln -snf /home/gerrit2/review_site/bin/gerrit.sh /etc/init.d/gerrit
# sudo -i
# chkconfig --add gerrit
# echo "GERRIT_SITE=/home/gerrit2/review_site" > /etc/default/gerritcodereview
---

確認

Webプラウザで、GerritサーバのPort:8081にアクセスすると、Gerritのダッシュボードを利用することができる。ログインアカウントはLaunchpadアカウント(母艦上で利用しているユーザの公開鍵登録済み)を利用した。

http://10.0.2.0:8081

これで、Gerritも正常にインストールされたことが確認できた。

プロジェクト登録

Gerritのインストールが完了したところで、テスト用のプロジェクト「sandbox」を作成して、Gerritが正しく機能提供できているかをチェックする。

  1. Gerritダッシュボード -> Sign In -> Sign in with a Launchpad ID -> Launchpadアカウントでログインする
  2. settings -> profile -> Usernameを設定する -> SSH Public Keys -> 公開鍵を登録する -> HTTP Password -> Generate Passwordでパスワードを生成する

これでGerritにログインしてプロジェクトを作成することが可能となったので、実際にsandboxプロジェクトを作成してみる

---
$ ssh -p 29418 foo@10.0.2.10 gerrit create-project --empty-commit --name sandbox
---

エラーが出なければ作成成功。Gerritのダッシュボードから確認すると、sandboxプロジェクトが作成されているのがわかる。

続いて、母艦(osx)上で、gitコマンドでGerritのサイトからソースコードをチェックアウトしてみる。

---
$ git clone http://10.0.2.10:8081/sandbox
$ cd sandbox
$ git config --local user.name foo
$ git config --local user.email foo@example.com

$ git remote add gerrit http://10.0.2.10:8081/sandbox
$ git-review -s

$ git branch test/0
$ git checkout test/0
$ date > testfile.txt
$ git add testfile.txt
$ git commit
$ git-review
Username for 'http://10.0.2.10:8081': プロジェクト登録で指定したUsername
Password for 'http://foo@10.0.2.10:8081': プロジェクト登録で生成したHTTP Password
---

おまけ

デフォルトのプロジェクト設定ファイル(project.config)を変更したい場合

---
$ git init cfg ; cd cfg
$ git remote add origin ssh://foo@10.0.2.10:29418/All-Projects
$ git pull origin refs/meta/config
$ vi project.config
$ git push origin HEAD:refs/meta/config
---

いろいろあってパッチセットをDBから削除したい

---
MariaDB [(none)]> use reviewdb
MariaDB [reviewdb]> delete from patch_sets;
---

JenkinsとGerritの連携

事前準備

JenkinsがGerritを利用するために必要になる公開鍵を作成する。パスフレーズありだとテストが成功しないため、ここではパスフレーズ無しの公開鍵を生成した。生成した公開鍵は、あらかじめクライアントに登録しておく。

---
$ sudo -u jenkins ssh-keygen -t rsa -C foo@example.com
---

続いて、母艦(osx)から、GerritにJenkinsのユーザアカウントを登録する。ここでは、アカウント名:jenkinsとした。生成した公開鍵の登録も忘れずに。

---
$ ssh -p 29418 foo@10.0.2.10 gerrit create-account jenkins --email foo@example.com --full-name jenkins
$ cat /tmp/jenkins.pub | ssh -p 29418 foo@10.0.2.10 gerrit set-account jenkins --add-ssh-key -
---

続いて、CIサーバからjenkinsユーザでGerritにログインできることを確認する。Welcomeメッセージが表示されれば、公開鍵の登録は無事に完了している。

---
sudo -u jenkins ssh jenkins@localhost -p 29418
---

Gerrit上でJenkinsのユーザアカウントに対して、コードレビューに必要な権限を設定する。

  1. AdministratorグループのアカウントでGerritにログイン
  2. People -> List Groups -> Non-Interactive Users -> Members を選択する
  3. jenkins ユーザをAddする
  4. Projects -> List -> sandbox -> Access -> Edit -> Add Reference を押す
  5. Reference: refs/* を設定する
  6. Reference: refs/* で Add Permissions -> Read -> ALLOW: Non-Interactive Users を選択する
  7. Reference: refs/heads/* で Label Code-Review に Non-Interactive Users を(-1,+1)で追加する
  8. Reference: refs/heads/* で Label Verified に Non-Interactive Users を(-1,+1)で追加する
  9. People -> Create New Group : "Event Streaming Users" を作成して jenkins ユーザを追加する
  10. Projects -> List -> All-Projects -> Access -> Edit -> Global Capabilities -> Stream Events に ALLOW: Event Streaming Users を追加する

Jenkinsプラグインのインストール

Jenkinsのダッシュボードのプラグインの管理から、Gerrit Trigger PluginとGit Pluginをインストールする。

Gerrit Triggerプラグインの設定

プラグイン管理->Gerritトリガー を選択して、以下の3つのセクションの設定を行う。設定を保存するのを忘れずに。

  1. 新しいサーバを追加
  2. Gerrit接続設定
  3. Gerritレポートスコア

新しいサーバを追加

---
- サーバを追加: develop
- ◉ Gerrit Server with Default Configurations
---

Gerrit接続設定

---
- 名前: develop
- 起動時に接続しない: □
- ホスト名: 10.0.2.10
- フロントエンドURL: http://10.0.2.10:8081/
- SSHポート: 29418
- プロキシ: 空
- ユーザー名: jenkins
- メールアドレス: foo@example.com
- SSHキーファイル: /var/lib/jenkins/.ssh/id_rsa
- SSHキーファイルパスワード: 空
- 最新のパッチのみビルド: □
---

Gerritレポートスコア

---
Verified
  ===
  - 開始: 0
  - 成功: 1
  - 失敗: -1
  - 不安定: 0
  - ビルドせず: 0
  ===

Code-Review
  ===
  - 開始: 0
  - 成功: 1
  - 失敗: -1
  - 不安定: 0
  - ビルドせず: 0
  ===
---

JenkinsとGerritを連携させるジョブの作成

Jenkinsのダッシュボードから、新規ジョブの作成を選択する。

---
プロジェクト名: sandbox_gerrit
説明: Gerritのサンプルプロジェクト用のテストジョブ
フリースタイルジョブ
□ 古いビルドの破棄    Help for feature: 古いビルドの破棄
□ ビルドのパラメータ化  Help for feature: ビルドのパラメータ化
□ ビルド無効化 (プロジェクトが再び有効化されるまで新しいビルドは行われなくなります)
□ ビルドを並行実行
---

ソースコード管理

---
○ なし 
○ CVSCVS Projectset 
◉ Git
   ===
   Repositories
   - Repository URL: git+ssh://jenkins@10.0.2.10:29418/sandbox.git
   - Credentials: なし
   - 高度な設定:
     - Name: 空
     - Refspec: $GERRIT_REFSPEC

   Branches to build
   - Branch Specifier (blank for 'any'): 空   .....空文字にしても、設定を反映すると結局は"**"が入る

   リポジトリ・ブラウザ: 自動

   Additional Behaviours: Strategy for choosing what to build
   - Choosing strategy: Gerritトリガー
   ===
○ Subversion
---

ビルド・トリガ

---
□ Build after other projects are built
■ Gerritイベント
---

Gerritトリガー

トリガーするGerritイベントに、必要なイベントを追加していくが、Patchset Createdだけで十分かな。

---
サーバー: develop
サイレントモード: □
レビューされていないパッチセットをチェックする: ■
トリガーするGerritイベント
  ===
  - Patchset Created
    - Draftsを除外する: □
    - Trivial Rebaseを除外する: □
    - No Code Changeを除外する: □
  ===
動的トリガー設定: □

プロジェクト追加
  ===
  Gerritプロジェクト
  - タイプ: Plain
  - パターン: sandbox
  - ブランチ追加
    ===
    タイプ: Path
    パターン: **
    ===

□ SCMをポーリング
□ 定期的に実行
---

ビルド

ビルド手順を追加する。テスト用なので、成功させたいときは exit 0 で、失敗させたいときは exit 0以外 とする。

---
シェルの実行
  - シェルスクリプト
    ===
    #!/bin/sh
    echo "Jenkins review is done"
    exit 0
    ===
---

おわり

これで、ソースコードをcloneしてソースコードを修正後にcommitし、git-reviewにかけるとパッチセットが作成されて、Gerrit上でレビューが実施できる状態となり、そのタイミングでパッチセットの自動ビルドとチェックをJeninsを利用して実施できる環境を構築できた。

ビルド後の処理

特に何もしない

参考URL