🍣

FlutterアプリをGitHub Actionsを使ってwebとapkを同時にbuildし公開するまで

2020/10/26に公開

はじめに

私は普段休みの日の朝を中心に、普段家庭内の生活に使ったり、子供と遊ぶための便利なアプリなどを作ってます。
個人開発なので、あまり手間をかけずにサクッと色んなものを作りたいと思っていたときに
Flutterに出会いました。
Flutterはほぼローコード開発ツールやノーコードツールと同じくらいと言っていいくらい
あまり手間がかからずそれなりのアプリをサクッと開発できます。
はじめは、手元でbuildし、いちいちサーバにdeployするといった作業をしていましたが、貴重な土日の朝の時間
少しでも手間を減らしたいと思っていました。
手元ではコードを書いてテストを走らせ、かんたんにエミュレータで確認すると言った作業だけに集中し、
buildやdeployはGitHub Actionsに任せようと思い色々調査をした結果をメモしています。

flutter web を使ってwebアプリを gh-pagesに公開する

前提

この記事では前提として下記を想定しています。

  • Flutterでアプリ開発をしている
  • GitHub上にレポジトリが配置されている
  • レポジトリ上にgh-pagesというbranchが作成されている

gh-pagesの設定

まずはweb版をdeployするための下地としてgh-pagesを設定しましょう
https://github.com/[あなたのユーザID]/[対象のレポジトリ]/settings
に行き gh-pagesの設定を下記のようにします
image.png

GitHub Actionsの設定

/path/to/[flutterアプリのルート]/.github/workflows/flutter.yaml
を作成しましょう

name: Flutter CI
'on':
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout 🛎️
        uses: actions/checkout@v2
      - name: Flutter setting
        uses: subosito/flutter-action@v1
        with:
          channel: beta
      - name: "Install and Build  🔧"
        run: |
          flutter config --enable-web
          flutter pub get
          flutter test
          flutter build web
      - name: "Deploy 🚀"
        uses: JamesIves/github-pages-deploy-action@releases/v3
        with:
          GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
          BRANCH: gh-pages
          FOLDER: build/web

これをmainにpushしましょう

web appがdeployされていることを確認しましょう

pushすると自動的にGitHub Actions Flutter CIが走ると思います
こちらが終わったら(自分のレポジトリの場合は3分位かかります^^;)
https://[あなたのgithubカウント].github.io/[レポジトリ名]/
に行ってあなたのFlutterアプリが動くかどうか確認してください

apkをGitHub Actionsを使ってsignする

なぜsignが必要か

自分の場合これを調査したきっかけは、firebase_authを使った場合、
ではkeystoreのSHA-1 fingerprintをfirebase consoleに設定しないと
google_sign_inがAndroid app版では動かないとう症状に悩まされたことと、
基本的にはbuildはGitHub Actionsを使ってやりたいなと思っていたたため、これを同時に出来る方法が無いか調査していました。
またセキュリティ上の理由から、keystoreファイルや生のパスワードをgithub repositryにpushすることは流石に嫌ですよね。
もしこれをやってしまうと悪意を持った人がリポジトリにアクセスし、
Google Play にアプリをあなたになりすまして公開ができるようになってしまいます。
以下の章ではSigning Flutter Android apps for release in GitHub Actionsを参考にさせていただき
GitHub Actionsを使ってflutter build apkを使って安全にAndroidをリリース署名を行う方法を解説します。

keystoreを作成する

Signing the app にある方法を使って
keystoreを作成してください
例えばWindowsであれば

$ keytool -genkey -v -keystore c:\Users\USER_NAME\key.jks -storetype JKS -keyalg RSA -keysize 2048 -validity 10000 -alias [ALIAS]

このようにして作成します。
また作成時に利用したKEY_STORE_PASSWORD, KEY_PASSWORD, ALIASは忘れないで覚えるかメモしてください

SIGNING_KEYを取得する

opensslコマンドを使えば SIGNING_KEYを取得できます

$ openssl.exe base64 -A -in c:\Users\USER_NAME\key.jks
/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.....xxxxxxxxxxxxxx=

出力されたながーい文字列をコピペしてメモしておきましょう

(option) SHA-1 fingerprintをfirebase consoleのAndroidアプリに設定しましょう

自分がもともとハマっていたのはここで、先程つくったkeystoreを下記のコマンドを使ってSHA-1 fingerprintを得て
それをメモしておきましょう

$ keytool.exe  -list -v --alias [ALIAS] -keystore c:\Users\USER_NAME\key.jks
Enter keystore password:  [KEY_STORE_PASSWORD]
Alias name: [ALIAS]
Creation date: YYYY/MM/DD
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: C=US, O=Android, CN=Android Debug
Issuer: C=US, O=Android, CN=Android Debug
Serial number: 1
Valid from: Fri Sep 25 20:27:37 JST 2020 until: Sun Sep 18 20:27:37 JST 2050
Certificate fingerprints:
         MD5:  XX:XX:XX..
         SHA1: XX:XX:XX..
         SHA256: XX:XX:XX..
Signature algorithm name: SHA1withRSA
Subject Public Key Algorithm: 2048-bit RSA key
Version: 1

上記に表示されるSHA1 XX:XX:XXとSHA256XX:XX:XXをコピーして
Firebase consoleに行き設定しましょう
image.png

手元でbuildする準備をする

key.propertiesを作成

/path/to/[flutterアプリのルート]/android/key.properties
を作成します

storePassword=[先程メモったKEY_STORE_PASSWORD]
keyPassword=[先程メモったKEY_PASSWORD]
keyAlias=[先程メモったALIAS]
storeFile=[c:\Users\USER_NAME\key.jks など]

key.propertiesを.gitignoreに忘れずに入れておきましょう

key.propertiesを公開してしまったら元も子もないので
ちゃんと.gitignoreに入れておきましょう

$ echo android/key.properties >> .gitignore

build.gradleの編集

/path/to/[flutterアプリのルート]/android/app/build.gradle
を編集します
編集する箇所は2つ
まずは key.propertiesがあったら
先程設定した key.propertiesからKEY_STORE_PASSWORD, KEY_PASSWORD, ALIASKEY_PATHを読み込むように編集します
GitHub Actions上では環境変数から読み込むのでelseの中身はGitHub Actions用です

def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
} else {
    keystoreProperties.setProperty('storePassword', System.getenv('KEY_STORE_PASSWORD'));
    keystoreProperties.setProperty('keyPassword', System.getenv('KEY_PASSWORD'));
    keystoreProperties.setProperty('keyAlias', System.getenv('ALIAS'));
    keystoreProperties.setProperty('storeFile', System.getenv('KEY_PATH'));
}

次にsignできるようにbuildTypesの上にsiningConfigsを追加し、
更にbuildTypesもsigningConfigs.releaseに変えましょう

signingConfigs {
        release {
            keyAlias keystoreProperties['keyAlias']
            keyPassword keystoreProperties['keyPassword']
            storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
            storePassword keystoreProperties['storePassword']
        }
    }
    buildTypes {
        release {
            signingConfig signingConfigs.release
        }
    }
    /*
    buildTypes {
        release {
            // TODO: Add your own signing config for the release build.
            // Signing with the debug keys for now, so `flutter run --release` works.
            signingConfig signingConfigs.debug
        }
    }*/

## 手元でbuildしてみましょう

$ flutter build apk
You are building a fat APK that includes binaries for android-arm, android-arm64, android-x64.
If you are deploying the app to the Play Store, it's recommended to use app bundles or split the APK to reduce the APK size.
    To generate an app bundle, run:
        flutter build appbundle --target-platform android-arm,android-arm64,android-x64
        Learn more: https://developer.android.com/guide/app-bundle
    To split the APKs per ABI, run:
        flutter build apk --target-platform android-arm,android-arm64,android-x64 --split-per-abi
        Learn more: https://developer.android.com/studio/build/configure-apk-splits#configure-abi-split
Running Gradle task 'assembleRelease'...                           19.0s
√ Built build\app\outputs\flutter-apk\app-release.apk (7.6MB).

このようにbuildできたら成功です

GitHubのレポジトリのsecretsにこれらを設定していきます

https://github.com/[あなたのユーザID]/[対象のレポジトリ]/settings/secrets
に行って
右上のNew secretを押下してメモしたKEY_STORE_PASSWORD, KEY_PASSWORD, ALIASSIGNING_KEY
を設定しましょう

image.png

.github/workflows/flutter.yamlを編集

さあ 後少しで終わりです
/path/to/[flutterアプリのルート]/.github/workflows/flutter.yaml
を下記のように書き換えましょう

name: Flutter CI
'on':
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout 🛎️
        uses: actions/checkout@v2
      - name: Flutter setting
        uses: subosito/flutter-action@v1
        with:
          channel: beta
      - name: "Install and Build  🔧"
        run: |
          echo $SIGNING_KEY | base64 -d > android/app/key.jks
          flutter config --enable-web
          flutter pub get
          flutter test
          flutter build apk
          flutter build web
          mkdir build/web/apks
          cp build/app/outputs/flutter-apk/*.apk build/web/apks/
        env:
          SIGNING_KEY: ${{ secrets.SIGNING_KEY }}
          KEY_STORE_PASSWORD: ${{ secrets.KEY_STORE_PASSWORD }}
          KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }}
          ALIAS: ${{ secrets.ALIAS }}
          KEY_PATH: key.jks
      - name: "Deploy apk 🚀"
        uses: actions/upload-artifact@v1
        with:
          name: release-apk
          path: build/app/outputs/flutter-apk/app-release.apk
      - name: "Deploy to gh-pages 🚀"
        uses: JamesIves/github-pages-deploy-action@releases/v3
        with:
          GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
          BRANCH: gh-pages
          FOLDER: build/web

これをまたmainにpushしましょう
成功すると
https://[あなたのgithubカウント].github.io/[レポジトリ名]/apks/app-release.apk にアプリが配置されます

デモアプリはこちら

Demo

Demo App

おわりに

ちょっと長かったですが、なんとかこれで
web appとAndroid apk(野良アプリ)を gh-pages上に同時公開することができました。
すごく極端な話、Android Studioがなくても GitHub上でかんたんなbug fixとか編集してしまえば
自動的にGitHub Actionsが走り、ビルドされ、Deployまでできます

Discussion