Concourse CIでiOSアプリのCIを行う

前に[SIの現場のiOSアプリケーション開発 \- Qiita](http://qiita.com/tenten0213/items/4099016c07ff99c93762)で書いたように、CIにはJenkinsを使っているのですが、特定メンバーがJenkins職人になりがちでツラみがあります。
せっかくfastlaneなどでビルドスクリプトをコード化出来ているので、ビルドパイプラインもコード化したい…！

ってことで[Concourse CI](https://concourse.ci/)を試してみました。

## Concourse CIのインストール

docker-composeでやりました。
以下の公式ドキュメント通りに行えばサクッと起動します。

* [Installing - Docker Repository](https://concourse.ci/docker-repository.html)

dockerでConcourse CIを構築して、iOSのビルド出来るのか？って心配になるかもしれませんが、Darwin用のworkerを利用することでiOSのビルドを行うことが可能です。

## workerの設定

以下から最新のconcourse_darwin_amd64をダウンロードしてきて、パスの通ったディレクトリに配置します。
https://github.com/concourse/concourse/releases

worker用の鍵の生成とauthorized_worker_keysへの追加を行います。

```bash
$ ssh-keygen -t rsa -f ./keys/worker/darwin_worker_key -N ''
$ cat ./keys/worker/darwin_worker_key.pub >> ./keys/web/authorized_worker_keys
```

Macホスト上でconcourse workerを起動します。

```bash
$ sudo concourse worker --work-dir /opt/concourse/worker --tsa-host 127.0.0.1 --tsa-public-key ./keys/worker/tsa_host_key.pub --tsa-worker-private-key ./keys/worker/darwin_worker_key
```

とりあえずこれでworkerが動きました。

```json
{"timestamp":"1487892702.682704926","source":"worker","message":"worker.garden.started","log_level":1,"data":{"session":"1"}}
{"timestamp":"1487892702.682797194","source":"baggageclaim","message":"baggageclaim.listening","log_level":1,"data":{"addr":"127.0.0.1:7788"}}
{"timestamp":"1487892702.683754444","source":"worker","message":"worker.beacon.restarting","log_level":2,"data":{"error":"failed to dial: failed to connect to TSA: dial tcp 127.0.0.1:2222: getsockopt: connection refused","session":"3"}}
```

2222番ポートで接続しようとしてエラーになっているので、docker-compose.ymlに設定を追加します。

```yaml:docker-compose.yml
concourse-web:
  image: concourse/concourse
  links: [concourse-db]
  command: web
  ports: ["8080:8080", "2222:2222"]
  volumes: ["./keys/web:/concourse-keys"]
  environment:
    CONCOURSE_BASIC_AUTH_USERNAME: concourse
    CONCOURSE_BASIC_AUTH_PASSWORD: changeme
    CONCOURSE_EXTERNAL_URL: "${CONCOURSE_EXTERNAL_URL}"
    CONCOURSE_POSTGRES_DATA_SOURCE: |-
      postgres://concourse:changeme@concourse-db:5432/concourse?sslmode=disable
```

どうやら繋がったようです。

```json
{"timestamp":"1487892892.915976048","source":"tsa","message":"tsa.connection.channel.forward-worker.register.start","log_level":1,"data":{"remote":"172.17.0.1:50078","session":"1.1.1.5","worker-address":"127.0.0.1:42459","worker-platform":"darwin","worker-tags":""}}
{"timestamp":"1487892892.928279877","source":"tsa","message":"tsa.connection.channel.forward-worker.register.reached-worker","log_level":0,"data":{"remote":"172.17.0.1:50078","session":"1.1.1.5","took":"10.962879ms"}}
```


## ビルドパイプラインの作成

立ち上がっているWebにアクセスし、

http://127.0.0.1:8080/

ビルドパイプライン設定用のCLIツールである`fly`をダウンロードします。

![Concourse.png](https://qiita-image-store.s3.amazonaws.com/0/6092/e93a62ae-cbde-5339-4f54-6cd217f2ccd8.png)

ダウンロードしたバイナリをパスが通っているディレクトリに配置しておきます。

とりあえず以下の3つを実行できるようにしてみます。

* GitHubからclone
* CocoaPodsで依存関係解決(fastlaneで)
* fastlaneでテスト実行

最終的なyamlは以下の通りです。
ビルドの実行ユーザはrootになるのですが、`pod install`がrootで実行できないのでパーミッションだったりユーザのスイッチだったりごにょごにょやっています。


* https://guides.cocoapods.org/using/troubleshooting.html#im-getting-permission-errors-while-running-pod-commands

```yaml:concourse.yml
resources:
  - name: ios-concourse
    type: git
    source:
      uri: https://github.com/tenten0213/ios-concourse.git
      branch: master
jobs:
  - name: build
    plan:
      - get: ios-concourse
        trigger: true
      - task: specs
        config:
          platform: darwin
          inputs:
            - name: ios-concourse
          run:
            path: sh
            args:
              - -c
              - |
                env
                mkdir ios-concourse/ExampleForConcourse/Pods
                chown -R $SUDO_USER ios-concourse/
                chown -R $SUDO_USER ~/Library/Caches/CocoaPods
                chown -R $SUDO_USER ~/.cocoapods
                cd ios-concourse/ExampleForConcourse
                sudo -u $SUDO_USER bundle exec fastlane test
```

パイプラインを登録して実行可能な状態にし、ビルドを実行すると…

```bash
$ fly -t ci login -c http://127.0.0.1:8080/
$ fly -t ci set-pipeline -p ios-concourse -c concourse.yml
$ fly -t ci unpause-pipeline -p ios-concourse
```

↓な感じでfastlaneが実行され、ビルドが成功しました！ヽ(=´▽`=)ﾉ
画像見れば分かる通り、ちゃんとビルド通すのに結構苦労しました…

![build__30_-_Concourse_と_1__tmux.png](https://qiita-image-store.s3.amazonaws.com/0/6092/1ce0c856-5bfb-30f6-c792-d2bdd25064e2.png)

試したモロモロは以下に置いてあります。

* https://github.com/tenten0213/ios-concourse

## 参考

* [パイプラインベースのCI/CDツール Concourse CI入門 \- BLOG\.IK\.AM](https://blog.ik.am/entries/379)
* [はじめてのConcourse CI \- BLOG\.IK\.AM](https://blog.ik.am/entries/380)
* [Using Concourse CI for building iOS and OSX apps – David Karlsson](http://www.davidkarlsson.no/2016/12/21/using-concourse-ci-for-building-ios-and-osx-apps/)
* [On\-Device Open Source CI and CD for Mobile Reinvented: Meet Concourse](https://content.pivotal.io/blog/on-device-open-source-ci-and-cd-for-mobile-reinvented-meet-concourse)