GitLab CI RunnerをMac上に構築する

# はじめに

iOSアプリのCIを実現する手段としてはCircleCIやTravisCIなどのSaaSビルドツールを使う他に、JenkinsやGitLab CIのAgentとして自前のMacを使う方法があります。

本記事ではGitLab CI RunnerをMac端末上にインストールして動作させる手順をまとめます。
基本的には[ドキュメント](https://docs.gitlab.com/runner/install/osx.html)の手順通りにやるだけですが、ところどころ詰まったところをメモとして補足します。

# 前提

GitLab CI Runner on Macはgitlab.comでも自前構築のgitlab ceでも実現可能です。

# GitLab CI RunnerをMacにインストールする

GitLab CI Runnerのバイナリファイルをダウンロードします。

```sh
# Install gitlab-runner
$ sudo curl --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/latest/binaries/gitlab-runner-darwin-amd64
```

デフォルトのコマンドだと`latest`のバージョンがダウンロードされます。GitLabのバージョンと整合性をあわせるために、メジャーバージョンがそろったものを入れたい場合は、`latest`のところをダウンロードしたいバージョンのタグに置き換えるとよいでしょう。

```sh
# Install gitlab-runner
$ sudo curl --output /usr/local/bin/gitlab-runner https://gitlab-runner-downloads.s3.amazonaws.com/v11.11.4/binaries/gitlab-runner-darwin-amd64
```

タグの一覧は[こちら](https://gitlab.com/gitlab-org/gitlab-runner/-/tags)から確認ができます。

次にダウンロードしたバイナリに実行権限を付与します。

```sh
# set permission
$ sudo chmod +x /usr/local/bin/gitlab-runner

# check gitlab-runner command
$ gitlab-runner --version
Version:      12.0.2
Git revision: d0b76032
Git branch:   
GO version:   go1.8.7
Built:        2019-07-07T00:39:54+0000
OS/Arch:      darwin/amd64
```

# GitLab CI RunnerをGitLabに登録する

次にGitLab CI Runnerを対象のGitLabに登録します。

このとき順番にインタラクティブに以下が聞かれるので、事前に準備しておきましょう。

- GitLabのホスト名(coordinator URL)
- GitLab CIの連携用のトークン(token)
- GitLab CI Runnerの名前(description)
- GitLab Runnerのタグ名(tag)
- 実行形態(executor)

tokenはGitLabのサイト上で確認することができます。以下のRunnerの種類によってtokenが異なるので、用途にあったものを確認しておきましょう。

- Shared Runners
  - RunnerをGitLabホスト内で共有する。
- Group Runners
  - 特定のGitLab Group内のプロジェクト専用のRunnerにする 
- Specific Runners
  - 特定のレポジトリ専用のRunnerにする

トークンはそれぞれSettings->CI/CD->Runnersの中で確認することができます。また管理権限のユーザがアクセスできるadmin areaでも確認ができます。

次に上記の情報をもとにRunnerを登録してきます。Macでビルドする場合は実行形態は`shell`を選択します。

```sh

# Register GitLab
$ gitlab-runner register

# GitLabのホスト名を入力
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/):
https://gitlab.com/ 

# 連携用tokenをを入力
Please enter the gitlab-ci token for this runner:
xxxxxxxxx

# GitLab CI Runnerの名前を入力
Please enter the gitlab-ci description for this runner:
yyyyyyyyyy.local: takami228-mac-gitlab-runner

# タグ名を入力
Please enter the gitlab-ci tags for this runner (comma separated):
mac-ci-runner 

Registering runner... succeeded                     runner=zzzzzz

# 実行形態を入力
Please enter the executor: ssh, virtualbox, docker+machine, docker-ssh+machine, parallels, shell, kubernetes, docker, docker-ssh:
shell

Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded! 
```

実行が完了すると、homeディレクトリのroot配下に`.gitlab-runner/config.toml`が出来上がります。

```toml
concurrent = 1
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "takami228-mac-gitlab-runner"
  url = "https://gitlab.com/"
  token = "xxxxxxxxxx"
  executor = "shell"
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
```

# GitLab Runnerを起動する

以下のコマンドでGitLab Runnerを起動します。

```sh
$ gitlab-runner install
Runtime platform arch=amd64 os=darwin pid=17304 revision=d0b76032 version=12.0.2

$ gitlab-runner start
Runtime platform arch=amd64 os=darwin pid=17318 revision=d0b76032 version=12.0.2

$ gitlab-runner status
Runtime platform arch=amd64 os=darwin pid=17337 revision=d0b76032 version=12.0.2
gitlab-runner: Service is running!
```

上記を実行したら、Runnersの設定画面の`Runners activated for this project`の英数文字列の横が緑色になることを確認します。

また`lauchctl`コマンドでgitlab-runnerがlaunchdに登録されていることがわかります。

```sh
$ launchctl list | grep "gitlab"
xxxx    0    gitlab-runner
```

# 実行結果を確認する。

テストレポジトリを作成し、以下の`.gitlab-ci.yml`を作成し正しく動作していることを確認します。tagsのところでGitLab CI Runnerのtagsを指定することで特定のRunner上で実行させることができます。

```yml
build:
  stage: build
  tags:
    - mac-ci-runner 
  script:
    - uname -n
    - echo "hello"
```

テストレポジトリのCI/CDのところのPipelinesのところでRun Pipelinesを実行するとジョブが実行されます。
無事以下のような結果が得られ、Mac上でshellコマンドが実行されていることが確認できました。

```
Running with gitlab-runner 12.0.2 (d0b76032)
  on test zzzzzzz
  Using Shell executor...

  Running on takami228noMac-mini.local...

  Fetching changes with git depth set to 50...
  Initialized empty Git repository in /Users/takami228/builds/xxxx/0/takami228/gitlab-ci-test/.git/
  Created fresh repository.
  From https://gitlab.com/takami228/gitlab-ci-test
   * [new branch]      master     -> origin/master
  Checking out 251869d7 as master...
  Skipping Git submodules setup

  $ uname -n
  yyyyyyyyyyyyyy.local
  $ echo "hello"
  hello

Job succeeded
```

あとはRunnerのMac上にXcodeやPod、SwiftLint等の実行させたいコマンドをインストールし、`.gitlab-ci.yml`に`swiftlint`や`xcodebuild`などのコマンドを記載すればiOSのCI/CDを実現することができます。

# ハマったところ

[公式のドキュメント](https://docs.gitlab.com/runner/register/index.html)の上部ではGNU/Linuxの手順が紹介されており、そこでは`sudo`権限で設定する手順になっています。

sudo権限でgitlab-runner registerを実行するとroot権限でconfig.tomlが作成され、root権限でしアクセスできない場所に置かれます。

そのためgitlab-runnerの実行もsudo権限が必要になります。

iOSではライブラリの依存関係解決にPodを使うのですが、このPodはroot権限では実行できないというエラーに遭遇し、手順に間違えていることに気づきました。インストール時の権限設定には注意してください。

```sh
$ sudo pod install
/usr/local/Cellar/cocoapods/1.6.1/libexec/gems/claide-1.0.2/lib/claide/command.rb:439:in `help!': [!] You cannot run CocoaPods as root. (CLAide::Help)
```

# おまけ

GitLab CEに内包されているMattermostも利用している場合は、通知連携することでGitLab CIの実行結果を毎回Mattermostへ通知させることができます。連携については[こちら](https://qiita.com/takamii228/items/a0f4b2ef8107d6d3cd34#4-gitlab%E5%81%B4%E3%81%AEmattermost%E8%A8%AD%E5%AE%9A)を参考にしてください。

# 参考文献

- [https://docs.gitlab.com/runner/](https://docs.gitlab.com/runner/)
- [https://docs.gitlab.com/runner/install/osx.html](https://docs.gitlab.com/runner/install/osx.html)
- [https://docs.gitlab.com/runner/install/bleeding-edge.html](https://docs.gitlab.com/runner/install/bleeding-edge.html)
- [https://qiita.com/takamii228/items/a0f4b2ef8107d6d3cd34](https://qiita.com/takamii228/items/a0f4b2ef8107d6d3cd34)