October 11, 2020

Spinpassを支える技術 Kleat・fastlane・Terraform・Forestry

こんにちは。本記事ではSpinpassで使われている技術について紹介したいと思います。

Spinpassは継続的デリバリープラットフォームであるSpinnakerのiOSアプリ版という立ち位置です。先日、TestFlightの審査が通ってアルファ版をリリースしたところです。そして現在、App Storeでの正式公開に向けて少しずつ準備・開発しているところですが、一足先に、Spinpassで使われている技術について紹介しようと思います。

詳細はひとつひとつ紹介していますので興味があるセクションでもご覧ください。 使っている技術とその内容を端的にまとめると以下の通りです。

  • Kleat: Spinnnakerの設定と継続的な運用
  • fastlane(注1): iOSアプリのビルドリリース作成・署名などの自動化
  • App Store Connect上でのBuildやBeta Groupなどの宣言的な管理
  • Forestry: SpinpassのWebサイトCMS

注1: Fastlaneではなく先頭が小文字のfastlaneが正確な名称です。

全体像

Spinpassの開発環境は以下のようになっています。

上図では4つのパートに分けましたが、これからより詳細な図とともに、部分的に紹介していこうと思います。

Kleat

SpinnakerのCI/CDを担っている部分です。

Kleatは、Spinnakerの設定・継続的な運用を行うための次世代ツールで、現在はSpinnakerコミュニティで開発が進められています。Request for Comments(RFC)が公開されているので、詳しいモチベーションや仕様の紹介はここではしません。

App Storeでアプリを公開するにはテストユーザーを用意しなければならず、Apple社のためにSpinnakerを用意する必要があったのでKleatを導入しました。検証用の個人SpinnakerもKleatで設定をしていて、実績もあり、スムーズに導入できました。

Spinnakerの設定、およびデプロイのためのデファクト・スタンダードなツールにはHalyardがあります。今後はKleatを中心に置き換わっていくのですが未だHalyardが推奨されているデプロイ方法です(注2)。Kleatは、Halyardの単一の設定ファイルhalconfigから各Spinnakerを構成するコンポーネントの設定ファイルを生成するためツールであり、Kubernetes manifestのビルドには次に説明するkustomize-baseを、デプロイにはkubectlを使います。Kleatの設定ファイルを生成する流れは以下の通りです。

この生成されたファイルをKustomizeを使ってビルドしてからデプロイをします。KustomizeのベースとなるのがSpinnakerコミュニティが開発・運用しているkustomize-baseで、Spinnakerの各コンポーネントの基本的なKubernetes manifestが定義されています。Kleatによって生成された各コンポーネントファイルがKubernetes ConfigMapやSecretとしてビルドされ、各Deployment manifestが生成されます。流れは以下の通りです。

ここでPatchと書いたのは、KustomizeのPatchのことです。各コンポーネントのReplica数や他の設定を柔軟にできます。Halyardではできない宣言的な設定がKleatによって出来るようになり、各コンポーネントの設定はKustomizeを導入することによってモジュール性を持つようになります。これによって簡単にSpinnakerの設定・デプロイができました。いまのところ、コミュニティのkustomize-baseにPatchをあてるだけで済んでいますが、必要であればForkしてご自身で運用をする必要も今後出るかもしれません。

注2: Halyard v.s. Kleatの比較はフェアではなく、 Halyard v.s. Kleat + kustomize-base + kubectlが正しい技術的比較です。Halyardは内部でkubectlを実行していますが、部分的なAPIしか開発者に提供されていません。

fastlane

fastlaneは、モバイルアプリケーションをビルドしてリリースするための処理を自動化してくれるツールです。これはiOSアプリに限らず、モバイルアプリケーション開発をしていたら日常的に使うツールだと思うので、説明は割愛し、図のみの掲載とします。

fastlaneを使うことによってXcode上での操作がなくなり、毎回のビルドの中で10分ぐらい時間を節約することができます。

Terraform + App Store Connect

App Store Connectでは、iOSアプリをリリース、TestFlightのテストリリースを行うことができ、同時にBeta Groupと呼ばれるBeta Testerの集合や対象を管理をすることができます。しかし、いちいち手作業で行うと面倒です。そのためTerraformによって以下のようにApp Store Connectのリソースを定義しています。

例えば、Beta Groupを作成するには以下のようなリソースを定義します。

resource "app-store-connect_beta_group" "spinpass" {
    name   = "Spinpass alpha testing users"
    app_id = app-store-connect_app.id

    bundles = [
        app-store-connect_bundle.id
    ]

    beta_testers = [
        app-store-connect_beta_tester.keke.id,
        app-store-connect_beta_tester.tester_1.id
    ]
}

このようにして宣言的に、App Store Connectのリソースを管理することができました。今回はCustom Terraform Providerを開発したのですが、モバイルアプリという広大無辺なマーケット、および開発コミュニティがありながらTerraformを中心として、App Store Connectに関するプロビジョニングツールがないことが非常に驚きでした。

Forestry

ForestlyとはStatic CMSで、Wordpressに似たSaaSです。Forestryで行った変更は指定したGitHubにコミットされることが特徴です。SpinpassのWebサイトにはHugoを使っているのですが、Forestlyを導入することによってWorkpressのようにブラウザで記事をリッチなエディタで書くことが出来ます。GitHubで変更が行われるとNetlifyにデプロイされるようにしています。

また、SpinpassのWebサイトに使っているドメインはGoogle Domainsで取得をして、Google Cloud PlatformのCloud DNSを使ってNetlifyのWebページが取得したドメインでアクセスできるようにしています。 TerrafromでCloud DNSのゾーン、およびレコード管理は行っていて、以下のような流れになっています。

おわりに

最初に開発環境はざっと整えたので、モバイルアプリケーションのビジネスロジックを書くことに専念ができています。

Apple社の審査のために必要になるテスト用のSpinnakerおよびアカウントはKleatによって簡単に設定し、アップグレードの運用ができています。fastlaneによって、Xcode上で行っていたビルドリリースの作成や署名の作業を自動化することによって大幅に時間を節約することができています。TerraformによってBeta GroupやBuildの管理を管理を宣言的に、ソースコードで記述することによって定義をすることができ、簡単にApp Store Connectで必要な作業ができています。Forestryを導入したことによって、SpinpassのWebページは簡単にGUIでページ作成などをすることができています。TerraformでApp Store ConnectのBeta GroupやBuildなどのリソースを管理することができ、Infrastracture as Code(IaC)のメリットも感じています。

今回はiOSアプリのみを取り上げましたが、モバイルアプリケーションのCI/CDは非常に奥が深く、色んな学びがありました。

次はAndroid開発をしようと思っていますが、今後の継続的な開発コストを考え、思い切ってFlutterで書き直そうと思っています。それについてはまたブログにしたいと思います。 App StoreにSpinpassが正式リリースされることを、どうぞご期待ください。最後までありがとうございました。

© KeisukeYamashita 2020