-
-
Notifications
You must be signed in to change notification settings - Fork 0
新しくアプリを追加する時の手順
- Identity Platform で新しくテナントを作ってプロバイダを設定する
https://console.cloud.google.com/customer-identity/tenants?project=kingu-garage-dev https://console.cloud.google.com/customer-identity/tenants?project=kingu-garage-prod
- Identifiers で App ID を登録する
- App Attest
- Push Notifications
- Sign In with Apple
- ぐらいが必須か
- Identifiers で Services ID を登録する
- dev
- Domains and Subdomains は
kingu-garage-dev.web.app,kingu-garage-dev.firebaseapp.com
- Return URLs は
https://kingu-garage-dev.firebaseapp.com/__/auth/handler
- Domains and Subdomains は
- prod
- Domains and Subdomains は
kingu-garage-prod.web.app,kingu-garage-prod.firebaseapp.com
- Return URLs は
https://kingu-garage-prod.firebaseapp.com/__/auth/handler
- Domains and Subdomains は
- dev
- Keys で Sign In with Apple を有効にした Key を作る
手動で作成する必要がある?
- https://console.cloud.google.com/apis/credentials?project=kingu-garage-dev
- https://console.cloud.google.com/apis/credentials?project=kingu-garage-prod
WIP
BUNDLE_ID=dev.kingu.example
PACKAGE_NAME=dev.kingu.example
NICKNAME=example
firebase --project prod apps:create ios --bundle-id $BUNDLE_ID $NICKNAME
firebase --project prod apps:create android --package-name $PACKAGE_NAME $NICKNAME
firebase --project dev apps:create ios --bundle-id "$BUNDLE_ID.dev" $NICKNAME
firebase --project dev apps:create android --package-name "$PACKAGE_NAME.dev" $NICKNAME
Firebase プロジェクトの URL
FIREBASE_PROJECT_DEV_URL="https://console.firebase.google.com/u/0/project/kingu-garage-dev/settings"
FIREBASE_PROJECT_PROD_URL="https://console.firebase.google.com/u/0/project/kingu-garage-prod/settings"
- Identity Platform で作ったテナント ID から末尾のランダムな文字列を除いたものをデータベース名として作成する
# テナントIDが foo-1234567890 の場合
DATABASE=foo
firebase --project prod firestore:databases:create $DATABASE \
--location=asia-northeast1 \
--delete-protection ENABLED
firebase --project dev firestore:databases:create $DATABASE \
--location=asia-northeast1 \
--delete-protection ENABLED
cp firebase/firestore/template.firestore.rules firebase/firestore/firestore.$DATABASE.rules
cp firebase/firestore/template.firestore.default.indexes.json firebase/firestore/firestore.$DATABASE.indexes.json
firestore
に追記する
firebase --project dev apps:list
open firebase/remoteconfig/template.dev.json
firebase --project prod apps:list
open firebase/remoteconfig/template.prod.json
-
folders
に追加 -
jest.disabledWorkspaceFolders
に追加 -
conventionalCommits.scopes
に追加
NEW_PACKAGE=foo
flutter create --org dev.kingu --project-name $NEW_PACKAGE --platforms ios,android --template app packages/$NEW_PACKAGE
open packages/obento/pubspec.yaml
open packages/$NEW_PACKAGE/pubspec.yaml
sed -i '' -e '/# .*/d' packages/$NEW_PACKAGE/pubspec.yaml
sed -i '' -e '/description: /d' packages/$NEW_PACKAGE/pubspec.yaml
sed -i '' -e 's/version: 1.0.0+1/version: 0.0.0+1/g' packages/$NEW_PACKAGE/pubspec.yaml
open packages/obento/README.md
open packages/$NEW_PACKAGE/README.md
melos bootstrap
pod install --repo-update --project-directory=packages/$NEW_PACKAGE/ios
tool/flutterfire_configure.dart のpackages
に追記する
grind flutterfire-configure
NEW_PACKAGE=foo
mkdir -p packages/$NEW_PACKAGE/configs
cp packages/obento/configs/AdHocExportOptions.plist packages/$NEW_PACKAGE/configs/
cp packages/obento/configs/AppStoreExportOptions.plist packages/$NEW_PACKAGE/configs/
16.6
- PROJECT → Runner → Info → Deployment Target
- TARGETS → Runner → General → Minimum Deployment
open packages/$NEW_PACKAGE/ios/Runner.xcworkspace
# 最上部の platform
open packages/$NEW_PACKAGE/ios/Podfile
flutter_additional_ios_build_settings
の下に追加する
target.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '16.6'
end
https://apilevels.com/ でバージョンを確認する。
open packages/$NEW_PACKAGE/android/app/build.gradle
minSdk
を修正する
// TODO: 要確認 TARGETS → Runner → General → Identity → Build を削除する。
open packages/$NEW_PACKAGE/ios/Runner.xcworkspace
defaultConfig.versionCode を修正する。
versionCode = (System.currentTimeMillis() / 1000).toInteger()
open packages/$NEW_PACKAGE/android/app/build.gradle
# 余分な変数の定義があれば消す
cp packages/obento/ios/Flutter/Debug-dev.xcconfig packages/$NEW_PACKAGE/ios/Flutter/Debug-dev.xcconfig
cp packages/obento/ios/Flutter/Debug-prod.xcconfig packages/$NEW_PACKAGE/ios/Flutter/Debug-prod.xcconfig
cp packages/obento/ios/Flutter/Release-dev.xcconfig packages/$NEW_PACKAGE/ios/Flutter/Release-dev.xcconfig
cp packages/obento/ios/Flutter/Release-prod.xcconfig packages/$NEW_PACKAGE/ios/Flutter/Release-prod.xcconfig
cp packages/obento/ios/Flutter/Profile-dev.xcconfig packages/$NEW_PACKAGE/ios/Flutter/Profile-dev.xcconfig
cp packages/obento/ios/Flutter/Profile-prod.xcconfig packages/$NEW_PACKAGE/ios/Flutter/Profile-prod.xcconfig
Xcode でデフォルトの xcconfig
は削除する。
open packages/$NEW_PACKAGE/ios/Runner.xcworkspace
open packages/$NEW_PACKAGE/ios/Flutter
エンコードした App ID
を確認する
open $FIREBASE_PROJECT_DEV_URL/general
open $FIREBASE_PROJECT_PROD_URL/general
DEV_FIREBASE_ENCODED_APP_ID=FIXME
PROD_FIREBASE_ENCODED_APP_ID=FIXME
sed -i '' -e "s/FIREBASE_ENCODED_APP_ID = .*/FIREBASE_ENCODED_APP_ID = $DEV_FIREBASE_ENCODED_APP_ID/g" packages/$NEW_PACKAGE/ios/Flutter/Debug-dev.xcconfig
sed -i '' -e "s/FIREBASE_ENCODED_APP_ID = .*/FIREBASE_ENCODED_APP_ID = $DEV_FIREBASE_ENCODED_APP_ID/g" packages/$NEW_PACKAGE/ios/Flutter/Release-dev.xcconfig
sed -i '' -e "s/FIREBASE_ENCODED_APP_ID = .*/FIREBASE_ENCODED_APP_ID = $DEV_FIREBASE_ENCODED_APP_ID/g" packages/$NEW_PACKAGE/ios/Flutter/Profile-dev.xcconfig
sed -i '' -e "s/FIREBASE_ENCODED_APP_ID = .*/FIREBASE_ENCODED_APP_ID = $PROD_FIREBASE_ENCODED_APP_ID/g" packages/$NEW_PACKAGE/ios/Flutter/Debug-prod.xcconfig
sed -i '' -e "s/FIREBASE_ENCODED_APP_ID = .*/FIREBASE_ENCODED_APP_ID = $PROD_FIREBASE_ENCODED_APP_ID/g" packages/$NEW_PACKAGE/ios/Flutter/Release-prod.xcconfig
sed -i '' -e "s/FIREBASE_ENCODED_APP_ID = .*/FIREBASE_ENCODED_APP_ID = $PROD_FIREBASE_ENCODED_APP_ID/g" packages/$NEW_PACKAGE/ios/Flutter/Profile-prod.xcconfig
DEV_REVERSED_CLIENT_ID=`plutil -convert json -o - packages/$NEW_PACKAGE/ios/dev/GoogleService-Info.plist | jq --raw-output .REVERSED_CLIENT_ID`
PROD_REVERSED_CLIENT_ID=`plutil -convert json -o - packages/$NEW_PACKAGE/ios/prod/GoogleService-Info.plist | jq --raw-output .REVERSED_CLIENT_ID`
sed -i '' -e "s/GOOGLE_SERVICE_REVERSED_CLIENT_ID = .*/GOOGLE_SERVICE_REVERSED_CLIENT_ID = $DEV_REVERSED_CLIENT_ID/g" packages/$NEW_PACKAGE/ios/Flutter/Debug-dev.xcconfig
sed -i '' -e "s/GOOGLE_SERVICE_REVERSED_CLIENT_ID = .*/GOOGLE_SERVICE_REVERSED_CLIENT_ID = $DEV_REVERSED_CLIENT_ID/g" packages/$NEW_PACKAGE/ios/Flutter/Release-dev.xcconfig
sed -i '' -e "s/GOOGLE_SERVICE_REVERSED_CLIENT_ID = .*/GOOGLE_SERVICE_REVERSED_CLIENT_ID = $DEV_REVERSED_CLIENT_ID/g" packages/$NEW_PACKAGE/ios/Flutter/Profile-dev.xcconfig
sed -i '' -e "s/GOOGLE_SERVICE_REVERSED_CLIENT_ID = .*/GOOGLE_SERVICE_REVERSED_CLIENT_ID = $PROD_REVERSED_CLIENT_ID/g" packages/$NEW_PACKAGE/ios/Flutter/Debug-prod.xcconfig
sed -i '' -e "s/GOOGLE_SERVICE_REVERSED_CLIENT_ID = .*/GOOGLE_SERVICE_REVERSED_CLIENT_ID = $PROD_REVERSED_CLIENT_ID/g" packages/$NEW_PACKAGE/ios/Flutter/Release-prod.xcconfig
sed -i '' -e "s/GOOGLE_SERVICE_REVERSED_CLIENT_ID = .*/GOOGLE_SERVICE_REVERSED_CLIENT_ID = $PROD_REVERSED_CLIENT_ID/g" packages/$NEW_PACKAGE/ios/Flutter/Profile-prod.xcconfig
Based on Configuration File
で Debug-dev.xcconfig
などを選択する。
Debug-dev
Release-dev
Profile-dev
open packages/$NEW_PACKAGE/ios/Runner.xcworkspace
open packages/$NEW_PACKAGE/ios/Runner.xcworkspace
sed -i '' -e "s/buildConfiguration = \"Debug\"/buildConfiguration = \"Debug-dev\"/g" packages/$NEW_PACKAGE/ios/Runner.xcodeproj/xcshareddata/xcschemes/dev.xcscheme
sed -i '' -e "s/buildConfiguration = \"Release\"/buildConfiguration = \"Release-dev\"/g" packages/$NEW_PACKAGE/ios/Runner.xcodeproj/xcshareddata/xcschemes/dev.xcscheme
sed -i '' -e "s/buildConfiguration = \"Profile\"/buildConfiguration = \"Profile-dev\"/g" packages/$NEW_PACKAGE/ios/Runner.xcodeproj/xcshareddata/xcschemes/dev.xcscheme
sed -i '' -e "s/buildConfiguration = \"Debug\"/buildConfiguration = \"Debug-prod\"/g" packages/$NEW_PACKAGE/ios/Runner.xcodeproj/xcshareddata/xcschemes/prod.xcscheme
sed -i '' -e "s/buildConfiguration = \"Release\"/buildConfiguration = \"Release-prod\"/g" packages/$NEW_PACKAGE/ios/Runner.xcodeproj/xcshareddata/xcschemes/prod.xcscheme
sed -i '' -e "s/buildConfiguration = \"Profile\"/buildConfiguration = \"Profile-prod\"/g" packages/$NEW_PACKAGE/ios/Runner.xcodeproj/xcshareddata/xcschemes/prod.xcscheme
open packages/$NEW_PACKAGE/ios/Runner.xcworkspace
open packages/$NEW_PACKAGE/ios/Podfile
以下に置換する。
project 'Runner', {
'Debug-dev' => :debug,
'Debug-prod' => :debug,
'Profile-dev' => :release,
'Profile-prod' => :release,
'Release-dev' => :release,
'Release-prod' => :release,
}
open packages/$NEW_PACKAGE/ios/Runner.xcworkspace
1024x1024 のアイコンを追加する。
AppIcon
または AppIconDev
に変更する。
open packages/$NEW_PACKAGE/ios/Runner/Info.plist
名称は InfoPlist
で、Runner ディレクトリの下に作成する。
CFBundleDisplayName
と CFBundleName
に日本語の名称に修正する。
open packages/$NEW_PACKAGE/ios/Runner/InfoPlist.xcstrings
echo "ITSAppUsesNonExemptEncryption" | pbcopy
open packages/$NEW_PACKAGE/ios/Runner/Info.plist
KEYSTORE_OUT_DIR=packages/$NEW_PACKAGE/android/app
KEYSTORE_PASS_DEBUG=$(openssl rand -base64 32 | tr -d /=+ | cut -c -32)
KEYSTORE_PASS_UPLOAD=$(openssl rand -base64 32 | tr -d /=+ | cut -c -32)
keytool -genkey -v -keystore $KEYSTORE_OUT_DIR/debug-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias debug -keypass $KEYSTORE_PASS_DEBUG -storepass $KEYSTORE_PASS_DEBUG
keytool -genkey -v -keystore $KEYSTORE_OUT_DIR/upload-keystore.jks -keyalg RSA -keysize 2048 -validity 10000 -alias upload -keypass $KEYSTORE_PASS_UPLOAD -storepass $KEYSTORE_PASS_UPLOAD
android
の最上部に以下を追記する。
if (file("signing-configs-debug.gradle").exists()) {
apply from: "signing-configs-debug.gradle", to: android
}
if (file("signing-configs-release.gradle").exists()) {
apply from: "signing-configs-release.gradle", to: android
}
echo "signingConfigs {
debug {
storeFile file(\"debug-keystore.jks\")
storePassword \"${KEYSTORE_PASS_DEBUG}\"
keyAlias \"debug\"
keyPassword \"${KEYSTORE_PASS_DEBUG}\"
}
}" > packages/$NEW_PACKAGE/android/app/signing-configs-debug22.gradle
echo "signingConfigs {
release {
storeFile file(\"upload-keystore.jks\")
storePassword \"${KEYSTORE_PASS_UPLOAD}\"
keyAlias \"upload\"
keyPassword \"${KEYSTORE_PASS_UPLOAD}\"
}
}" > packages/$NEW_PACKAGE/android/app/signing-configs-release.gradle
open packages/$NEW_PACKAGE/android/app/
SHA を確認する。
keytool -list -v -alias debug -storepass $KEYSTORE_PASS_DEBUG --keystore $KEYSTORE_OUT_DIR/debug-keystore.jks
登録する。
APP_SHA1_DEBUG="FIXME"
APP_SHA256_DEBUG="FIXME"
APP_ID_DEV=$(jq -r '.flutter.platforms.android.buildConfigurations."src/dev".appId' packages/$NEW_PACKAGE/firebase.json)
firebase --project dev apps:android:sha:create $APP_ID_DEV $APP_SHA1_DEBUG
firebase --project dev apps:android:sha:create $APP_ID_DEV $APP_SHA256_DEBUG
buildTypes {
debug {
signingConfig = signingConfigs.debug
}
release {
signingConfig = signingConfigs.release
}
}
open packages/$NEW_PACKAGE/android/app/build.gradle
android
の中に以下を追記追記する。
flavorDimensions "default"
productFlavors {
dev {
dimension "default"
applicationIdSuffix ".dev"
}
prod {
dimension "default"
}
}
mkdir -p packages/$NEW_PACKAGE/android/app/src/main/res/values
mkdir -p packages/$NEW_PACKAGE/android/app/src/main/res/values-en
mkdir -p packages/$NEW_PACKAGE/android/app/src/main/res/values-ja
APP_NAME_STRINGS_XML='''<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">FIXME</string>
</resources>'''
echo "$APP_NAME_STRINGS_XML" > packages/$NEW_PACKAGE/android/app/src/main/res/values/strings.xml
echo "$APP_NAME_STRINGS_XML" > packages/$NEW_PACKAGE/android/app/src/main/res/values-en/strings.xml
echo "$APP_NAME_STRINGS_XML" > packages/$NEW_PACKAGE/android/app/src/main/res/values-ja/strings.xml
open packages/$NEW_PACKAGE/android/app/src/main/res/values/strings.xml
open packages/$NEW_PACKAGE/android/app/src/main/res/values-en/strings.xml
open packages/$NEW_PACKAGE/android/app/src/main/res/values-ja/strings.xml
android:label="@string/app_name"
に修正する。
open packages/$NEW_PACKAGE/android/app/src/main/AndroidManifest.xml
rm -r packages/$NEW_PACKAGE/android/app/src/main/res/mipmap-*
mkdir -p packages/$NEW_PACKAGE/android/app/src/dev/res
open packages/$NEW_PACKAGE/android/app/src/dev/res
mkdir -p packages/$NEW_PACKAGE/android/app/src/prod/res
open packages/$NEW_PACKAGE/android/app/src/prod/res
https://apps.admob.com/v2/home でアプリを追加してアプリ ID を確認する
NSUserTrackingUsageDescription
も必要だが、リリースするまで AdMob と連携できない。
先んじて追加していると Apple のレビューでリジェクトされるのでこの時点では追加してはならない。
GADApplicationIdentifier
SKAdNetworkItems
open packages/obento/ios/Runner/Info.plist
open packages/$NEW_PACKAGE/ios/Runner/Info.plist
https://apps.admob.com/v2/home でアプリを追加してアプリ ID を確認する。
open packages/$NEW_PACKAGE/android/app/src/main/AndroidManifest.xml
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="FIXME"/>
open packages/$NEW_PACKAGE/android/app/build.gradle
https://mvnrepository.com/artifact/com.google.android.gms/play-services-ads で最新のバージョンを確認する。
dependencies {
implementation 'com.google.android.gms:play-services-ads:23.0.0'
}
open https://apps.admob.com/v2/home
cp packages/core/analysis_options.yaml packages/$NEW_PACKAGE/
(cd packages/$NEW_PACKAGE && ln -s ../core/build.yaml .)
cp packages/obento/lib/main.dart packages/$NEW_PACKAGE/lib/
cp packages/obento/lib/main_dev.dart packages/$NEW_PACKAGE/lib/
cp packages/obento/lib/main_prod.dart packages/$NEW_PACKAGE/lib/
cp packages/obento/lib/my_app.dart packages/$NEW_PACKAGE/lib/
cp packages/obento/lib/my_go_router.dart packages/$NEW_PACKAGE/lib/
mkdir -p packages/$NEW_PACKAGE/lib/features/onboarding/application
cp packages/obento/lib/features/onboarding/application/onboarding_route.dart packages/$NEW_PACKAGE/lib/features/onboarding/application/
mkdir -p packages/$NEW_PACKAGE/lib/features/onboarding/presentation
cp packages/obento/lib/features/onboarding/presentation/onboarding_page.dart packages/$NEW_PACKAGE/lib/features/onboarding/presentation/
mkdir -p packages/$NEW_PACKAGE/lib/features/home/application
cp packages/obento/lib/features/home/application/home_route.dart packages/$NEW_PACKAGE/lib/features/home/application/
mkdir -p packages/$NEW_PACKAGE/lib/features/home/presentation
touch packages/$NEW_PACKAGE/lib/features/home/presentation/home_page.dart
mkdir -p packages/$NEW_PACKAGE/lib/i18n
echo "{}" > packages/$NEW_PACKAGE/lib/i18n/strings_ja.i18n.json
echo "{}" > packages/$NEW_PACKAGE/lib/i18n/strings_en.i18n.json
(cd packages/$NEW_PACKAGE && dart run flutter_native_splash:create)
mkdir -p packages/$NEW_PACKAGE/.vscode
cp packages/onebto/.vscode/launch.json packages/$NEW_PACKAGE/.vscode/
melos run build_runner:build --no-select && \
melos run build:ipa:dev && \
melos run build:apk:dev
open https://appstoreconnect.apple.com/apps
open $FIREBASE_PROJECT_DEV_URL/general/ios:$BUNDLE_ID
open $FIREBASE_PROJECT_PROD_URL/general/ios:$BUNDLE_ID
melos run build:ipa:prod:upload
open https://play.google.com/console/u/0/developers/create-new-app
- Google Cloud プロジェクトのリンク
初回は対応する Package が無く失敗するので クローズドテスト
を作成して手動でアップロードすること。
melos run build:appbundle:prod:upload
open packages/$NEW_PACKAGE/build/app/outputs/bundle/prodRelease
設定 → アプリの署名から SHA を確認する。
APP_SHA1_UPLOAD="FIXME"
APP_SHA256_UPLOAD="FIXME"
APP_ID_PROD=$(jq -r '.flutter.platforms.android.buildConfigurations."src/prod".appId' packages/$NEW_PACKAGE/firebase.json)
firebase --project prod apps:android:sha:create $APP_ID_PROD $APP_SHA1_UPLOAD
firebase --project prod apps:android:sha:create $APP_ID_PROD $APP_SHA256_UPLOAD
cp -rf packages/obento/.fastlane packages/$NEW_PACKAGE/
find packages/$NEW_PACKAGE/.fastlane -type f -name 'name.txt' -exec sh -c 'echo "TODO" > {}' \;
find packages/$NEW_PACKAGE/.fastlane -type f -name 'subtitle.txt' -exec sh -c 'echo "TODO" > {}' \;
find packages/$NEW_PACKAGE/.fastlane -type f -name 'description.txt' -exec sh -c 'echo "TODO" > {}' \;
find packages/$NEW_PACKAGE/.fastlane -type f -name 'promotional_text.txt' -exec sh -c 'echo "TODO" > {}' \;
open https://docs.fastlane.tools/actions/deliver/#reference
open packages/$NEW_PACKAGE/.fastlane/primary_category.txt
open packages/$NEW_PACKAGE/.fastlane/secondary_category.txt
grind upload-app-privacy-details --package=$NEW_PACKAGE --noAds
(要確認) クローズドテストが存在していれば失敗しない? アプリ名や説明は fastlane でアップロードするが、初回は手動で設定する必要があるので適当に設定する。
open https://play.google.com/console
open packages/$NEW_PACKAGE/.fastlane/metadata/android
Slack、BigQuery、AdMob、Google Play
open $FIREBASE_PROJECT_DEV_URL/integrations
open $FIREBASE_PROJECT_PROD_URL/integrations
open $FIREBASE_PROJECT_DEV_URL
open $FIREBASE_PROJECT_PROD_URL
SIGNING_CONFIGS_BASE64=$(base64 -i packages/$NEW_PACKAGE/android/app/signing-configs-release.gradle)
UPLOAD_KEYSTORE_BASE64=$(base64 -i packages/$NEW_PACKAGE/android/app/upload-keystore.jks)
echo "SIGNING_CONFIGS_${NEW_PACKAGE}_BASE64=$SIGNING_CONFIGS_BASE64" >> .env
echo "UPLOAD_KEYSTORE_${NEW_PACKAGE}_BASE64=$UPLOAD_KEYSTORE_BASE64" >> .env
gh secret set --env-file .env
rm .env
Android Signing に追加する
open .github/workflows/build.yaml
cp packages/obento/test/dart_test.yaml packages/$NEW_PACKAGE/
追加しておかないと CI が失敗する。
echo "import 'package:core/gen/strings.g.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import '../../core/test/core.dart';
void main() {
goldenTestCombo(
testName: 'example',
widget: Container(),
supportedLocales: AppLocaleUtils.supportedLocales,
cupertinoThemeData: const CupertinoThemeData(),
materialThemeData: ThemeData(),
providerOverrides: [],
skip: true,
);
}" > packages/$NEW_PACKAGE/test/example_golden_test.dart
activity タグに追記
android:screenOrientation="portrait"
open packages/$NEW_PACKAGE/android/app/src/main/AndroidManifest.xml
UISupportedInterfaceOrientations
を修正する。
iPad をサポートしない場合は UISupportedInterfaceOrientations~ipad
は不要なので削除する。
open packages/$NEW_PACKAGE/ios/Runner/Info.plist
cp -r packages/obento/obento/test/feature_graphic packages/$NEW_PACKAGE/obento/test/feature_graphic
melos run flutter:golden:update
open packages/$NEW_PACKAGE/test/feature_graphic
cwebp -q 80 packages/$NEW_PACKAGE/test/feature_graphic/ogp.png -o "firebase/public/assets/$NEW_PACKAGE-ogp.webp"
cp packages/$NEW_PACKAGE/assets/images/app_icon.webp firebase/public/$NEW_PACKAGE-app_icon.webp
code firebase/public/index.html