Developer's Blog

Jenkins はもうオワコン? Concourse CI で iOS 向けビルドをやってみた



忙しい人向けのまとめ

Concourse CI は Docker による構築が容易で、CLI による処理を自動化出来ますが、シンプルなUIしか持っていません。
そのため、Jenkins のように特定の個人に依存することなく、分散化した自動化のためのプラットフォームとして有望です。
モバイルアプリのビルドにも使えるので実際に試してみました。

Jenkins は最高! そう考えていた時期が俺にもありました

こんにちは、普段は iOS 向けのアプリを作っている森本です。

弊社では、以前よりアプリのビルドを始め定型作業の内、自動化出来るものを Jenkins で行うこととしております。

そもそもの導入の目的は、提供するアプリの品質を安定させるため、環境が変化しやすい個人の端末ではなく、特定のビルド専用機でビルドを行う必要があり、それを実施できる WebUI が欲しい、というところにありました。

導入当初の印象は、

  • Cron みたいに設定がややこしくない😁
  • Web UI からいろんな設定が変更できて便利😆
  • ビルド環境をうっかり変更してしまうことがなくて安心😊

といった感じでした。

そして、時は流れ、メンバーも増え、Jenkins の利用者も大きく増えた結果、現在ではこのようになりました。

  • 設定の項目が多い上、変更のヒストリーがないから訳がわからなくなる😑
  • Jenkinsfile も情報が少ないし期待している機能とズレが有る😩
  • 常に全員が求めているビルド環境を構築するのが辛い。維持するのも辛い・・・😶

結果として、Jenkins 道に長けた特定の人間に管理を依存することとなり、昨日の投稿のように、苦難に満ちた運用を強いられています。

辛い旧環境Jenkins

一体、どうしてこうなってしまったんだ・・・

Concourse CI との出会い

と言うわけで、なんかもっとシンプルでハッピーになれる CI ツールは無いものか、といろいろ探していた最中、良さそうなものを見つけたので紹介しよう、というのが本記事となっております。

今回、試しに動かしてみるのは Concourse CI という、 OSS で開発されているソフトウェアです。

特徴としては、

  • GoLang で書かれており軽量に動作する
  • マイクロサービス化されたシンプルな構成
  • Docker 時代に適応しており、環境を簡単に構築できる
  • Docker 内だけではなく、ネイティブ環境で作業させることも出来る

などがあり、目的に近い様に思われます。
とはいえ実際に目で見るまでは信じられないので、期待を胸に秘めつつ、実際に動かしていきます。

Concourse CI 基本部分のインストール

今回は、公式のドキュメント に従ってセットアップしていくことになります

インストールの方法はいくつかありますが、現状では Docker Compose を使うのが非常に楽なので、この方法で進めていきます。

docker と docker-compose がインストールされてない、という方は 公式サイト からダウンロードするか、Homebrew を使って下記のような感じでインストールしておいて下さい。

brew update
brew install docker-compose
brew cask install dockertoolbox

Docker の準備が整ったはずなので、ターミナルから適当なディレクトリを作成してセットアップ作業を開始します。

mkdir concourse_native_trial
cd concourse_native_trial

認証情報の作成

まず、今回の構成では、DB、Web サーバー、linux の Worker、ネイティブの Worker、4つの独立した環境が連携して動作するため、お互いを識別するための認証情報を作成する必要があります。

ちなみに、上記の内、ネイティブの Worker のみがローカル環境で動作し、それ以外は Docker 内の環境で動作することとなります。

mkdir -p keys/web keys/worker

ssh-keygen -t rsa -f ./keys/web/tsa_host_key -N ''
ssh-keygen -t rsa -f ./keys/web/session_signing_key -N ''

ssh-keygen -t rsa -f ./keys/worker/worker_key -N ''
ssh-keygen -t rsa -f ./keys/worker/darwin_worker_key -N ''

cat ./keys/worker/worker_key.pub >> ./keys/web/authorized_worker_keys
cat ./keys/worker/darwin_worker_key.pub >> ./keys/web/authorized_worker_keys

cp ./keys/web/tsa_host_key.pub ./keys/worker

上記では、公式のものに加えて、ネイティブの Worker 向けの認証情報を作っている点に注意が必要です。

docker-compose.yml の作成

認証情報が作成できたら、引き続きこのディレクトリ内に、好みのエディタを使って下記のような内容の docker-compose.yml を作成します。

version: '3'

services:
  concourse-db:
    image: postgres:9.5
    environment:
      POSTGRES_DB: concourse
      POSTGRES_USER: concourse
      POSTGRES_PASSWORD: changeme
      PGDATA: /database

  concourse-web:
    image: concourse/concourse
    links: [concourse-db]
    depends_on: [concourse-db]
    command: web
    restart: unless-stopped
    ports: ["8080:8080", "2222:2222"]
    volumes: ["./keys/web:/concourse-keys"]
    environment:
      CONCOURSE_EXTERNAL_URL: "${CONCOURSE_EXTERNAL_URL}"
      CONCOURSE_BASIC_AUTH_USERNAME: concourse
      CONCOURSE_BASIC_AUTH_PASSWORD: changeme
      CONCOURSE_POSTGRES_HOST: concourse-db
      CONCOURSE_POSTGRES_USER: concourse
      CONCOURSE_POSTGRES_DATABASE: concourse
      CONCOURSE_POSTGRES_PASSWORD: changeme

  concourse-worker:
    image: concourse/concourse
    privileged: true
    links: [concourse-web]
    depends_on: [concourse-web]
    command: worker
    volumes: ["./keys/worker:/concourse-keys"]
    environment:
      CONCOURSE_TSA_HOST: concourse-web

このファイルさえあれば、 Docker のイメージを3つ一気に作成し、実行状態にすることが出来ます。便利な時代になったものですね・・・

あと、YAML 内にパスワードが埋まっているので、ちゃんと使う時はパスワードを忘れずに変更するようにしましょう。

起動

そしておもむろに、下記コマンドでコンテナを作成し起動します。

docker-compose up

ログの流れが落ち着いてきたら、ブラウザで http://127.0.0.1:8080/ にアクセスし、下記のような画面が出たら成功です。

Concourse CI 画面

右上にある「login」から、docker-compose.yml に書いたパスワードでログインできます。そして、もちろん中身は空っぽとなっています。

Concourse コマンドのインストール

さて、次に Concourse 関連のコマンドをインストールしていきます。

Concourse はコマンドラインから設定を変更できる(と言うかwebからは出来ない)という、割り切った仕様となっているので、この作業は必須となります。

同時にビルド用のネイティブ Workerを作るため、コンパイル済みのシングルバイナリ版の Concourse もセットアップします。

どちらも Concourse CI の GitHub にあるので、ダウンロードした後、パスを通せば OK です。
参考として、下記に手順を置いておきますが、環境と好みに応じて適当な方法で入れて下さい。

sudo mkdir /usr/local/concourse
sudo chown (ユーザー名):(ユーザーグループ) /usr/local/concourse

cd /usr/local/concourse

curl -L -O https://github.com/concourse/concourse/releases/download/v3.3.1/concourse_darwin_amd64
ln -s ../concourse/concourse_darwin_amd64 /usr/local/bin/concourse

curl -L -O https://github.com/concourse/concourse/releases/download/v3.3.1/fly_darwin_amd64
ln -s ../concourse/fly_darwin_amd64 /usr/local/bin/fly

concourse と fly コマンドがインストールできたところで、作業用ディレクトリに戻って作業を継続します。

この concourse コマンドは、単体で動作するようにビルドされたもので、これだけでもほぼ全機能を使用できます。

しかし、今回はネイティブ環境でビルドがしたいだけなので、下記のようにして Worker として動作させます。

concourse worker --work-dir ./working \
  --tsa-host 127.0.0.1 \
  --tsa-public-key ./keys/worker/tsa_host_key.pub \
  --tsa-worker-private-key ./keys/worker/darwin_worker_key

tsa.connection.channel.forward-worker.register.done を含むログが出ていれば接続に成功しているはずです。

Xcode を使ったビルドを試してみる

いつもお世話になっている通信系の大人気ライブラリ Alamofire をビルドしてみようと思います。

build_trial.yml の作成

まず、下記内容を build_trial.yml として保存します。

resources:
  - name: Github-Alamofire
    type: git
    source:
      uri: https://github.com/Alamofire/Alamofire.git
      branch: master
jobs:
  - name: build
    plan:
      - get: Github-Alamofire
        trigger: true
      - task: specs
        config:
          platform: darwin
          inputs:
            - name: Github-Alamofire
          run:
            path: sh
            args:
              - -c
              - |
                cd Github-Alamofire
                xcodebuild -workspace Alamofire.xcworkspace -scheme Alamofire\ iOS -configuration Debug build

pipeline の登録と手動実行

次に下記のように、コマンドラインからサーバーにログインします。
パスワードは docker-compose.yml にあるやつを使って下さい。

fly -t sample login -c http://127.0.0.1:8080/

ログインできたので、そこに先程作った YAML を追加します。

fly -t sample set-pipeline -p build_trial -c build_trial.yml

すると、前回の内容との差分を教えてくれて、更新していいか尋ねられます。こういう部分は利用者の気持ちがよくわかっていて素晴らしい。

そして、web を更新すると、team main に build_trial という pipeline が追加されているはずです。

Concourse CI 画面

pipeline はデフォルトで無効化されているので、 web の左ペインにある build_trial pipeline の左の▶ボタンを押して有効化する必要があります。

そして、右ペインにある「build」部分をクリックし、右上にある+ボタンを押すと手動で pipeline を開始させることが出来ます。

Concourse CI 画面

「>_ specs」の行をクリックするとコンソールログも確認する事ができるので経過を眺めることも出来ます。

今回は、成果物を送る先のサーバーがまだ出来ておらず、これ以上の作業はしないため、成果物は concourse_native_trial/working 以下のフォルダの奥の方から拾ってくる必要があります。

しかし、もちろん、成果物を他の git に push したり、ftp にアップロードしたりも出来ますし、定期的なポーリングやプルリクエストをトリガとして動作させることも出来ます。

build_trial.yml を見てもらえば分かるかと思いますが、同様の方法で任意のコマンドを実行できるので、Fastlane を使うのも良いですし、Gradle から Android のビルドにつなげるのも容易に行うことが出来ます。

ここまで読んで頂いたありがたい方向けのまとめ

これまで見てきたように、Concourse CI は Jenkins のように誰でもが全機能を触れる、と言った趣ではなく、ちゃんと知識を持った人間が、少ない労力で、大規模な自動化処理を、安定的に実行出来る、という部分に強みがあるように思えます。

何より、シンプルで軽量で構築も簡単、操作が全部 CLI、というあたりが個人的には響いているところです。

というわけで、現在 Jenkins で行われている作業の内、アプリのビルドなどはフローが共通化しやすく、メリットも大きい部分なので、このような部分から段階的に導入を進めていけたらなー、と考えている次第です。

Jenkins はデファクトスタンダードとなっていますが、それを使って仕事を自動化したつもりが、いつの間にか自分たちが Jenkins のための歯車になっていることに気付いて悲しい思いをしたりする前に、皆様も Concourse CI の導入を検討してみるのはいかがでしょうか。



フェンリルのオフィシャル Twitter アカウントでは、フェンリルプロダクトの最新情報などをつぶやいています。よろしければフォローしてください!

フェンリル採用チームの Twitter アカウントです。応募前のお問い合わせや、ちょっとした相談ごとなどお気軽にどうぞ!

フェンリルの Facebook ページでは、最新トピックをお知らせしています。よろしければいいね!してください!

Sleipnir の Facebook ページでは、ユーザーの方たちとのコミュニケーションや最新情報の投稿などを行なっています。よろしければいいね!してください!

Copyright © 2019 Fenrir Inc. All rights reserved.