FlutterアプリをGitHub Actionsを使ってwebとapkを同時にbuildし公開するまで
はじめに
私は普段休みの日の朝を中心に、普段家庭内の生活に使ったり、子供と遊ぶための便利なアプリなどを作ってます。
個人開発なので、あまり手間をかけずにサクッと色んなものを作りたいと思っていたときに
Flutterに出会いました。
Flutterはほぼローコード開発ツールやノーコードツールと同じくらいと言っていいくらい
あまり手間がかからずそれなりのアプリをサクッと開発できます。
はじめは、手元でbuildし、いちいちサーバにdeployするといった作業をしていましたが、貴重な土日の朝の時間
少しでも手間を減らしたいと思っていました。
手元ではコードを書いてテストを走らせ、かんたんにエミュレータで確認すると言った作業だけに集中し、
buildやdeployはGitHub Actionsに任せようと思い色々調査をした結果をメモしています。
flutter web を使ってwebアプリを gh-pagesに公開する
前提
この記事では前提として下記を想定しています。
- Flutterでアプリ開発をしている
- GitHub上にレポジトリが配置されている
- レポジトリ上にgh-pagesというbranchが作成されている
gh-pagesの設定
まずはweb版をdeployするための下地としてgh-pagesを設定しましょう
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に行き設定しましょう
手元で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, ALIASとKEY_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にこれらを設定していきます
右上のNew secretを押下してメモしたKEY_STORE_PASSWORD, KEY_PASSWORD, ALIASとSIGNING_KEY
を設定しましょう
.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 にアプリが配置されます
デモアプリはこちら
おわりに
ちょっと長かったですが、なんとかこれで
web appとAndroid apk(野良アプリ)を gh-pages上に同時公開することができました。
すごく極端な話、Android Studioがなくても GitHub上でかんたんなbug fixとか編集してしまえば
自動的にGitHub Actionsが走り、ビルドされ、Deployまでできます
Discussion