GitlaberのためのAndroid Dockerベース CI

Gitlover ではありません． [Gitlab](https://about.gitlab.com/)erです．

# Gitlabについて

　みなさん，仕事で使っているのは Github Enterpriseでしょうか？
　Gitlab，ご存知ですか？
　[成長期の評判](http://www.slideshare.net/takafumionaka/is-there-anynecessityofusinggithubenterprise#9) だったり，例のアイコンだったり，Githubクローン（単刀直入に言うと劣化版Github）というちょっとネガティブなイメージがあるかもしれません．
![image](https://qiita-image-store.s3.amazonaws.com/0/51949/fabc9247-3432-3273-08ab-44c562f11ae4.png)（例のアイコン．いまのはこんなに眼力強くない）
　弊社ではGHEの利用価格と運用コスト（GHEでも運用費用はゼロにはならない）とGitlab Community Editionの運用コストを比較した結果，Gitlab CEが採用されることになりました．

（当時は要求していたGHEが通らず消沈していた記憶が…）

# コンテナベースCI

　Androidに限った話ではないのですが，JenkinsからTravis CIやらCircle CIといったコンテナベースCIが普及してきました．Jenkinsはビルドジョブ設定がリポジトリと乖離してしまうために版管理ができないというデメリットや，特定のプラグインへの依存，UIによるジョブ設定のための属人化，クリーンなCI環境の維持の難しさが課題となっていました．
　そこに風穴を開けたのがコンテナベースCIと呼ばれる技術でしたが， [まだ CircleCI で消耗してるの？](http://qiita.com/KeithYokoma/items/b839ef3f5496a22f3e7a) という話もあり Wercker が台頭してきました．
　Werckerもコンテナベースではあるのですが， Dockerコンテナ上で動作させることができますので，最新の Android SDK を使ってCIしたい場合も，Circle CIのようにサービス側の対応を待つ必要もなく，ymlにSDKのアップデート処理を埋め込んで，CIのたびにSDKのアップデートから始まるということもありません．

# 会社がうるさい

　いやぁ，それでもセキュリティ面，価格面がキビシイ会社はまだまだあります．

- Wercker？ 価格は？ $350？ 安いね
    - え？ 並列実行が制限されるの？
    - え？ クラウドにソースコード出すの？
    - え？ DockerfileもDockerHubにだすの？
    - えー…

めんどくさいので，社内にDockerベースCIを立ててしまうことにしましょう！

# Gitlaberだけにできる選択

- Gitlab
- Gitlab CI Runner
- Gitlab Container Registry

## [Gitlab](https://docs.gitlab.com/)

　Gitlab の説明は，まぁ，不要ですよね．
　Githubみたいなものです．
　バージョン8系よりCI機能がGitlabに統合され，Gitlab CIの設定も行えるようになりました．
　ただし，実際にCIする環境はGitlabとは別に用意する必要があります．

## [Gitlab CI Runner](https://docs.gitlab.com/runner/)

　それがこの[Gitlab CI Runner](https://docs.gitlab.com/runner/)と言われるやつです．
　GitlabからCI命令を受け，実際にビルドを走らせる環境です．
　gitlab.com では [Shared Runnerという共用サーバが提供されています](https://about.gitlab.com/2016/04/19/gitlab-partners-with-digitalocean-to-make-continuous-integration-faster-safer-and-more-affordable/) が，自前でGitlab立てている場合はRunnerも自前で用意する必要があります．

### [Gitlab CI Runner Executor](https://docs.gitlab.com/runner/#selecting-the-executor)

　RunnerにはいくつかのExecutorを指定することができます．
　Executorとは，CIを実際に動かすベース環境といえば良いのでしょうか．良い表現が浮かびませんが，聞いてもらったほうがわかりやすいので，とりあえず代表的なものを紹介します．
　ひとつのRunnerに対して，複数のExecutorを指定することはできますが，副作用がある気がするのであまりお勧めできません．

#### [Docker](https://docs.gitlab.com/runner/executors/docker.html)

　Werckerのように，DockerベースでCIすることができます．
　DockerHubなどでAndroidのDockerイメージが共有されていればそのまま使えますが， [AndroidSDKを含めたDockerイメージの公開はライセンス的に問題がある](http://gfx.hatenablog.com/entry/2016/06/21/112404) という話もあるので，後述する Gitlab Container Registry と併せて使います．

#### [Shell](https://docs.gitlab.com/runner/executors/shell.html)

　Jenkinsのように，そのRunnerの環境上でCIを実行します．
　通常，Dockerイメージの用意できないWindowsやMac上でのCIで使えると思いますが，ドキュメントには一般的にShellでの実行はセキュリティリスクがあると [書かれています](https://docs.gitlab.com/runner/executors/shell.html#security)

#### [VirtualBox](https://docs.gitlab.com/runner/executors/virtualbox.html)

　Runnerの中にVirtualBoxでVMを立てて，その中でCI？
　使い捨てのWindows環境が欲しい場合とかに有用？

#### [SSH](https://docs.gitlab.com/runner/executors/ssh.html)

　RunnerからリモートサーバへSSH接続して，リモートサーバ上でCIします．
　使いみちは…？

まぁ，ほとんどはDockerで事足りると思います．
gitlab.comのShared RunnerもDocker Executorです．

# Gitlab Container Registry

　プライベートなDockerHubのようなものです．
　Dockerイメージの管理は，別途 [Docker Registry](https://docs.docker.com/registry/) を動かして管理されます．
　Gitlab Container RegistryはDocker RegistryとGitlabの接続とUIを提供します．

# Gitlab CI 全体の流れ

- GitlabにDockerImage管理用プロジェクトを立てる
- Dockerfileと `.gitlab-ci.yml` に記述したビルド設定を配置する
    - Gitlab CI Runner上でDockerイメージがビルドされ，Container Registryに登録される
- Androidプロジェクトを立てる
- `.gitlab-ci.yml` に Androidのビルドを記述する
    - 上のDockerイメージを用いるようにする
- オリジナルDockerイメージを使ってCIできる．

DockerイメージとAndroidリポジトリを結びつけるなら，Dockerイメージリポジトリをsubmoduleでリンクさせるのがベストでしょうか．

# Gitlab + Gitlab CI Runner + Docker Registryの導入

カット（あまりにもAndroidからかけ離れてしまう＆Gitlab CI RunnerのコンテナとRegistryが接続できずに詰まってる）
別記事として書く予定です．
今回はgitlab.comを使います

（追記）
私が書くまでもなく，Gitlab Advent Calendarで記事化してくれた方がいらっしゃいました．
http://qiita.com/masakura/items/0a0f00dfdddc8ce27f29
ただし，今回のようにGitlab CI Runner上でDockerベースCI（Docker in Docker）を行うには，Registryと正規SSL証明書で通信できるようにする必要がありそうです．

# Dockerイメージの作成

## Dockerfile管理用リポジトリを作成

[gitlab.com](https://gitlab.com/) でDockerfileの管理用リポジトリを作成します．
今回は名前を `android-container` としています．
ライセンスの問題があるので，このプロジェクトはprivateとしてください．

### `.gitlab-ci.yml` ファイルを追加

`.gitlab-ci.yml` というファイルにビルドスクリプトを記述すると，Gitlab CI Runnerがそのとおりにビルドしてくれます．
gitリポジトリを作って，その中に `.gitlab-ci.yml` を作ってpushしても良いのですが，面倒なのでここは gitlab.com 上から作ってしまいます．
New Fileで　`.gitlab-ci.yml` とファイル名を入力すると，右にテンプレートが選べるようになりますので，Dockerを選択してテンプレのままコミットします．

![image](https://qiita-image-store.s3.amazonaws.com/0/51949/9f4d3cae-8a29-3908-68c9-cc5d70a3c004.png)

```yaml:.gitlab-ci.yml
# This file is a template, and might need editing before it works on your project.
# Official docker image.
image: docker:latest

services:
  - docker:dind

build:
  stage: build
  script:
    - docker login -u "gitlab-ci-token" -p "$CI_BUILD_TOKEN" $CI_REGISTRY
    - docker build --pull -t "$CI_REGISTRY_IMAGE:$CI_BUILD_REF_NAME" .
    - docker push "$CI_REGISTRY_IMAGE:$CI_BUILD_REF_NAME"
```

コミットした瞬間からCIが走りますが，まだDockerfileがないので，ビルドは当然失敗します．

![image](https://qiita-image-store.s3.amazonaws.com/0/51949/a3f87e6b-bcd0-bb72-000c-f6e82a872226.png)

## Dockerfile 追加

@gfx さんがMIT Licenseで[公開してくださってるDockerfile](https://github.com/gfx/docker-android-project/blob/master/Dockerfile) をお借りします．
これをそのまま `.gitlab-ci.yml` と同じ場所に配置してコミットします．
コミットすると自動的にDockerイメージのビルドが走り，Registryに登録されます．

![image](https://qiita-image-store.s3.amazonaws.com/0/51949/fbe28e6b-96f4-b194-0fa6-b3b59e437b57.png)

# Android リポジトリの作成

すでにAndroidリポジトリがあれば，それを新しく作ったプロジェクトにコミットして構いません．
今回はDockerfile同様横着させていただいて， [giltab-ci-shared-runner-android-example](https://gitlab.com/greysonp/gitlab-ci-shared-runner-android-example) をForkさせてもらいます．

## .gitlab-ci.yml 修正

ForkしたプロジェクトにはすでにFork元で作られた `.gitlab-ci.yml` があります．
手持ちのAndroidプロジェクトをコミットした場合は， `.gitlab-ci.yml` を追加してください．

```yaml:.gitlab-ci.yml
image: registry.gitlab.com/greysonp/gitlab-ci-shared-runner-android-example:latest

before_script:
  - chmod +x ./gradlew

build:
  script:
    - ./gradlew assembleDebug
  artifacts:
    paths:
    - app/build/outputs/
```

Fork元はこうなっています．
特別なことはしていませんね．debugビルドして，成果物を指定しています．
このymlで指定されているimageを，今回自分で作ったイメージに切り替えます．

`image: registry.gitlab.com/tetsukay/android-container:master`

コミットすると，Andoidプロジェクトのビルドが走ります．

![image](https://qiita-image-store.s3.amazonaws.com/0/51949/ae99bf2b-740b-cb2f-719b-417a09f34053.png)

というわけで，無事ビルドに成功しました．
Gitlabを使っている方はGitlab CI，試してみてはいかがでしょうか．

# さいごに

Android成分が少なめですみません．
Gitlabへの印象は，私自身最初はやはり良い印象はありませんでした．
導入から4年ほど立ちましたが，毎月20日頃のメジャーアップデートをはじめとした進化速度や，Gitlab CI，Docker Registry連携など，欲しい機能がどんどん追加され，今では本当に素晴らしいツールに進化したと思います．
いろいろなしがらみで社内のGitlab + JenkinsでCIしている方も多いと思いますが，ぜひGitlab CIを試してみてください．