はじめに
この記事はFlutter Advent Calendar 2019 (#2) 20日目の記事です。 その1 も合わせて今年もFlutterの盛り上がりを感じますね!
やってみること
昨年のアドベンドカレンダーでは、ビルドスクリプトとかCI/CDについて書いてました。 CodeMagic が登場し、かなり慌てたことを覚えています。
1年経ったのでなにかしら新しいことに挑戦したい……不安定なものを触りたい……破壊的な変更に巻き込まれたい……でも調べるのが大変すぎるのはつらい……ということで、Flutter for WebのCI/CDに挑戦したいと思います。 よろしくお願いします。
開発環境
Flutterは先日リリースされた 1.12.13
を利用します。
Webもベータに格上げされたので、ちょうどいい感じです。
~/workspace » flutter --version Flutter 1.12.13+hotfix.5 • channel stable • https://github.com/flutter/flutter.git Framework • revision 27321ebbad (7 days ago) • 2019-12-10 18:15:01 -0800 Engine • revision 2994f7e1e6 Tools • Dart 2.7.0
Flutter for Webの準備
まずはプロジェクトを作成していきます。 Web版のプロジェクトを作る場合は、まず下記の公式チュートリアルを確認するのが一番早く、確実です。
2019年12月18日現在(このブログを書いている日です)、まだstable版では使えないのでbetaチャンネルに変更します。
stable版に格上げされたら、下のコードは不要になります。 enable-web
は残るような気もするけど。
$ flutter channel beta $ flutter upgrade $ flutter config --enable-web
完了したら flutter devices
を呼び出してみます。
筆者の環境では、ドキュメント通りChromeが表示されました。
~/workspace » flutter devices 2 connected devices: Chrome • chrome • web-javascript • Google Chrome 79.0.3945.79 Web Server • web-server • web-javascript • Flutter Tools
続いて、Githubにリポジトリを作成します。
今回のプロジェクト名は flutter_web_deploy
としました。
すでに flutter run -d chrome
するとChromeで動作を確認できます。
また flutter build web
することで /build/web/
ディレクトリに index.html
などが作成され、公開する準備が整っています
ここで終わってしまうとあまりにもあっさりしてるので、次はBitriseと組み合わせてみましょう。
Bitrise上でFlutter for Webをビルドする
お馴染み、BitriseにログインしてGithubのリポジトリと連携していきます。
そのあとは先ほどのステップをそのままBitrise上で再現してみると。
見事、Bitrise上でFlutter for Webのビルドを実現できました。 プロジェクトをPublicにしてあるので、興味のある方は見てみてください。
bitrise.yml
は以下の通りです。
--- format_version: '8' default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git project_type: flutter trigger_map: [] workflows: deploy_web: steps: - activate-ssh-key@4.0.5: run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}' - git-clone@4.0.17: {} - flutter-installer@0.11.0: inputs: - version: beta - is_update: 'false' - script@1.1.5: title: flutter config inputs: - content: |- #!/usr/bin/env bash # fail if any commands fails set -e # debug log set -x flutter config --enable-web - script@1.1.5: title: Build flutter for web inputs: - content: |- #!/usr/bin/env bash # fail if any commands fails set -e # debug log set -x flutter build web - create-zip@0.9.0: inputs: - source_path: build/web - destination: "$BITRISE_DEPLOY_DIR" - deploy-to-bitrise-io@1.9.4: {} app: envs: - opts: is_expand: false BITRISE_FLUTTER_PROJECT_LOCATION: "." - opts: is_expand: false BITRISE_PROJECT_PATH: ios/Runner.xcworkspace - opts: is_expand: false BITRISE_SCHEME: Runner - opts: is_expand: false BITRISE_EXPORT_METHOD: app-store
これでGithubのmasterブランチへのプッシュや、タグの作成に応じてFlutter for Webのビルドができるようになりました! Android/iOS版のCI/CDと組み合わせて実行できます。(ただ、実行時間的に課金プランになりますが)
12月25日にmonoさんが「FlutterでモバイルとWeb両対応のアプリを作るノウハウ」を書いてくださる予定です。 ソースの共通化をしたら、CI/CDも共通化するニーズが高まる気がするので、今後はこの手の構成が増えるのではないかなーと思っています。
デプロイも自動化したい
おわろうかと思ったのですが続きます。
上記のステップでは「zipファイルをダウンロードし、温かみのある手動アップロード」作業が必要になっています。 令和元年もそろそろ終わってしまう昨今、もう一歩自動化を進めたいところですね?
ということで、Firebase Hostingを利用した自動化に進みましょう。
Firebase Hostingは、ご存知Firebaseが提供するWebホストプロバイダーです。
ドキュメントはこちら。
今回はCI/CD用の設定をする必要があるので、最初に手元の環境でトークンを取得しておきます。 手順は次のドキュメントを確認してください。
こちらでゲットしたトークンを、BitriseのSercretsに保存します。
(筆者は FIREBASE_TOKEN
として追加しました。後ほど変数名として利用します。)
続いて、ローカルのプロジェクトでFirebase Hostingの設定を行います。 以下、コマンド処理のイメージです。
$ cd workspace/firebase_web_deploy/ $ firebase login $ firebase init
上記のステップを踏むと firebase.json
ファイルと public
ディレクトリが、 firebase_web_deploy
の下に生成されます。
public
ディレクトリに追加したファイルが firebase deploy
することでアップロードされる、という理解でほぼ大丈夫です。もしもいろいろと設定したい場合には、コマンドの途中で変更したりjsonファイルをいじってみてください。
さて、Firebaseのプロジェクトを新規作成か既存への追加を行ったことかと思います。
このときに指定した Project ID を、トークンと同じようにBItriseの環境変数に定義しましょう。
(筆者は FIREBSSE_PROJECT_ID
として定義しました。)
あとは public
ディレクトリの中身をFlutter for Webの成果物で置き換え、アップロードするだけです。
先ほどのzip処理の次に、簡単なスクリプトを追加します。
#!/bin/bash curl -sL firebase.tools | bash cp -rf build/web/* public/ firebase deploy --project ${FIREBASE_PROJECT_ID} --token ${FIREBASE_TOKEN}
ステップをワクワクしながら走らせ、完了後にHosting先を見てみると……お馴染みのアプリが動いています!
flutter-web-deploy-demo.firebaseapp.com
おめでとうございます!アップロード処理まで自動化できました。 Webにはストア審査がないので、これで1日に二桁回数のリリースもできちゃいますね!
ステップを一つ追加しただけですが、定義したymlファイルは下のようになります。
workflows: deploy_web_firebase: steps: - activate-ssh-key@4.0.5: run_if: '{{getenv "SSH_RSA_PRIVATE_KEY" | ne ""}}' - git-clone@4.0.17: {} - flutter-installer@0.11.0: inputs: - version: beta - is_update: 'false' - script@1.1.5: title: flutter config inputs: - content: |- #!/usr/bin/env bash # fail if any commands fails set -e # debug log set -x flutter config --enable-web - script@1.1.5: title: Build flutter for web inputs: - content: |- #!/usr/bin/env bash # fail if any commands fails set -e # debug log set -x flutter build web - create-zip@0.9.0: inputs: - source_path: build/web - destination: "$BITRISE_DEPLOY_DIR" - deploy-to-bitrise-io@1.9.4: {} - script@1.1.5: inputs: - content: |- #!/usr/bin/env bash # fail if any commands fails set -e # debug log set -x curl -sL firebase.tools | bash cp -rf build/web/* public/ firebase deploy --project ${FIREBASE_PROJECT_ID} --token ${FIREBASE_TOKEN} title: Firebase Hosting
Firebase Hostingをする場合でも、後ほどなんらかの事情でWebアプリのロールバックする可能性もあるため、zipファイルをダウンロード可能な状態にして保存しておくのが良さそうな気もします。 この辺りは、Webアプリエンジニアの方の知見をいただきたいところですね。
おまけ
Github Actionsも試してみたところ、さっくりデプロイできました。
Create main.yml · koji-1009/flutter_web_deploy@d0dfd12 · GitHub
利用したワークフローは下の通りです。 これで意図通りに動くのがすごい。
name: CI on: push: branches: - master jobs: build: runs-on: ubuntu-latest steps: - uses: actions/checkout@v1 - name: Install flutter (beta channel) uses: subosito/flutter-action@v1 with: channel: 'beta' - name: Enable Flutter for Web run: flutter config --enable-web - name: Build Flutter for Web run: flutter build web - name: copy resource run: cp -rf build/web/* public/ - name: Firebase GitHub Action uses: pizzafox/firebase-action@1.0.7 env: PROJECT_ID: "flutter-web-deploy-demo" FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }} with: args: deploy
FlutterとFirebase CLIのActionsがあるので、そちらを適宜利用しています。 Flutterのビルドコマンドが整理されているため、全体的にすっきりしてますね。
コードは flutter_web_deploy/main.yml at master · koji-1009/flutter_web_deploy · GitHub にあるので、よければご確認ください。 実行速度もBitriseとほぼ変わりません。WebだけならGithub Actionsだけで対応できちゃいそうです。
終わりに
BitriseとGithub Actionsを利用して、Flutter for WebのFirebase Hostingを利用したデプロイを試してみました。 ささっと環境構築して、ささっと配信環境を作って、ささっとアプリ開発していけるようになり嬉しい限りです。
ぱっと考えてみるとCircleCIでも同じことができるので、手の空いたときにymlファイルを書いてみたいなと思います。 2年連続でCIについて書いたから、来年はCircleCIでなにか書けるといい気もする……。
それでは、Flutterを遊び倒していきましょう! 明日は akio_r さんの記事です。お楽しみに〜。