🚀

Bitriseを使って検証、本番環境ごとにflutterアプリのCI/CD

2020/11/02に公開1

はじめに

先日初めてビルドをしてtestflightとgoogle playの内部テストにあげてみたのですが、想像より遥かに工数が多く大変だと感じました。現在自分はアプリを1人で開発していますが、もし人が増えてきたときにこのままだとデプロイ作業が属人化してしまうし、そもそも手動でデプロイするのが面倒すぎたので自動化しようと思いました。
今回使用するプラットフォームはBitriseです。flutterを公式にサポートしており、ドキュメントがかなり整備されていたので選びました。

なおこの記事は一度手動でtestflight、google playの内部テストにアップロードしたことがある前提で話を進めます。またandroidとiOSどちらについても記述しているので長めの記事になりますが、最後までお付き合いいただけると幸いです。

google playの方は記事書いてみたので良かったら読んでみてください

この記事でやること

  • Bitrise上で新規アプリの作成
  • developブランチにプルリクが来るたびにテストと解析が走るように設定
  • mainとstagingブランチにマージされるたびにテストと自動デプロイ(両プラットフォーム)が走るように設定
  • プロダクション環境にデプロイされたらgit tagを打つように設定
  • 上の完了をSlackで通知

お願い

自分は現在flutterで開発をしていますが、iOS、androidの開発経験は全くのゼロなのでネイティブ側のビルドやデプロイの作業に不備があることがございます。またCI/CDパイプラインを組むのも初めてです。何かあればコメント欄で指摘していただけると助かります。

環境

バージョン
MacOS X 10.15.4
DartSDK 2.10.1
flutterSDK 1.22.3
XCode 11.7
AndroidStudio 4.1
minSdkVersion 23
compileSdkVersion 30
targetSdkVersion 30
firebase_core 0.5.1
firebase_auth 0.18.2
cloud_firestore 0.14.2
firebase_storage 4.0.1

前提

大抵のアプリ開発ではBuild Flavorを分けて(開発版、ステージング版、製品版)開発をしていると思います。

自分もfirebaseのプロジェクトの接続先を変えたかったのでこの記事を参考にしてビルドモードの設定をしました。それらが適用されている前提でこの記事では解説をしていきますのでご注意ください

またiOS、androidアプリ自体はストアでテスト用、製品版と2つ作成していることを念頭に置いておいてください

bitriseで新規アプリ作成

まずはログインしたら新規アプリ作成を開始します。

Connect your repository

組織リポジトリの場合
Organizationのリポジトリで開発している場合は組織側でBitriseのアクセスを許可する必要があります。Githubで自分のアカウントの[Settings]->[Applications]->[Authorized OAuth Apps]でBitriseの項目があるので対象の組織で有効にします。

有効にすると組織内のリポジトリでも選択できるようになります。

Setup repository access

ここではBitriseがどのようにリポジトリにアクセスするかを決めます。Git tagを自動で打ちたい場合はここで自動生成してしまうと読み取り権限しか無いデプロイキーを発行されるので、マニュアル作成をおすすめします。自分はここで自動生成にしてしまったので、この記事の後半でキーを置き換える作業を紹介します。

Choose Branch

ここで選択したブランチはbitriseがそのプロジェクトの構成を読み取るのに使われます。基本的には開発が一段落した段階で設定をしていると思うので一旦masterにするなりして、最新のブランチを指定しましょう。flutterプロジェクトであることはここで読み取ってくれます

Project build configuration

ここの設定はどうせ後で変えるので基本何でも良いですが、テストビルド(静的解析とflutter test)が通るようにはしておきましょう。

iOS

前述のように自分はビルドモードを分けているのでXCodeの方でDevelop、StagingとProduction用のSchemeをすでに作成済みです。このあたりで解説されているので設定した上でbitrise側がそれらを読み込んでくれることを確認してください。以下のようになります。

exportメソッドは何でも良いです。iOS側の設定が終わると以下のように確認のカードが出てくるので合っているか確認しましょう

App Icon

アプリアイコンはflutter側で設定していると思うので一旦スキップでオッケーかと思います(Bitrise用のアイコンかな?)

Webhook

Webhookは自動で登録してくれます。

テストビルド

Webhookの登録が終わると一度静的解析とテストを行い、bitriseにアップロードしてくれます。基本的にここは失敗することがないと思います(ローカルの方で解析とテストが失敗してなければ)

これで初期設定は終わりです

CIの設定

解析とテストはdevelopにプルリクエストを出すたびに走るようにします。終わったらSlackで通知

Slackの設定

SlackのWebhookを登録します。こちらに行くとまだOutgoing Webhookを有効にしていない場合は有効にする旨のボタンが出ると思います。基本は難しい設定がないので割愛します。

こんな画面になると思います(Bitriseのアイコンは自分でアップロードします)

ここにあるWebhook URLは後で使います。

CIワークフロー

CIはプルリクエストのたびにテストと解析をするだけなので初期設定の段階で生成されたワークフローで十分です
workflowはデフォルトで名前がprimaryになっていますが、わかりにくいのでpull-requestあたりにかえます。

初期生成されたものから[Do Anything With Script Step]と[Deploy to Bitrise.io]を削除し、最後に[Send a Slack Message]を追加します。Slackのところは結構カスタマイズできるのでお好みでいろんな工夫をしてみてください。

[Triggers]に行き、developブランチに対してのすべてのpull requestをフックにpull-requestワークフローが走るように設定します

これでCIの設定は完了です。一度試しにpull requestを出してテストが走ることを確認してください

yamlを載せておきます。

pull-request:
    steps:
    - activate-ssh-key@4:
        run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'
    - git-clone@4: {}
    - flutter-installer@0:
        inputs:
        - is_update: 'false'
    - cache-pull@2: {}
    - flutter-analyze@0:
        inputs:
        - project_location: "$FLUTTER_PROJECT_LOCATION"
    - flutter-test@0:
        inputs:
        - project_location: "$FLUTTER_PROJECT_LOCATION"
    - cache-push@2: {}
    - slack@3:
        inputs:
        - channel: "$SLACK_NOTIFICATION_CHANNEL_NAME"
        - text: ''
        - pretext: "*Check was passed*"
        - buttons: ''
        - channel_on_error: "$SLACK_NOTIFICATION_CHANNEL_NAME"
        - text_on_error: ''
        - pretext_on_error: "*Check was failed!*"
        - webhook_url: "$SLACK_WEBHOOK_URL"

CDの設定

ブランチ構成

  • main->プロダクション環境ブランチ
  • staging->ステージング環境ブランチ
  • develop->開発安定版ブランチ
  • release/x.y.z->リリース前の準備ブランチ

ワークフローの概要

以下のような手順でデプロイが進むようにワークフローを組みたいと思います。

  • 機能追加や修正をdevelopブランチにマージする
  • developブランチからrelease/x.y.zブランチを切り、軽微な修正やpubspecのバージョンの更新などを行う
  • release/x.y.zブランチをstagingブランチにマージし、それを検知してstaging環境へのデプロイが走る(developブランチへのマージも行っておく)
  • staging環境で問題があればdevelopからまた上と同じ名前でブランチを切って修正した上で、BuildNumberを上げて再びstagingブランチとdevelopブランチへのマージを行う
  • staging環境で問題がなければmainブランチにマージし、それを検知してproduction環境へのデプロイが走る
  • production環境へのデプロイが完了したらgitのタグを打つ

デプロイ作業はiOSとandroidそれぞれのビルドと署名などのプロビジョニング系の作業から構成されます。

deployフローがデフォルトで作成されているはずなのでそれをもとにstaging-deployから作っていきます。ここからの入力はすべて環境変数で行います。適宜名前をつけて環境変数を[Env Var]から作成してください

一旦iOSとAndroid別々にワークフローを組んでテストした上で最後に合体します。

iOS(Staging)

証明書のアップロード

今回はXCodeのmanaged profileを使っているので、bitrise上でprofileを作成できるようにp12ファイルをアップロードする必要があるようです。(参考)

Macで[キーチェーンアクセス]に行って対象のApple DevelopmentとDistributionの証明書を選択し、右クリックして[書き出す]を選択します。

この際パスワードを要求されるので覚えておきましょう。p12ファイルが生成されたらbitriseにアップロードします。

アプリの画面に行ったら[code signing]を選択し、[CODE SIGNING CERTIFICATE]にp12ファイルをアップロードします。

パスワードが入力されていないので、パスワードの横の目のボタンをクリックして、パスワードを入力し、保存してください。正しいパスワードを入力するとチーム情報などが見れるようになるはずです。

iOS Auto Provisionの追加

自動でprofileを作成して貰う場合はワークフローに[iOS Auto Provision with App Store Connect Api]を追加します。(flutter testとflutter buildの間)この際、[Certificate and profile installer]が含まれているとエラーが出るようなので削除します。

ワークフローのパラメータを変更します

  • Distribution type->app store
  • Scheme name->Staging

これで署名周りの設定は完了です。

flutter buildの変更

[flutter build]のステップに行き、ステップ内[iOS Platform Configs]の[Additional Paramaters]を--flavor stagingに変更します

Xcode Archive & Export for iOSの設定

[Xcode Archive & Export for iOS]に行き、ステップ内の[Scheme name]をStagingに変更します。Schemeファイルの中で設定ができていれば必要ないですが、build configurationを設定したい場合は[Configuration name]から設定できます。

apple developer accountの紐付け

bitriseがappleの2段階認証を通過するためにapple developer accountを紐付ける必要があります。
app store connectのコンソールに行き、[User and Access]から[Key]のタブに行き、app store connect apiのキーを新規作成します。権限はdeveloperで問題ないです。

鍵を作成したらbitriseのアカウント設定に行き、[Appleアカウントの接続]を押して以下のフォームを埋めてください

issuerIDとkeyIDはapp store connectから見れます。p8ファイルはapp store connectからダウンロードできますが、1度しかダウンロードできないので気をつけてください

Bitriseアプリの方でもapple developer accountについて教えて上げる必要があるので、アプリのトップから[Team]を選択し、[Connected Apple developer portal account]へ行って、先程接続したアカウントを選択します。

ここでかなりハマったのですが、実はこれでもapple idの2段階認証を突破できないようになっているので、appleアカウントの方でサービスアカウント的な外部からの認証を突破するためのキーを発行する必要があります。

まずappleアカウントのページに行き、セキュリティセクションにある以下のような項目を選択します。

ここで発行されたキーをBitriseのSecretに保存してください

Deploy to iTunes Connect - Application Loaderの追加

現在はapp store connectになっていますが、bitriseの名前は以前のもののようです。本当は審査などに自動提出ができる[Deploy to iTunes Connect]ステップを使用したかったのですが、公式が提示している2段階認証の突破方法が何度やっても機能せず、うまく行かなかったのでこちらを使用します。
このissueを見る限り、まだ公式が個別に対応している段階で有効な対応策は見つかってないのかなと思います。自分は原因が特定できなかったのですが、なにか知っている方いましたらコメントいただけるとありがたいです。

XCode Archiveのあとに入れます。
ステップ内の[Apple Id]と[Password]を設定します。[Application Specific Password]にも先ほど作成したApp用パスワードのSecretを設定しておきます。

Send a Slack Messageを追加

CIのところでやったように最後にSlackのメッセージ送信を入れておきます。細かい設定は割愛。

この時点でのWorkflow

Activate SSH Key
Git clone Repository
Flutter install
Bitrise.io Cache:Pull
Flutter Analyze
Flutter test
iOS Auto Provision with App Store Connect API
Flutter Build
XCode Archive & Export for iOS
Deploy to iTunes Connect - Application Loader
Bitrise.io Cache:Push
Send a Slack Message

テストビルドのはずが...

自分はここで一度ビルドを試してみましたが、flavorの設定をしているとは言え、flutter createで生成されるcounterアプリのソースコードであるにも関わらずアーカイブビルドの途中でタイムアウトしてしまうほど時間がかかっていました(制限時間は45分です。buildに30分くらいかかり、archiveの途中で終わります)

firestoreパッケージのプリコンパイル版を使う

さすがにどうにかならないかと思って、色々探しているとfirestoreのプラグインを入れているとすごくiOSビルドに時間がかかってしまうが、プリコンパイルされたものを使えばビルド時間を短縮できるというissueを発見したので試してみた所30分だったビルド時間がなんと6~7分に...。
驚異的な短縮です。

やり方は非常に簡単でPodfile.lockを一度消して、flutter cleanをしたあとでPodfileに以下のように記述するだけです。

# ...
target 'Runner' do
  pod 'FirebaseFirestore', :git => 'https://github.com/invertase/firestore-ios-sdk-frameworks.git', :tag => '6.33.0'
# ...

tagの後ろのバージョンはfirestoreのプラグインのバージョンが0.14.2なら6.33.0になります。本当はtagの後ろを省略すると最新バージョンを取れるらしいのですが、うまく行かなかったので指定しました。
これでローカルでビルドするだけでも効果が実感できると思います。

iOS側の設定はこれで完了です!

android(staging)

androidの方はapp bundleの自動デプロイについて書きます

アプリの作成

まずgoogle play consoleでアプリを先に作成しておいてください。以前書いた記事で軽く解説していますが、アプリのビルドをアップロードするまでにストアの初期設定と初回デプロイを行っておく必要があります。

keystoreのアップロード

Bitriseアプリコンソールの[Code Signing]->[ANDROID KEYSTORE FILE]からkeystoreファイルをアップロードできます。アップロードすると以下のようなフォームが出て、各種プロパティの入力が求められます。これらの値が自動的に環境変数として追加されます。

署名設定の変更

flutter buildコマンドは内部的に署名を行っていると思いますが、ローカルでビルドするのと違って、CI環境から得られる環境変数やアップロードしたkeystoreから値をとってくる必要があります。そのためbuild.gradleをCI環境にいるときはBitriseの環境変数を参照するように変更する必要があります。

まずCI環境にいるかの判定をするためにBitriseの[Env Vars]でルートレベルに$IS_BITRISEという変数を追加し、trueにしておきます。これをbuild.gradleの中で読み、CI環境の中であればBitriseがkeystoreアップロード時に作成された環境変数を読み出すようにします。具体的はコードは以下のとおりです。

// ...

signingConfigs {
        release {
            if (System.getenv('IS_BITRISE')) {
                keyAlias System.getenv("BITRISEIO_ANDROID_KEYSTORE_ALIAS")
                keyPassword System.getenv("BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD")
                storeFile file(System.getenv("HOME") + "/keystores/key.jks")
                storePassword System.getenv("BITRISEIO_ANDROID_KEYSTORE_PASSWORD")
            } else {
                keyAlias keystoreProperties['keyAlias']
                keyPassword keystoreProperties['keyPassword']
                storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
                storePassword keystoreProperties['storePassword']
            }
        }
    }
    
// ...

File Downloaderの追加

ここで結構ハマったのですが、keystoreファイルのpathはこのままでは読み出せないので先に[File Downloader]ステップを設置します。

keystoreファイルアップロード時に作成されるBITRISEIO_ANDROID_KEYSTORE_URLはkeystoreファイルをダウンロードするためのURLです。少しややこしいのですが、これはそのままでは使えず、この[File Downloader]で読み出せるようにダウンロードする必要があります。

gradleファイルで読み出し先を$HOME/keystores/key.jksに指定しているので、このステップの[Download source url]に$BITRISEIO_ANDROID_KEYSTORE_URLを、[Download destination path]に$HOME/keystores/key.jksを指定しておきます。

これでkeystoreファイルが読み出せるようになります。

flutter buildの変更

[flutter build]のステップに行き、[Android Platform Configs]の[Additional Paramaters]を--flavor stagingに変更します

サービスアカウントの作成

google playでもCI環境からアカウントへのアクセスをするためにサービスアカウントを発行する必要があります。

Play Consoleに行き、サイドバーの[設定]->[APIアクセス]に行き、新規プロジェクトの作成を押すとこのような画面になると思います。

次にサービスアカウントを作成していきます。[新しいサービスアカウントを作成]のボタンを押すと、以下のようなポップアップが出ると思うので、表示されているリンクから飛んで[サービスアカウントを作成]を押してGoogle Play Api Bitrise Deployなどの名前でアカウントを作成します。[このサービス アカウントにプロジェクトへのアクセスを許可する]では[Service Accounts]->[Service Account User]を選択し、次の手順はスキップします。

アカウントが作成されたら以下のように[キーを作成]を選択します。形式はJSONです。ダウンロードしたファイルは大切に保管してください

play consoleに戻り、以下の画面のように[アクセスを許可]を押します。

アカウント権限の設定に移ると思うので、[アプリのアクセス権]->[アプリ情報の閲覧、一括レポートのダウンロード]と[リリース]の項目全てにチェックを付けて、あとは外し、[ユーザーを招待]を押して完了します。

これでサービスアカウントの設定は完了です。

サービスアカウントキーのアップロード

次に先ほど作成したサービスアカウントに接続できるようにキーファイルをアップロードする必要があります。Bitriseに戻り、[Code Signing]から[Generic File Storage]に行き、SERVICE_ACCOUNT_JSON_KEYという名前でJSONファイルをアップロードします。

完了するとこんな感じ

Deploy to Google Playの追加

Workflowエディタに戻り、flutter buildのあとに[Deploy to Google Play]ステップを入れます。

[Service Account JSON Key file path]には先ほど作成したキーファイルのダウンロード先変数を入れます。(上の場合だと$BITRISEIO_SERVICE_ACCOUNT_JSON_KEY_URL
[Package Name]にはcom.hoge.fugaのようなアプリIDを入れます。[Track]にはご自身のプロジェクトに合わせた設定をしてください。

この時点でのWorkflow

Activate SSH Key
Git clone Repository
Flutter install
Bitrise.io Cache:Pull
Flutter Analyze
Flutter test
File Downloader
Flutter Build
Deploy to google play
Bitrise.io Cache:Push
Send a Slack Message

テストデプロイ

これで一旦デプロイをしてみましょう。Androidの方はビルド時間も短く、特に問題は発生しないと思います。

合体

両方のテストが上手く行ったら最後にそれぞれのワークフローを合体します。

Activate SSH Key
Git clone Repository
Flutter install
Bitrise.io Cache:Pull
Flutter Analyze
Flutter test
iOS Auto Provision with App Store Connect API
File Downloader
Flutter Build
XCode Archive & Export for iOS
Deploy to iTunes Connect - Application Loader
Deploy to Google Play
Bitrise.io Cache:Push
Send a Slack Message

yamlも載せておきます

staging-deploy:
    steps:
    - activate-ssh-key@4:
        run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'
    - git-clone@4: {}
    - flutter-installer@0: {}
    - cache-pull@2: {}
    - flutter-analyze@0:
        inputs:
        - project_location: "$FLUTTER_PROJECT_LOCATION"
    - flutter-test@0:
        inputs:
        - project_location: "$FLUTTER_PROJECT_LOCATION"
    - ios-auto-provision-appstoreconnect@0:
        inputs:
        - scheme: "$STAGING_SCHEME"
        - project_path: "$IOS_PROJECT_PATH"
        - distribution_type: app-store
    - file-downloader@1:
        inputs:
        - destination: "$HOME/keystores/key.jks"
        - source: "$BITRISEIO_ANDROID_KEYSTORE_URL"
    - flutter-build@0:
        inputs:
        - ios_additional_params: "$STAGING_BUILD_COMMAND"
        - android_output_type: appbundle
        - android_additional_params: "$STAGING_BUILD_COMMAND"
    - xcode-archive@2:
        inputs:
        - configuration: ''
        - verbose_log: 'no'
        - export_method: app-store
        - project_path: "$IOS_PROJECT_PATH"
        - scheme: "$STAGING_SCHEME"
    - deploy-to-itunesconnect-application-loader@0:
        inputs:
        - itunescon_user: "$APPLE_ID"
        - app_password: "$APP_SPECIFIC_PASSWORD"
        - password: "$APPLE_PASSWORD"
    - google-play-deploy@3:
        inputs:
        - package_name: "$STAGING_BUNDLE_IDENTIFIER"
        - track: internal
        - service_account_json_key_path: "$BITRISEIO_SERVICE_ACCOUNT_JSON_KEY_URL"
    - cache-push@2: {}
    - slack@3:
        inputs:
        - channel: "$SLACK_NOTIFICATION_CHANNEL_NAME"
        - pretext: "*Build and Deploy Succeeded!*"
        - pretext_on_error: "*Build and Deploy Failed!*"
        - webhook_url: "$SLACK_WEBHOOK_URL"

合体後にもう一度走らせてみてうまくいくかを確認してください。最後にstagingブランチにpushがあった際にワークフローが走るようにしておきましょう。

Production環境用の設定

Production環境もStaging用のものと基本同じですが、最後にタグを打つステップを追加します。(環境変数などはStaging用のものと適宜差し替えておいてください)

Github Access Tokenの設定

Githubでリリースを自動化するためにGithub Access Tokenが必要になります。こちらから作成を行います。
プライベートリポジトリにアクセスする必要がある場合は[repo]にチェックを入れます。

作成後に表示されるトークンは一度しか見れないので、コピーしてすぐにBitriseのsecretsに保存しておきます。

Github Deploy keyの再設定

上で言ったように自動生成されたSSHKeyは読み取り権限しかなく、タグが打てないので新しくSSHKeyを発行する必要があります。

Bitriseアプリコンソールに行き[Settings]から[Change SSH Key Pairs]に行きます。

ここで[Generate SSH Keypair]を選択し、Githubリポジトリの[Settings]->[Deploy Keys]に行って、新しいデプロイキーを発行されたSSHKeyで作成します。このとき書き込み権限を有効にしておいてください

Get pubspec version and build numberの追加

[Bitrise.io Cache:Push]の後ろに[Get pubspec version and build number]を追加します。これを使うとpubspecからバージョン名と番号を読み取り、$PUBSPEC_VERSION_NAME$PUBSPEC_VERSION_NUMBERに格納しておいてくれます

Git tagの追加

上のステップのあとに[Git tag]ステップを追加します。tag名はビルド番号を無視して、version_nameのみにしたいので[Tag to set on current commit]をv$PUBSPEC_VERSION_NAMEにしておきます。

Generate Changelogの追加

上のステップのあとに[Generate Changelog]ステップを追加します。[Next version]をv$PUBSPEC_VERSION_NAMEに変えます

Github Releaseの追加

[Github Release]ステップを追加し、[Personal API Token]に先ほど作成したトークンを、[User Name]に自分のuser名を入れてください。

[tag]と[Release Name]には例によってv$PUBSPEC_VERSION_NAMEを、リリースノートのbodyメッセージはコミットメッセージを入れるようにしたいので、$BITRISE_GIT_MESSAGEを入れておきます。
即リリースにしたいので[Draft]はNoにしておきます。

これでgit周りの設定は完了です。

テストデプロイ

これでtriggerにproductionのpush時に上のワークフローを走らせるようにすれば、Production環境の方の設定も完了です。Git commitメッセージなどを含むフローなので実際にmainブランチにマージしてテストしてみましょう。

yaml

productionの方のワークフローとyamlは以下の通り

Activate SSH Key
Git clone Repository
Flutter install
Bitrise.io Cache:Pull
Flutter Analyze
Flutter test
iOS Auto Provision with App Store Connect API
File Downloader
Flutter Build
XCode Archive & Export for iOS
Deploy to iTunes Connect - Application Loader
Deploy to Google Play
Bitrise.io Cache:Push
Get pubspec version and build number
Git tag
Generate Changelog
Github Release
Send a Slack Message
production-deploy:
    steps:
    - activate-ssh-key@4:
        run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}'
    - git-clone@4: {}
    - flutter-installer@0: {}
    - cache-pull@2: {}
    - flutter-analyze@0:
        inputs:
        - project_location: "$FLUTTER_PROJECT_LOCATION"
    - flutter-test@0:
        inputs:
        - project_location: "$FLUTTER_PROJECT_LOCATION"
    - ios-auto-provision-appstoreconnect@0:
        inputs:
        - scheme: "$PRODUCTION_SCHEME"
        - project_path: "$IOS_PROJECT_PATH"
        - distribution_type: app-store
    - file-downloader@1:
        inputs:
        - destination: "$HOME/keystores/key.jks"
        - source: "$BITRISEIO_ANDROID_KEYSTORE_URL"
    - flutter-build@0:
        inputs:
        - ios_additional_params: "$PRODUCTION_BUILD_COMMAND"
        - android_output_type: appbundle
        - android_additional_params: "$PRODUCTION_BUILD_COMMAND"
    - xcode-archive@2:
        inputs:
        - configuration: ''
        - verbose_log: 'no'
        - export_method: app-store
        - project_path: "$IOS_PROJECT_PATH"
        - scheme: "$PRODUCTION_SCHEME"
    - deploy-to-itunesconnect-application-loader@0:
        inputs:
        - password: "$APPLE_PASSWORD"
        - app_password: "$APP_SPECIFIC_PASSWORD"
        - itunescon_user: "$APPLE_ID"
    - google-play-deploy@3:
        inputs:
        - package_name: "$PRODUCTION_BUNDLE_IDENTIFIER"
        - track: internal
        - service_account_json_key_path: "$BITRISEIO_SERVICE_ACCOUNT_JSON_KEY_URL"
    - cache-push@2: {}
    - get-pubspec-version-and-build-number@1: {}
    - git-tag@1:
        inputs:
        - tag: v$PUBSPEC_VERSION_NAME
    - generate-changelog@0:
        inputs:
        - new_version: v$PUBSPEC_VERSION_NAME
    - github-release@0:
        inputs:
        - username: "$GITHUB_USER_NAME"
        - tag: v$PUBSPEC_VERSION_NAME
        - name: v$PUBSPEC_VERSION_NAME
        - body: "$BITRISE_GIT_MESSAGE"
        - draft: 'no'
        - api_token: "$GITHUB_ACCESS_TOKEN"
    - slack@3:
        inputs:
        - channel: "$SLACK_NOTIFICATION_CHANNEL_NAME"
        - pretext: "*Build and Deploy Succeeded!*"
        - pretext_on_error: "*Build and Deploy Failed!*"
        - webhook_url: "$SLACK_WEBHOOK_URL"

これですべての設定が終わりました!

まとめ

初めてCI/CDパイプラインを組んでみたのですが、ビルド設定やプロビジョニング周り、サービスアカウントなどいろんな知識が身についたように思います。実際試してみて相当開発体験が向上しました。少ない人数でやっているほどこの作業をやっておく恩恵は大きいと思うのでぜひ試してみてください。

かなり長い記事でしたが最後まで読んでくださりありがとうございました。

Discussion

Tatsuya YamamotoTatsuya Yamamoto

素晴らしい記事ありがとうございます!とても勉強になりました!
一点、Bitrise の更新があり変数名が変わっていたのでコメントさせていただきます。

IS_BITRISEBITRISE_IO

    signingConfigs {
        release {
+            if (System.getenv('BITRISE_IO')) {
-            if (System.getenv('IS_BITRISE')) {
                keyAlias System.getenv("BITRISEIO_ANDROID_KEYSTORE_ALIAS")
                keyPassword System.getenv("BITRISEIO_ANDROID_KEYSTORE_PRIVATE_KEY_PASSWORD")
                storeFile file(System.getenv("HOME") + "/keystores/key.jks")
                storePassword System.getenv("BITRISEIO_ANDROID_KEYSTORE_PASSWORD")
            } else {
                keyAlias keystoreProperties['keyAlias']
                keyPassword keystoreProperties['keyPassword']
                storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
                storePassword keystoreProperties['storePassword']
            }
        }
    }

参考
Available environment variables - Bitrise Docs