GitLab と Jenkins を連携する (2)

# はじめに

前回の「[GitLab と Jenkins を連携する (1) - Qiita](http://qiita.com/garbagetown/items/fe055dcfd8e0c090e610)」では、GitLab と Jenkins の基本的な連携手順を紹介しましたが、Git や GitLab の長所を活かし切れておらず、誤ったコミットが master に push されてしまいました。

今回は、Git および GitLab の長所を活かしたマージリクエストによる開発手順を紹介します。


## マージリクエストによる開発手順

### issue の作成

まずはコードを変更する契機となった課題や担当者を明らかにするために、GitLab の issue を作成します。

[Issues] メニューを選択したら、[New Issue] をクリックします。

![001.png](https://qiita-image-store.s3.amazonaws.com/0/6755/a4e282d0-c48a-ccdc-7be6-32184ba9ee42.png)

Issue の内容を入力して [Submit new issue] をクリックします。

今回は例なので簡潔に入力していますが、[Details] には後からコードを読んでも判断することのできない課題発生の背景などを記入するとよいでしょう。[Details] では、[GitLab Flavored Markdown (GFM)](https://github.com/gitlabhq/gitlabhq/blob/master/doc/markdown/markdown.md) 記法を使用することができます。

![002.png](https://qiita-image-store.s3.amazonaws.com/0/6755/fb7384ad-d1f4-adb1-980d-eff3b50c6253.png)

正常に Issue が作成されることを確認します。

![002a.png](https://qiita-image-store.s3.amazonaws.com/0/6755/87e332a2-2b26-e44e-feac-47c771577fb3.png)

以上で issue の作成は完了です。


### コードの修正

続いてコードを修正します。まずは issue 対応用のブランチを作成して checkout します。

ここでは単純に issue 番号を指定していますが、ブランチの名称や、リポジトリをフォークする/しない等の運用ルールがすでに存在する場合は、それに従うとよいでしょう。

```bash
$ git checkout -b issues_1
Switched to a new branch 'issues_1'
```

issue の内容のとおりにソースコードを修正します。

```bash
$ git diff
diff --git a/src/main/java/Main.java b/src/main/java/Main.java
index b2cffac..cdf452b 100644
--- a/src/main/java/Main.java
+++ b/src/main/java/Main.java
@@ -1,6 +1,6 @@
 public class Main {

-    public static final Double TAX_RATE = 1.08;
+    public static final Double TAX_RATE = 1.10;

     public static int calc(int price) {
         return new Double(Math.floor(price * TAX_RATE)).intValue();
```

なにか忘れている気がしますが、commit して push してみましょう。

コミットコメントに `#1` のように `#` に続けて issue の番号を書くことで、GitLab 上で commit から issue へのリンクが設定されるので便利です。

```bash
$ git commit -am "消費税率を10%に変更 refs #1"
[issues_1 84b2e2b] 消費税率を10%に変更 refs #1
 1 file changed, 1 insertion(+), 1 deletion(-)

$ git push origin issues_1
Counting objects: 11, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
(snip)
 * [new branch]      issues_1 -> issues_1
```

以上でコードの修正は完了です。


### Merge Request の作成

いよいよ Merge Request を作成します。

[Commits] メニューから [Branches] タブを選び、さきほど push した issues_1 ブランチの [Compare] ボタンをクリックします。

![003.png](https://qiita-image-store.s3.amazonaws.com/0/6755/024fc283-0ec2-bc24-5b68-63475c5cc533.png)

Diff の内容を確認して、問題なければ [Make a merge request] をクリックします。

![004.png](https://qiita-image-store.s3.amazonaws.com/0/6755/4ee7955a-7bc0-e153-8810-289afb76524b.png)

Merge Request の内容を入力して [Submit merge request] をクリックします。

Issue のときと同様、今回は例なので簡潔に入力していますが、[Description] にはレビューアに特に伝えたいこと、注意点などを記入するとよいでしょう。

![005.png](https://qiita-image-store.s3.amazonaws.com/0/6755/9afe5c9c-4057-b154-4deb-12640e81695f.png)

正常に Merge Request が作成されることを確認します。

![006.png](https://qiita-image-store.s3.amazonaws.com/0/6755/cfc9b3ba-5b48-445c-03ef-5842db745a1c.png)

以上で Merge Request の作成は完了です。


## Jenkins による自動ビルド

この時点で Jenkins にアクセスすると、ビルドが実行され、テストに失敗していることが分かります。

![007.png](https://qiita-image-store.s3.amazonaws.com/0/6755/c88af9fa-d733-8e82-e68f-fece602c8f9f.png)

前回の「[ジョブの作成](http://qiita.com/garbagetown/items/fe055dcfd8e0c090e610#3-11)」において、[Branches to build] を空に設定したため、master ブランチだけでなく、今回 push した issues_1 ブランチもビルドの対象となってます。


## マージリクエストによる開発手順（つづき）

### テストの修正

消費税率を 8% から 10% に変更したので、テストも修正する必要がありました。作為的ですね。

このままマージするわけにはいかないので、テストを修正し、commit して push します。

```bash
$ git diff
diff --git a/src/test/java/MainTest.java b/src/test/java/MainTest.java
index c2dc042..c29b142 100644
--- a/src/test/java/MainTest.java
+++ b/src/test/java/MainTest.java
@@ -7,11 +7,11 @@ public class MainTest {

     @Test
     public void 一円に満たない消費税は切り捨てられること() {
-        assertThat(Main.calc(10), is(10));
+        assertThat(Main.calc(9), is(9));
     }

     @Test
     public void 一円を超える消費税は加算されること() {
-        assertThat(Main.calc(30), is(32));
+        assertThat(Main.calc(10), is(11));
     }
 }

$ git commit -am "テストを修正 refs #1"
[issues_1 7de9a17] テストを修正 refs #1
 1 file changed, 2 insertions(+), 2 deletions(-)

$ git push origin issues_1
Counting objects: 13, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 491 bytes | 0 bytes/s, done.
Total 6 (delta 2), reused 0 (delta 0)
(snip)
```

再度 Jenkins にアクセスすると、今度はテストに成功していることが分かります。


### Merge Request のマージ

さきほど作成した Merge Request の画面を開くと、今回の修正内容が反映されていることが分かります。

![008.png](https://qiita-image-store.s3.amazonaws.com/0/6755/00a1a793-f116-33bf-30b7-ea057a37726e.png)

Jenkins による自動ビルドのおかげで、この Merge Request の内容が正しいことは分かっているので、いよいよ master ブランチにマージします。

[Remove source-branch] にチェックを入れて、[Accept Merge Request] ボタンをクリックしてください。

![009.png](https://qiita-image-store.s3.amazonaws.com/0/6755/8dd424a8-b7a1-35a8-e99d-7bb4c8eb9eec.png)

Merge Request が正常にマージされたことを確認します。

![010.png](https://qiita-image-store.s3.amazonaws.com/0/6755/8fcc81dc-54d8-cc55-a67a-67779e3c6206.png)

再度 Jenkins にアクセスし、マージ先である master ブランチでもテストが成功していることを確認します。

![013.png](https://qiita-image-store.s3.amazonaws.com/0/6755/d4e2a9f3-1261-360e-8a71-87acbce638ec.png)

以上で Merge Request のマージは完了です。


### issue のクローズ

以上で issue の対応が完了したので、issue をクローズしましょう。コミットコメントに貼られたリンクなどから issue を開いて、クローズする理由をコメントとして記入たら [Add Comment] をクリックします。

このとき、`!1` のように `!` に続けて Merge Request の番号を書くと、コメントから Merge Request へのリンクが設定されるので便利です。

![011.png](https://qiita-image-store.s3.amazonaws.com/0/6755/dc936ffd-0ec3-3e20-8bec-42b341cc2b13.png)

コメントを追加したら [Close issue] をクリックします。

![012.png](https://qiita-image-store.s3.amazonaws.com/0/6755/e341ffe0-af26-d359-73fa-08df976b4c14.png)

以上で issue のクローズは完了です。


### ソースコードの同期

最後に手元のソースコードをマージが完了している origin と同期します。

以下のようにして、master ブランチに戻って origin からソースコードを pull します。

```bash
$ git checkout master
Switched to branch 'master'
Your branch is up-to-date with 'origin/master'.

$ git pull origin master
remote: Counting objects: 1, done.
remote: Total 1 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (1/1), done.
(snip)
Fast-forward
 src/main/java/Main.java     | 2 +-
 src/test/java/MainTest.java | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)
```

続いて、以下のようにして不要になった branch を削除します。

```bash
$ git branch -d issues_1
Deleted branch issues_1 (was 7de9a17).
```


# まとめ

以上のように、Merge Request による開発手順を踏むことで、master リポジトリに誤った commit が push されることを防止することができました。

しかし、Merge Request の内容が正しいかどうかは Jenkins によるビルド結果を確認しなければ分かりません。さらに、複数人で開発する場合は、複数の Merge Request とビルドが並行して実行されるため、テストが失敗した場合、どの Merge Request のテストが失敗したか判断するのは難しくなるでしょう。

次回は、[jenkins-gitlab-merge-request-builder-plugin](https://github.com/timols/jenkins-gitlab-merge-request-builder-plugin) を使い、テスト結果を Merge Request にフィードバックする方法を紹介します。


## 参考

- [「Gitブランチを使いこなすgit-flow／GitHub Flow入門」最新記事一覧 - ITmedia Keywords](http://www.atmarkit.co.jp/ait/kw/gitflow_nyuumon.html)
- [gitlabhq/doc/markdown/markdown.md at master · gitlabhq/gitlabhq](https://github.com/gitlabhq/gitlabhq/blob/master/doc/markdown/markdown.md)
- [Emoji cheat sheet for Campfire and GitHub](http://www.emoji-cheat-sheet.com/)