LoginSignup
39
22

More than 3 years have passed since last update.

CircleCI 2.1 と fastlane で Flutter の iOS と Android をビルドして DeployGate で配布する

Last updated at Posted at 2019-03-08

3行で

  • 会社のCI環境をCircleCIで統一しているため、BitriseやCodemagicではなくCircleCIでやりたかった
  • AndroidはDockerイメージで楽に環境構築できるが、iOSは色々対応が必要です
  • AndroidとiOSでビルドする手順に違いはあるが、CircleCI2.1の機能でうまく対応できました :tada:

config.yml と Fastfile の完成形

 今回は、リリースビルドで開発環境向け(Release-Development)のアプリを配布する処理を例にして書きます。Release-Developmentについては、 @mono0926さんのFlutterで環境ごとにビルド設定を切り替える — iOS編
を参考にしてください。

 少々長いのでGistにしました。これらのファイルを定義することで、タイトルどおりのCI環境が構築できるはずです。

~/.circleci/config.yml

~/Android/fastlane/Fastfile

~/ios/fastlane/Fastfile

~/ios/fastlane/Matchfile
# 証明書を保存するリポジトリを用意してください
git_url("git@github.com:example/example-ios-cert.git")
git_branch("master")

storage_mode("git")

type("development")

github.com/example-fastlane/util/Fastfile

 AndroidとiOSの共通変数や共通メソッドは、別リポジトリのFastfileをインポートして利用しています。実際のFastfileはもう少し分割していますが、今回は例なので一つにまとめています。

 別リポジトリのFastfileをインポートすることについては、@star__hoshiさんの Fastfile の import 機能を使い、複数のプロジェクトで共通の Fastfile を使う を参考にしてください。

 なお、flutter build コマンドはこのFastfileに定義しており、それぞれのFastfileから引数でパラメータを受け取り、ビルドモードとflavorとtargetを指定しています。iOSに限り、 --no-codesign にして、後から fastlane match で管理している証明書を差し込めるようにしています。

 ローカルとCIの両方の環境で実行できるように is_ci? で環境を判定しています。CI環境の場合に $FLUTTER_HOME/bin にしているのは、Androidで利用するDockerイメージのFlutterSDKのPATHが$FLUTTER_HOME になっているためです。

github.com/example-fastlane/util/Fastfile
# Flutter App をビルドする
private_lane :build_flutter_in_util do |options|

  codesign = options[:platform] == "ios" ? "--no-codesign" : ""

  if is_ci?
    sh("cd ../../ && $FLUTTER_HOME/bin/flutter build #{options[:platform]} --release --flavor #{options[:flavor]} --target #{options[:target]} #{codesign}")
  else
    sh("cd ../../ && flutter build #{options[:platform]} --release --flavor #{options[:flavor]} --target #{options[:target]} #{codesign}")
  end
end

CircleCI 2.1で Flutterのアプリをビルドする

 CircleCI 2.1の機能を有効にするには、CircleCIのプロジェクトの設定画面で Settings -> Advanced SettingsEnable build processing (preview)On にしてください。

 有効にすると、 executorscommandsparameters の機能が利用できます。簡単に説明すると、 executors は環境、 commands は処理、 parameters は変数を任意の組み合わせで定義できる機能です。

 他にもCircleCI 2.0の機能ですが、 working_directory: で処理ごとに実行するディレクトリを指定できます。Flutterプロジェクトはプラットフォームごとにスクリプトを実行するディレクトリが違うので、 working_directory: はとても便利です。

~/.circleci/config.yml
  setup_ios_build_setting:
    steps:
      - run:
         name: Run pod setup from cocoapods-specs.circleci.com
         command: curl https://cocoapods-specs.circleci.com/fetch-cocoapods-repo-from-s3.sh | bash -s cf
         working_directory: ~/flutterApp/ios

Androidをビルドする場合

 Androidのビルドに必要な環境は、 image: cirrusci/flutter:latest に用意されています。FlutterとAndroidのSDKがインストールされてPATHも通っているので、CircleCI側ではクローンして、 flutter doctorflutter analyze の後にビルドしてDeployGateに配信するだけです。とても楽です。

~/.circleci/config.yml
  beta_development_android:
    executor:
      name: default_android
    steps:
      - checkout
      - setup_flutter
      - setup_bundle:
          platform: android
      - flutter_build:
          platform: android
          configuration: development

iOSをビルドする場合

 iOSのビルドには macOSが必要なので、CircleCIはmacOSの環境を選択してください(有料です)。先ほど、Androidのビルドに利用したDockerイメージは、Linuxなので証明書でビルドが失敗します。したがって、iOSではFlutterのSDKをクローンしてPATHを通す必要があります。

~/.circleci/config.yml
  install_flutter:
    steps:
      - run:
          name: Install flutter SDK
          command: mkdir -p ~/sdks/flutter && git clone -b stable https://github.com/flutter/flutter.git ~/sdks/flutter
      - run:
          name: Set flutter SDK PATH in bash
          command: echo 'export FLUTTER_HOME=~/sdks/flutter' >> $BASH_ENV && source $BASH_ENV

CircleCI 2.1の新機能で実行環境を別にして処理を共通化

 AndroidとiOSの実行環境を別に定義したいので、executors を使います。 iOSでは、 executor:default_ios を指定したので、Dockerイメージではなく、CircleCIのmacOSをつかってビルドします。

 commands: の機能で、flutter doctorflutter analyzeの処理は共通化できますし、 parameters: の機能で flutter_build: で必要な引数もプラットフォームごとにわけて渡せます。

~/.circleci/config.yml
  beta_development_ios:
    executor:
      name: default_ios
    steps:
      - checkout
      - install_flutter
      - setup_flutter
      - setup_bundle:
          platform: ios
      - setup_ios_build_setting
      - flutter_build:
          platform: ios
          configuration: development

disable_automatic_code_signing で証明書を設定

 iOSでは --no-codesign でビルドしたので、 fastlaneの disable_automatic_code_signing を呼んで手動で証明書を設定します。このような手動の管理が面倒だと思う方は、 BitriseCodemagicを検討すると良いです。

 options[:app_configs] が配列なのは、全てのターゲットに一度に証明書を設定可能にするためです。iOSでは複数のターゲットをもつアプリが存在するので、このようにしておくと楽なのですが、今回の例では不要なループ処理です(消すのが面倒でした :bow: )。

github.com/example-fastlane/util/Fastfile

# Code Signing Style を Manual に変更
private_lane :change_manual_code_signing_style_in_util do |options|

  code_sign_identity = ""
  profile_name_prefix = ""

  if options[:mode] == "development"
    code_sign_identity = ENV["CERT_DEVELOPER_ID"]
    profile_name_prefix = "match Development"
  end

  options[:app_configs].each { |app_config|
    disable_automatic_code_signing(
      targets: app_config[:target],
      code_sign_identity: code_sign_identity,
      profile_name: "#{profile_name_prefix} #{app_config[:profile_name_app_id]}"
    )
  }
end

最後に

 モバイルアプリ開発でCI環境がない場合、アプリの検証サイクルを走らせるのが一気に面倒になります。できるだけ早くCI環境の構築は終わらせておき、開発に集中したいアプリエンジニアは多いと思います。特に私はそうです :smile:

 Flutterで開発するとき「CI環境どうしよう」と不安になっていた時期もありましたが、今の所は問題なく、ネイティブアプリの開発フローと変わらずに検証と開発ができています。さらに、本番・ステージング・開発など、環境別にアプリを分けて配信して、同じスマートフォンに複数のアプリをインストールさせることも可能です。

 あとは、DartとFlutterのスキルさえ上がれば・・・。Flutter開発がんばろう :muscle:

参考

39
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
22