Amazon Device FarmをJenkinsCIに導入する

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

* [こちら](https://github.com/awslabs/aws-device-farm-jenkins-plugin)の手順のとおりやってみる

## Mavenのインストール

* [yumでインストールする手順](http://qiita.com/digdagdag/items/87fef7ce7c97be10bee1)
* [yumを使わない方法で参考にした手順](http://stackoverflow.com/questions/7532928/how-do-i-install-maven-with-yum) 
* ~/.bashrcに以下を追加
 * Javaのパスをご確認の上、設定してください

```
JAVA_HOME=/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.45.x86_64/jre
```

* proxy環境では以下のファイルを配置する(以下は記述例)
 * 詳しくは[こちら](http://maven.apache.org/guides/mini/guide-proxies.html)

```xml:~/.m2/settings.xml
    <settings>
      .
      .
      <proxies>
       <proxy>
          <id>example-proxy</id>
          <active>true</active>
          <protocol>http</protocol>
          <host>proxy.example.com</host>
          <port>8080</port>
          <username>proxyuser</username>
          <password>somepassword</password>
          <nonProxyHosts>www.google.com|*.example.com</nonProxyHosts>
        </proxy>
      </proxies>
      .
      .
    </settings>
```

## プラグインのビルド

* 以下を実行する
 * target/aws-device-farm.hpiが生成される

```
$ git clone git@github.com:awslabs/aws-device-farm-jenkins-plugin.git
$ cd aws-device-farm-jenkins-plugin
$ make clean compile
```

## Jenkinsにプラグインをインストール
1. 「Jenkinsの管理」⇒「プラグインの管理」⇒「高度な設定」を選択する
1. プラグインのアップロードでaws-device-farm.hpiを選択してアップロードする
 * ![harumi_jenkins.png](https://qiita-image-store.s3.amazonaws.com/0/19778/f29c660c-12b6-fad3-94cb-998fe67d7986.png)
 * ![harumi_jenkins2.png](https://qiita-image-store.s3.amazonaws.com/0/19778/0537f43e-cf35-0629-7adb-1ca6c4f896ad.png)
1. Jenkinsを再起動する

# AWS側の設定
## 設定
1. AWSマネージメントコンソールにログイン後して「Identity & Access Management」を選択する
 * ![harumi_aws.png](https://qiita-image-store.s3.amazonaws.com/0/19778/7e07ecaf-45f8-6b33-f9c4-39cd1333b193.png)
1. 左側の項目の「ユーザー」を選択する
 * ![harumi_aws2.png](https://qiita-image-store.s3.amazonaws.com/0/19778/df09fca4-9b0d-0bc3-f43f-862c8e43de18.png)
1. 「新規ユーザーの作成」を選択する
 * ![harumi_aws3.png](https://qiita-image-store.s3.amazonaws.com/0/19778/1e78a0d8-6ca6-8aee-bfdb-6b0f33f63351.png)
1. ユーザー名を入力して、"ユーザーごとにアクセスキーを生成"にチェックが入っていることを確認して作成する
 * ![harumi_aws4.png](https://qiita-image-store.s3.amazonaws.com/0/19778/d5b7aec0-955a-3df4-8dda-f778aba8a8d7.png)
1. ポリシーを以下のように設定する
 * ![iam.png](https://qiita-image-store.s3.amazonaws.com/0/19778/56dc6766-1712-34e5-eefb-419718553c4a.png)

# Jenkins側の設定
## システムの設定
1. Jenkinsにログインして、「Jenkinsの管理」⇒「システムの設定」を選択する
1. 画面下部にある"AWS Device Farm"のところにあるAKIDとSKIDを入力して保存する
    * ![harumi_jenkins4.png](https://qiita-image-store.s3.amazonaws.com/0/19778/6d6e316d-712a-a214-8d2d-19d1ea4f37ef.png)
        * AKID/SKIDがご不明な方は[こちら](http://docs.aws.amazon.com/ja_jp/AWSSimpleQueueService/latest/SQSGettingStartedGuide/AWSCredentials.html)をご覧ください

## Jenkinsジョブの設定
1. AmazonDeviceFarmを使いたいジョブを選択して、「設定」を選択する
1. 「ビルド後の処理の追加」⇒「Run Tests on AWS Device Farm」を選択する
1. 以下のように設定する(ここでは対象のテストにFuzzテストを選択した)
 * ![devicefarm.png](https://qiita-image-store.s3.amazonaws.com/0/19778/926fc8e0-d07b-677c-1309-cc9eddfb14f5.png)
 * Project・・・DeviceFarmで作成したプロジェクトを選択する
 * DevicePool・・・作成したDevicePoolがあればそれをなければTop Devicesを選択する
 * Application・・・apkファイルの場所を指定する(例えば、*.apkなどでも可)
 * Choose test to runでBuilt-in Fuzzを選択する
 * Event Count/Event Throttle/Seedは指定しなくても実行できる(詳細はDeviceFarmを参照)

### プロキシ下では使えない？？
* 正確に言えば、ジョブの設定で入力すべきProject/DevicePoolが選択肢に何もでてこなかった
 * EC2上で同じことを試みると、作成したProject/DevicePoolは表示されていた
* [プロキシの設定](https://wiki.jenkins-ci.org/display/JENKINS/JenkinsBehindProxy)付きで再起動をしてもダメだった
* 認証プロキシだからダメなのかと思ってsquidを使ったもので試したけどダメだった
* ※　~~回避策がみつかったら追記します~~ → 使えるようにはなったので下に追記します

### プロキシ環境下で使う方法
* これを試しているうちに、「というかAmazonのサービスだからEC2使えよという話だよな・・・」と思いましたが見てみることに
* Jenkinsの設定で以下のプロキシの設定を試したのですがダメ、つまりはプラグイン側でプロキシに対応するようにしないといけない
 * システムの環境変数定義
 * 起動オプションにプロキシ設定追加
* 仕方なくjava不慣れな僕がコード見てみることに^^;
* こんなのやったよというのを書きます
* ```$ mvn clean compile```する前に以下のコードを追加しておきます。以上です

```java:src/main/java/org/jenkinsci/plugins/awsdevicefarm/AWSDeviceFarm.java
 49     /**
 50      * Private AWSDeviceFarm constructor. Uses the roleArn to generate STS creds if the roleArn isn't null; otherwise
 51      * just uses the AWSCredentials creds.
 52      * @param creds AWSCredentials creds to use for authentication.
 53      * @param roleArn Role ARN to use for authentication.
 54      */
 55     private AWSDeviceFarm(AWSCredentials creds, String roleArn) {
 56         if (roleArn != null) {
 57             STSAssumeRoleSessionCredentialsProvider sts = new STSAssumeRoleSessionCredentialsProvider
 58                     .Builder(roleArn, RandomStringUtils.randomAlphanumeric(8))
 59                     .build();
 60             creds = sts.getCredentials();
 61         }
 62 
 63         ClientConfiguration clientConfiguration = new ClientConfiguration().withUserAgent("AWS Device Farm - Jenkins v1.0");
 64         //以下２行を追加
 65         clientConfiguration.setProxyHost("[プロキシホスト]");
 66         clientConfiguration.setProxyPort([プロキシポート]);
 .
 .
 .
323     private Upload upload(File file, Project project, AWSDeviceFarmUploadType uploadType, Boolean synchronous) throws IOException, AWSDeviceFarmException {
324         CreateUploadRequest appUploadRequest = new CreateUploadRequest()
325                 .withName(file.getName())
326                 .withProjectArn(project.getArn())
327                 .withContentType("application/octet-stream")
328                 .withType(uploadType.toString());
329         Upload upload = api.createUpload(appUploadRequest).getUpload();
330         //CloseableHttpClient httpClient = HttpClients.createDefault(); この行を以下の４行のように変更する
331         CloseableHttpClient httpClient = HttpClients.custom()
332                 .useSystemProperties()
333                 .setProxy(new HttpHost("[プロキシホスト]", [プロキシポート]))
334                 .build();
335 
336         HttpPut httpPut = new HttpPut(upload.getUrl());
```



# 実行結果
## DeviceFarm
![result.png](https://qiita-image-store.s3.amazonaws.com/0/19778/bbba16ab-cf19-21e4-5483-6b6ab9474dee.png)


## Jenkins
![result2.png](https://qiita-image-store.s3.amazonaws.com/0/19778/3fd2de79-7114-f8c6-d20e-140c91c912f5.png)

* ジョブのトップから結果が閲覧できる

## 補足

* DeviceFarmのテストで失敗するとJenkinsのビルド結果も**失敗**として扱われます


----

# ～ただの宣伝～
* [全国のSeleniumer必読](http://qiita.com/oh_rusty_nail/items/b8ba525d31ea7c522856)
* Selenium, SauceLabs, Travis, Jenkinsに関するノウハウ書いているのでよかったら参考にしてみてください