Jenkins”だけ”で継続インテグレーションの真似事

#はじめに
Jenkinsの継続的インテグレーション（CI:Continuous Integration）については、以下記事に書いた通り、外部ツールをふんだんに取り入れないとビルド/テスト/デプロイの自動化が難しいです。

それでも、「Jenkinsだけで無理やり継続的インテグレーションってのをやってみたい！」っていうのを、無知ながらもやってみた結果になります。

>Jenkins”だけ”でほんとうにできること
https://qiita.com/Higemal/items/bb9a0c12b8fca0dd6657


#やりたいこと
自動ビルド
↓　ビルドが問題なく通ったら
自動テスト
↓　テストが問題なく通ったら
自動デプロイ

#もう少し細かく
①手動でプログラムのコーディング
②手動でテスト用プログラムのコーディング
③自動でプログラムのビルド
④自動でテスト用プログラムのビルド
⑤自動でテスト（テスト用プログラムの実行）
⑥自動で環境へのデプロイ
⑦継続インテグレーション実行確認

#環境
Ubuntu 14.04.3
Java JDK 1.8
Jenkins 2.73.2
言語：Java
エディタ：vi
>Ubuntu 14.04にjenkins 2.73.2をインストールする(OS上に直接)
https://qiita.com/Higemal/items/6b564cc10fbe2aeb5b17


#いざ実践
・・・の前に、今回使用するディレクトリの説明です。

```
/develop/UT/java
──┬──────────────
　├drwxrwxr-x  source/　　　　←ソースコード置き場（プログラム）
　├drwxrwxr-x  testsource/   ←ソースコード置き場（テスト用プログラム）
　│
　├drwxrwxrwx  jenbin/　　　　←ビルド確認用バイナリ置き場（プログラム）
　├drwxrwxrwx  jentestbin/　　←ビルド確認用バイナリ置き場（テスト用プログラム）
　│
　├drwxrwxrwx  bin/　　　　 　←デプロイ先ディレクトリ（プログラム）
　└drwxrwxrwx  testbin/　 　　←デプロイ先ディレクトリ（テスト用プログラム）
```
＃下4つのディレクトリは「jenkins」というJenkinsのユーザが触るため、パーミッションは777にしておきます。

#①手動でプログラムのコーディング
プログラムの引数を足し算するだけのソースを作りました。
エラーハンドリング等してないのは~~スキル不足~~ご愛嬌。

/develop/UT/java/source/Plus2args.java

```Plus2args.java
//  Plus2args

public class Plus2args {
        public static void main (String[] args){
                add(args);
        }

        public static void add(final String[] args) {
                int number;
                number = Integer.parseInt(args[0]) + Integer.parseInt(args[1]);
                System.out.println(number);
                System.exit(0);
        }
}
// EOL
```


#②手動でテスト用プログラムのコーディング
とりあえず正常終了を確認するだけの以下ソースを作りました。
出力値確認すらしてないのは~~技術力の限界~~ご愛嬌。

/develop/UT/java/testsource/UT_Plus2args.java

```UT_Plus2args.java
// UT_Plus2args.java

import java.util.*;
import java.io.*;

public class UT_Plus2args {
        public static void main (String[] args) {
                Test_Normal();
                System.exit(0);
        }

        public static void Test_Normal() {
　　　　　　　　　//ビルド確認用ディレクトリ内のクラスファイルを実行するコマンド文字列
                String command = "java /develop/UT/java/jenbin/Plus2args 6 9";
                Runtime runtime = Runtime.getRuntime();
                try {
                        //クラスファイルの実行、および実行完了まで待機
                        Process process = runtime.exec(command);
                        int exitValue = process.waitFor();
                }

                catch(IOException e) {
                        System.out.println("Test_Normal execuing error. IOException.");
                        System.exit(1);
                }
                catch(InterruptedException e) {
                        System.out.println("Test_Normal execuing error. InterruptedException.");
                        System.exit(1);
                }

                finally{
                }
                //正常終了確認用メッセージ
                System.out.println("Test_Normal executed.");
        }
}

// EOL

```


#③自動でプログラムのビルド
ようやっとJenkinsの登場です。以下を設定しようと思います。
　・ジョブ名は　20171111_Build_Plus2args
　・毎日13時05分にビルドを実行する
　・ソースプログラムをコンパイルしてビルド確認用ディレクトリに置く

まず左上の「新規ジョブの作成」
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/582440c9-fac5-6763-6757-b515d0fea16c.png)

「Enter an item name」にジョブ名を設定して、「フリースタイル・プロジェクトのビルド」を選択して「OK」
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/f41a8f0e-b54d-d8d8-bbd0-3e44f1cb7e89.png)

設定画面に移ります。説明等をここに書くことができます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/565f468f-68fc-a82c-a79e-193695967a1b.png)

ビルドトリガで「定期的に実行」を選び、「5 13 * * *」を設定して実行時間を固定します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/049fb1dc-2993-af10-1a62-ab98bc990529.png)

ビルドで「シェルの実行」を選び、以下コマンドを設定して、ビルドしたらビルド確認用バイナリ置き場にクラスファイルを出力するようにします。

```
javac /develop/UT/java/source/Plus2args.java -d /develop/UT/java/jenbin
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/5532476c-cfd2-9ff0-91ce-ec6d8359df01.png)

保存ボタンで確定すると、ジョブの詳細画面になります。（スクショはすでにだいぶ触った後なのでビルド履歴がおかしいことになってますが）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/5a06acca-e809-c9fd-d042-518a04842883.png)

＃ちなみに、今作ったジョブをすぐ実行したい場合は、左側の「ビルド実行」で即時実行できます。実行後、ビルド履歴に実行結果が出力されます。してみた結果がこちら。↓
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/3b7661c1-3d2e-d563-c979-ccdec08c410c.png)
↓ビルド履歴の「コンソール出力」を選択するとその結果が出ます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/c615def4-2b22-54c7-8e5e-e34495cbcfb3.png)

#④自動でテスト用プログラムのビルド
Jenkins設定の説明が入ったのでちょっと本筋からずれましたが、テスト用プログラムについても同様にJenkinsジョブ設定で自動化します。

今回は以下を設定しようと思います。先ほどと同じように新規ジョブを作成します。
　・ジョブ名は　20171111_Build_UT_Plus2args
　・ソースプログラムのビルドに成功したら、ビルドを実行する
　・テスト用ソースプログラムをコンパイルしてビルド確認用ディレクトリに置く

ビルドトリガで「他プロジェクトの後にビルド」を選び、対象プロジェクトに「20171111_Build_Plus2args」を設定して、ジョブ連携を実現します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/4074f273-c03b-dfa8-ae30-25a84c97c838.png)



ビルドは「シェルの実行」を選び、以下コマンドを設定して、ビルドしたらビルド確認用バイナリ置き場にクラスファイルを出力するようにします。さっきとほぼ同じ。

```
javac /develop/UT/java/testsource/UT_Plus2args.java -d /develop/UT/java/jentestbin
```
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/7b4b245a-1607-d78d-d963-2f22922b7f16.png)

＃ちなみに、ソースファイルを少し壊してビルドを実行すると、ビルド実行結果が赤くなり、コンソール画面からエラー内容の確認ができます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/8cdeb430-0d5d-c85b-d028-f8ea1be6edec.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/4c83fb17-44d2-ef61-4392-78920d687df8.png)


#⑤自動でテスト（テスト用プログラムの実行）
テスト用のジョブを設定します。
　・ジョブ名は　20171111_UnitTest_Plus2args
　・テスト用ソースプログラムのビルドに成功したら、テストを実行する
　・テスト成功はテスト用クラスファイル実行の正常終了と定義する

新規ジョブを作成。
ビルドトリガは「他プロジェクトの後にビルド」、対象プロジェクトに「20171111_Build_UT_Plus2args」を設定。
ビルドは「シェルの実行」を選び、以下コマンドを設定。テスト用クラスファイルを実行します。

```
java -cp /develop/UT/java/jentestbin UT_Plus2args
```

＃設定画面は省略します。


＃即時実行し、成功したジョブ結果のコンソール出力です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/2d3352bc-dc53-ff4a-c521-8035d944766f.png)

#⑥自動で環境へのデプロイ
最後のジョブ、デプロイ用のジョブを設定します。
　・ジョブ名は　20171111_DeployUT_Plus2args
　・テスト用クラスファイルの実行に成功したら、デプロイを実行する

新規ジョブを作成。
ビルドトリガは「他プロジェクトの後にビルド」、対象プロジェクトに「20171111_UnitTest_Plus2args」を設定。
ビルドは「シェルの実行」を選び、以下コマンドを設定。ソースファイルをコンパイルして、デプロイ先ディレクトリに生成したクラスファイルを置きます。

```
javac /develop/UT/java/source/Plus2args.java -d /develop/UT/java/bin
javac /develop/UT/java/testsource/UT_Plus2args.java -d /develop/UT/java/testbin
```

＃設定画面は省略します。

＃即時実行し、成功したジョブ結果のコンソール出力です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/5dbb8232-315e-7c30-f465-7a298dae410a.png)

#＃ちょっとここで流れのおさらい（ジョブ連携）
>↓定時起動（毎日13:05)
20171111_Build_Plus2args　プログラムのビルド
↓ジョブ正常終了
20171111_Build_UT_Plus2args　テスト用プログラムのビルド
↓ジョブ正常終了
20171111_UnitTest_Plus2args　テスト（テスト用プログラムの実行）
↓ジョブ正常終了
20171111_DeployUT_Plus2args　環境へのデプロイ

#⑦継続インテグレーション実行確認
最後にビルド、テスト、デプロイの自動連携実行（≒継続的インテグレーション）を確認します。
最初のトリガとなるプログラムビルドは即時実行で投入します。

プログラムビルドのジョブを即時実行。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/5b69512e-3564-0915-460b-0ed4fc7bbd08.png)

ビルド履歴を確認。うまくいっていってるっぽい。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/38e5746c-139f-9538-eb3a-fa1bcb3ac45f.png)

ビルドジョブのコンソール画面。正常終了できている。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/115957c3-e2ae-86f4-3628-77011f2dfdfc.png)


テスト用プログラムのビルドジョブのコンソール画面。正常終了できている。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/066f35b0-bbea-bc1c-178a-5267aa9deef9.png)


テストジョブのコンソール画面。正常終了できている。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/d705e4b0-2722-3f71-4b4d-f2d8417f2f8b.png)


デプロイジョブのコンソール画面。正常終了できている。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/201787/f0dd6d3b-500d-2319-6775-8fbb96159e55.png)

ファイル確認。各ジョブの正常終了時間にてファイルが作成されている。

```
batchuser@ubnt14-gn01:/develop/UT/java$ ll ./jenbin/Plus2args.class
-rw-r--r-- 1 jenkins jenkins 562 11月 16 23:18 ./jenbin/Plus2args.class

batchuser@ubnt14-gn01:/develop/UT/java$ ll ./jentestbin/UT_Plus2args.class
-rw-r--r-- 1 jenkins jenkins 1196 11月 16 23:18 ./jentestbin/UT_Plus2args.class

batchuser@ubnt14-gn01:/develop/UT/java$ ll ./bin/Plus2args.class
-rw-r--r-- 1 jenkins jenkins 562 11月 16 23:19 ./bin/Plus2args.class

batchuser@ubnt14-gn01:/develop/UT/java$ ll ./testbin/UT_Plus2args.class
-rw-r--r-- 1 jenkins jenkins 1196 11月 16 23:19 ./testbin/UT_Plus2args.class
```


クラスファイル実行確認。ちゃんと動いている。
＃エラーハンドリングしていない部分はもちろんエラー停止する。

```
batchuser@ubnt14-gn01:/develop/UT/java$ java -cp  ./bin Plus2args 10 21
31

batchuser@ubnt14-gn01:/develop/UT/java$ java -cp  ./bin Plus2args
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 0
        at Plus2args.add(Plus2args.java:10)
        at Plus2args.main(Plus2args.java:5)
```


#うまくいきました！


ということで、むりくり継続的インテグレーションっぽいことをやってみました。色んな意味でこのレベルが最低限かなと思います~~（特にコーディングスキルが）~~。

今後は外部ツールを絡ませがら、よりリッチな継続的インテグレーションを試していきます。

#参考
Jenkins実践入門
http://gihyo.jp/book/2011/978-4-7741-4891-5

Ubuntu 14.04にjenkins 2.73.2をインストールする(OS上に直接)
https://qiita.com/Higemal/items/6b564cc10fbe2aeb5b17

Jenkins”だけ”でほんとうにできること
https://qiita.com/Higemal/items/bb9a0c12b8fca0dd6657