FlutterのHelloWorldアプリをBitriseでCI/CDする手順（iOS向け）

# はじめに

Flutterに手を出して３ヶ月が経ちました。FlutterアプリをBirtiseでCI/CD構築するときにハマったので、こうすれば上手くいったという手順を書き残しておきます。

「この手順は不要」「この順番の方が良い」などのアドバイス大歓迎です。

## 開発環境、使用ツール

<dl>
 <dt>ターゲット</dt><dd>iOS</dd>
 <dt>言語</dt><dd>Flutter/Dart</dd>
 <dt>エディタ</dt><dd>Android Studio, Xcode</dd>
 <dt>リポジトリ</dt><dd>GitHub</dd>
 <dt>CI/CDツール</dt><dd>Bitrise</dd>
</dl>

# 構築手順

## GitHub リポジトリ作成

[GitHub](https://github.com/) にログイン
新規リポジトリ名を入力　（例）*FlutterHelloWorld*
**Public** または **Private** を選択
（任意） **Initialize this repository with a README** を選択
**[Create Repository]** を押下
<img width="757" alt="01_GitHub.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/2611aeca-bbbf-eed0-0128-62a6a26d9e84.png">


ローカルPC（の適当なディレクトリ）にクローンする

```
$ cd ~/workspace
$ git clone git@github.com:YOURNAME/FlutterHelloWorld.git
```

## Flutter プロジェクト作成

Android Studioを起動

**Start a new Flutter project** を選択
**Flutter Application** を選択し **[Next]** を押下

以下の項目を入力し **[Next]** を押下

<dl>
 <dt>Project name</dt><dd>helloworld</dd>
 <dt>Flutter SDK path</dt><dd>/Users/YOURNAME/development/flutter</dd>
 <dt>Project location</dt><dd>/Users/YOURNAME/workspace/FlutterHelloWorld</dd>
</dl>

以下の項目を入力し **[Finish]** を押下

<dl>
 <dt>Company domain</dt><dd>YOURCOMPANY.com</dd>
</dl>

エミュレータ（iOS）で動作確認。FlutterのHelloWorldアプリが動くこと
<img width="463" alt="07_EmuI.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/55b68f40-8e47-1d09-f921-a7ae811e675a.png">


いったんGitHubにコミットする

```
$ pwd
/Users/YOURNAME/workspace
$ cd FlutterHelloWorld
$ ls
README.md	helloworld
$ git add helloworld
$ git commit -m 'first commit'
```

## Apple Developerの設定

[Apple Developer](https://developer.apple.com/jp/) を開く
**Account** を押下し、自分のApple IDでログイン
**Certifictes, Identifiers & Profiles** を開く
**Identifiers** を選択し、**(＋)** を押下
**App IDs** を選択し **[Continue]** を押下

以下の項目を入力し **[Continue]** を押下

<dl>
 <dt>Description</dt><dd>説明文（例：flutter hello world）</dd>
 <dt>Bundle ID</dt><dd>（Explicitを選択）com.YOURCOMPANY.helloworld</dd>
 <dt></dt><dd></dd>
</dl>

**[Register]** を押下

## App Store Connectの設定

[App Store Connect](https://appstoreconnect.apple.com) にログインする。
**マイApp** を開く
**[＋]** > **新規App** を選択

以下の項目を入力し **[作成]** を押下

<dl>
 <dt>プラットフォーム</dt><dd>iOS</dd>
 <dt>名前</dt><dd>Flutter Hello World</dd>
 <dt>プライマリ言語</dt><dd>日本語</dd>
 <dt>バンドルID</dt><dd>flutter hello world - com.YOURCOMPANY.helloworld</dd>
   <dt>SKU</dt><dd>任意の文字列</dd>
   <dt>ユーザアクセス</dt><dd>アクセス制限あり または アクセス制限なし</dd>
</dl>

## FlutterアプリにApple署名証明書の設定

Android Studioにて **ios** ディレクトリを右クリック > **Flutter** > **Open iOS module in Xcode** を選択し、Xcodeを開く。

**TARGETS** > **Runner** > **Signing & Capabilities** > **All** を開く
**Signing** > **Team** にて 自分のチーム名を選択すると Signing Certificateのエラーが消えること
<img width="723" alt="12_XcodeSigning.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/99b38350-89c6-9268-30ea-9d3040b9d1da.png">

## app-store用のアーカイブを作成

スキームに **Generic iOS Device** を選択
<img width="546" alt="10_XcodeGeneric.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/1ebf32e9-ac67-ed6e-e275-b0a80ae9c92e.png">

メニューから **Product** > **Archive** を選択し、アプリをアーカイブ
<img width="802" alt="11_XcodeArchive.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/24b6c89c-9803-b9bd-115c-f8f9bf4a04c8.png">

アーカイブが成功すると開く、オーガナイザウィンドウにて **[Distribute App]** を押下
<img width="1112" alt="21_AppUpload.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/66bb200d-c5fa-1097-8118-c24508efb59d.png">

**App Store Connect** を選択し **[Next]** を押下
<img width="737" alt="22_AppUpload.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/63c1ba26-c526-a1bb-136a-942e6e2d11cb.png">

**Upload** を選択し **[Next]** を押下
<img width="737" alt="23_AppUpload.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/b3dcc8f1-79cb-b8dc-b4d7-6c0c2428574f.png">

デフォルト（チェックON）のまま **[Next]** を押下
<img width="737" alt="24_AppUpload.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/bc1a7210-e22d-5fd6-3e91-24f4587ad56c.png">

**Automatically manage signing** を選択し **[Next]** を押下
<img width="737" alt="25_AppUpload.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/5e12b95e-5242-9ae3-884c-2d890baaef93.png">

**[Upload]** を押下
<img width="737" alt="26_AppUpload.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/2084319b-2e7e-8957-45e4-b91328ea7a06.png">

Uploadが完了するまで、しばらく待つ
<img width="737" alt="27_AppUpload.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/acbd0d69-eaba-3a37-0984-e158cd2d7d44.png">

完了したら **[Done]** を押下
<img width="737" alt="28_AppUpload.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/38b14974-7d04-a257-0b85-d7022831c3b2.png">

App Store Connectにアプリがアップロードされていることを確認する。

## Bitrise Appを作成

[Bitrise](https://www.bitrise.io/) にログイン
**Add New App** > **Add New App on Web UI** を選択
<img width="335" alt="31_Br_AddNewApp.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/71a2e563-2fe1-9ccf-08db-46a336c0d491.png">

<dl>
  <dt>CHOOSE ACCOUNT</dt><dd>（組織名）</dd>
  <dt>SET PRIVACY OF THE APP</dt><dd>Public or Private</dd>
</dl>
<img width="524" alt="32_Br_ChooseAccount.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/5a0f612f-4991-84a0-ba82-58de797838dd.png">

**[Next]** を押下

GitHubリポジトリを選択（例： *FlutterHelloWorld*）

Setup Repository accessで **[I need to]** を押下
<img width="1070" alt="33_Br_SetupRepository.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/8ea7a32d-8583-fb7b-7144-179aece52ed5.png">

SSH Public key をコピーし、[GitHub](https://github.com/)を開く

GitHubアカウントの **Settings** > **SSH and GPG keys** > **[New SSH Key]** を押下

<dl>
  <dt>Title</dt><dd>（任意の名前）</dd>
  <dt>Key</dt><dd>コピーしたSSH Public key</dd>
</dl>

**[Add SSH Key]** を押下

Bitrise に戻り、 **[I've added the SSH key]** を押下

<dl>
  <dt>Choose branch</dt><dd>master</dd>
</dl>
<img width="698" alt="34_Br_ChooseBranch.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/d2caa7fe-2f80-0553-f22d-15297087edcb.png">

**[Next]** を押下

Validationが実行される。
<img width="1037" alt="35_Br_Validation.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/fdd5b8be-a268-c01f-6caf-f64914b8cbd3.png">

問題なければ、Project build configurationでFlutterが検出される。
<img width="1065" alt="36_ValidRslt.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/6b9b7fca-5576-3c10-dc38-cba74a25ac9e.png">

Selected project build configuration で以下を選択

<dl>
  <dt>Project location</dt><dd>helloworld</dd>
  <dt>Run tests found in the project</dt><dd>yes</dd>
  <dt>Project or Workspace path</dt><dd>helloworld/ios/Runner.xcworkspace</dd>
  <dt>Scheme name</dt><dd>Runner</dd>
  <dt>ipa export method</dt><dd>app-store</dd>
  <dt>Flutter stack</dt><dd>Xcode 11.1.x, on macOS 10.14.6 (Mojave)</dd>
</dl>
<img width="949" alt="37_buildconfig.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/78b8cde1-788e-f011-b612-093aac1c663d.png">


**[Confirm]** を押下

App Icon は **[Skip for Now]** を押下

Webhook setup は **[Skip the Webhook registration.]** を押下

**[We've kicked off your first test build for you!]** を押下

初回のprimaryビルドが実行される。
<font color="Red">初回は失敗しても気にしない。以降の手順で設定を見直す。</font>

## Bitrise primary Workflow の設定

<font color="Red">※Workflowを修正したら、こまめに **[⌘＋S]** で保存すること（けっこう忘れがち）</font>

Bitrise Workflow Editorを開き、**primary** を選択する。
<img width="611" alt="40_workflow.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/37c771af-2d26-253a-4876-f161a6c6e031.png">

各Stepのバージョンを最新にする。(**Always latest**)

以下を修正する。

- Flutter Install
<dl>
 <dt>Flutter SDK git repository version</dt><dd>dev</dd>
</dl>
<img width="654" alt="41_workflow.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/c0b120aa-dc13-ef61-2455-738b92e9363b.png">

primary Workflow のビルドを実行。今度は成功するはず。
<img width="601" alt="42_workflow_primary.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/d55857cd-de84-6d4c-57e1-bf04ae480d4a.png">

## Bitrise deploy Workflow の設定

Bitrise Workflow Editorを開き、**deploy** を選択する。
<img width="775" alt="43_workflow_deploy.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/3c49ca6b-f446-3eda-233d-6cf39b1660a7.png">

各Stepのバージョンを最新にする。(**Always latest**)

以下を修正する。

- Cetrificate and profile installer  
  このStepは使わないので削除

- Flutter Install  
<dl>
 <dt>Flutter SDK git repository version</dt><dd>dev</dd>
</dl>

- iOS Auto Provision  
  Flutter Test と Flutter Buildの間に追加
<dl>
 <dt>Distribution type</dt><dd>app-store</dd>
 <dt>The Developer Portal team ID</dt><dd>自分のチームID</dd>
 <dt>Configuration Name</dt><dd>Release</dd>
 <dt>Should the step try to generate Provisioning Profiles ...</dt><dd>yes</dd>
</dl>

- Xcode Archive & Export for iOS  
<dl>
 <dt>Select method for export</dt><dd>app-store</dd>
</dl>

- Deploy to Bitrise.io - Apps, Los, Artifacts  
<dl>
 <dt>Enable public page for the App?</dt><dd>true</dd>
</dl>

- Deploy to iTunes Connect - Application Loader  
  Bitrise.io Cache:Push の後に追加
<dl>
 <dt>Apple ID</dt><dd>自分のApple ID</dd>
 <dt>Password</dt><dd>自分のApple IDのパスワード</dd>
 <dt>Application Specific Password</dt><dd>App用パスワード（※）</dd>
</dl>

※[AppleID Website](https://appleid.apple.com/)にアクセスし、 **App用パスワード** > **パスワードを生成** をクリックすると生成できる。

## Bitrise Code Signing の設定

Bitrise Workflow Editor の **Code Signing** を開く。
<img width="1062" alt="44_CodeSigning.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/24af101b-04ec-b86e-f30c-1cbcfde34806.png">

Runner.xcworkspaceがあるディレクトリで、以下のコマンドを実行

```
$ cd ~/workspace/FlutterHelloWorld/helloworld2/ios

$ ls
Flutter			Runner.xcodeproj
Runner			Runner.xcworkspace

$ bash -l -c "$(curl -sfL https://raw.githubusercontent.com/bitrise-tools/codesigndoc/master/_scripts/install_wrap.sh)"
```

いろいろなチェックが走るので、しばらく待つ。

```
Select the ipa export method
Please select from the list:
[1] : development
[2] : app-store
[3] : ad-hoc
[4] : enterprise
(type in the option's number, then hit Enter) [1] : 
```

[1] : development を選択

```
Select the Provisioning Profile to sign target with bundle ID: com.YOURCOMPANY.helloworld
Please select from the list:
[1] : iOS Team Provisioning Profile: * (XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)
[2] : iOS Team Provisioning Profile: com.YOURCOMPANY.helloworld (XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)
(type in the option's number, then hit Enter) [1] : 
```

アプリのバンドルIDと合致するProfileを選択

```
Do you want to collect another ipa export code sign files
(select NO to finish collecting codesign files and continue) [yes/NO]:
```

**yes** を入力

```
Select the ipa export method
Please select from the list:
[1] : development
[2] : app-store
[3] : ad-hoc
[4] : enterprise
(type in the option's number, then hit Enter) [1] :
```

[2] : app-store を選択

```
Do you want to collect another ipa export code sign files
(select NO to finish collecting codesign files and continue) [yes/NO]:
```

**no** を入力

```
Do you want to upload the provisioning profiles and certificates to Bitrise? [yes/no] :
```

**no** を入力

生成された **〜.mobileprovision** と **〜.p12** ファイルをBitriseにドラッグドロップする。

アップロードが完了したら、**〜.mobileprovision** と **〜.p12** ファイルはローカルPCから削除する。<font color="Red">（うっかりGitHubにあげないように）</font>

## Teamの設定確認

Bitrise App *FlutterHelloWorld* の **Team** タブを選択
<img width="1107" alt="90_Team.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/f915db88-c794-7823-8c9f-b1428659e322.png">

**Connected Apple Developer Portal Account** に正しいアカウントが設定されているか確認すること。
<img width="738" alt="91_Team.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/83884db1-599b-7ef7-ab11-3e72c44548c5.png">

## deployビルドの確認

pubspec.yamlの以下をインクリメントし、アプリのバージョンを上げる。

```
version: 1.0.0+2
```

TestFlightの輸出コンプライアンス対策として、info.plistに以下を追加。
<dl>
 <dt>App Uses Non-Exempt encryption</dt><dd>NO</dd>
</dl>

<img width="776" alt="92_info_plist.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/23941c25-9941-f65c-807d-5fbd945cd9a7.png">

commit, pushする。

```
$ git add .
$ git commit -m 'build2'
$ git push
```

Bitrise deploy Workflow のビルドを実行。
<img width="599" alt="50_build_deploy.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/38b48578-4789-6117-8f11-437a025b5554.png">

ビルドが成功し、TestFlightにFlutter Hello Worldアプリがアップロードされることを確認する。

## BitriseとGitHubのWebhook設定

Bitrise App *FlutterHelloWorld* の **Code** タブを選択
<img width="1117" alt="61_Code.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/94a27c7e-d853-48d8-e0db-c539b620abd4.png">

**INCOMINC WEBHOOKS** の **[SETUP MANUALLY]** を押下
**GitHub(Code Push, Pull Request, Tag Push)** を選択
Webhook URLをコピーする

<img width="699" alt="62_IncomingWebhook.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/8fff7782-a12e-9a28-bb44-32eb07f1a50a.png">

[GitHub](https://github.com/) にログイン
*FlutterHelloWorld* リポジトリの **Settings** > **Webhooks** > **[Add webhook]** を押下
<img width="1009" alt="63_GitHubWebhook.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/4ac7e712-8c9d-dc27-e4c2-2b9185157ff9.png">

**Payload URL** に先ほどのWebhook URLを貼り付け、**[Add webhook]** を押下
<img width="745" alt="64_AddWebhook.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/3aef8d83-1f69-d504-24ed-6d63d1d2642c.png">

## GitHubにPushするとBitriseの自動ビルドを実行する設定

Bitrise Workflow Editor の **Triggers** を開く。

PUSHトリガに以下を設定
<dl>
 <dt>Push branch</dt><dd>master</dd>
 <dt>Workflow</dt><dd>primary</dd>
</dl>
<img width="1414" alt="65_Trigger_primary.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/f0c376c0-d91e-8f50-e926-f96a4fa804cf.png">

TAGトリガに以下を設定
<dl>
 <dt>Tag</dt><dd>v\*.\*.\*</dd>
 <dt>Workflow</dt><dd>deploy</dd>
</dl>
<img width="1414" alt="66_Trigger_deploy.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/68537/e59221b6-4abc-c6e9-1015-558e2a73e5b8.png">

<font color="Red">**（[⌘＋S]** での保存を忘れずに）</font>

## Bitrise自動ビルド確認（primary）

アプリのバージョンをあげる。

```:pubspec.yaml
version: 1.0.0+3
```

commit, pushする。

```
$ git add .
$ git commit -m 'build３'
$ git push
```

Bitriseのprimary Workflowが自動実行され、成功すること。

## Bitrise自動ビルド確認（deploy）

バージョンのtagをつけて、pushする。

```
$ git tag v1.0.0+3
$ git push origin v1.0.0+3
```

Bitriseのdeploy Workflowが自動実行され、成功すること。