Skip to content

Commit

Permalink
feat(Android): set up Firebase (#659)
Browse files Browse the repository at this point in the history
* feat(Android): set up Firebase

* shuffle around CI setup

* use separate secrets for separate app IDs

* toss in a potential fix for a flaky test
  • Loading branch information
boringcactus authored Jan 17, 2025
1 parent ac5fdb3 commit ea010f8
Show file tree
Hide file tree
Showing 11 changed files with 45 additions and 7 deletions.
3 changes: 2 additions & 1 deletion .envrc.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
# Firebase - used for Google Analytics collection, required because the library crashes without it
# Find at https://console.firebase.google.com/u/0/project/mbta-app-c574d/settings/general
export FIREBASE_KEY=
export GOOGLE_APP_ID=
export GOOGLE_APP_ID_IOS=
export GOOGLE_APP_ID_ANDROID=

# Optional Variables

Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/android-deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ jobs:
aws secretsmanager get-secret-value --secret-id mobile-app-android-upload-key --output json | jq -r '.SecretBinary' | base64 --decode > upload-keystore.jks
- name: Build Android app
env:
FIREBASE_KEY: ${{ secrets.FIREBASE_KEY }}
GOOGLE_APP_ID_ANDROID: ${{ secrets.GOOGLE_APP_ID_ANDROID_PROD }}
KEYSTORE_FILE: "${{ github.workspace }}/androidApp/upload-keystore.jks"
KEYSTORE_PASSWORD: ${{ env.MOBILE_APP_ANDROID_UPLOAD_KEY_PASSPHRASE }}
KEY_ALIAS: "upload"
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ jobs:
aws secretsmanager get-secret-value --secret-id mobile-app-android-upload-key --output json | jq -r '.SecretBinary' | base64 --decode > upload-keystore.jks
- name: Build Android app
env:
FIREBASE_KEY: ${{ secrets.FIREBASE_KEY }}
GOOGLE_APP_ID_ANDROID: ${{ secrets.GOOGLE_APP_ID_ANDROID_STAGING }}
KEYSTORE_FILE: "${{ github.workspace }}/androidApp/upload-keystore.jks"
KEYSTORE_PASSWORD: ${{ env.MOBILE_APP_ANDROID_UPLOAD_KEY_PASSPHRASE }}
KEY_ALIAS: "upload"
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,4 @@ fastlane/report.xml

/iosApp/secrets/*
/iosApp/Pods/*
/androidApp/src/main/res/values/secrets.xml
/androidApp/src/main/res/values/secrets*.xml
25 changes: 22 additions & 3 deletions androidApp/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ android {
dependencies {
implementation(projects.shared)
implementation(platform(libs.compose.bom))
implementation(platform(libs.firebase.bom))
implementation(platform(libs.koin.bom))
implementation(libs.accompanist.permissions)
implementation(libs.androidx.activity.compose)
Expand All @@ -76,6 +77,7 @@ dependencies {
implementation(libs.compose.shimmer)
implementation(libs.compose.ui)
implementation(libs.compose.ui.tooling.preview)
implementation(libs.firebase.analytics)
implementation(libs.javaPhoenixClient)
implementation(libs.koin.androidxCompose)
implementation(libs.kotlinx.coroutines.core)
Expand Down Expand Up @@ -146,11 +148,12 @@ task("envVars") {
println(".envrc file not configured, reading from system env instead")
}

fun getPropsOrEnv(key: String): String? = props.getProperty(key) ?: System.getenv(key)

android.defaultConfig.buildConfigField(
"String",
"SENTRY_DSN",
"\"${props.getProperty("SENTRY_DSN_ANDROID")
?: System.getenv("SENTRY_DSN_ANDROID") ?: ""}\""
"\"${getPropsOrEnv("SENTRY_DSN_ANDROID") ?: ""}\""
)

// https://stackoverflow.com/a/53261807
Expand All @@ -171,13 +174,29 @@ task("envVars") {
"staging"
}

val sentryEnvOverride: String = props.getProperty("SENTRY_ENVIRONMENT", sentryEnv)
val sentryEnvOverride: String = getPropsOrEnv("SENTRY_ENVIRONMENT") ?: sentryEnv

android.defaultConfig.buildConfigField(
"String",
"SENTRY_ENVIRONMENT",
"\"${sentryEnvOverride}\""
)

val firebaseKey = getPropsOrEnv("FIREBASE_KEY")
val googleAppId = getPropsOrEnv("GOOGLE_APP_ID_ANDROID")
if (firebaseKey != null && googleAppId != null) {
val googleSecretsFile = File("${projectDir}/src/main/res/values/secrets-google.xml")
val lines =
listOfNotNull(
"<?xml version=\"1.0\" encoding=\"utf-8\"?>",
"<resources>",
" <string name=\"google_app_id\" translatable=\"false\">$googleAppId</string>",
" <string name=\"google_api_key\" translatable=\"false\">$firebaseKey</string>",
" <string name=\"google_crash_reporting_api_key\" translatable=\"false\">$firebaseKey</string>",
"</resources>"
)
googleSecretsFile.writeText(lines.joinToString(separator = "\n"))
}
}

gradle.projectsEvaluated {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class MorePageTests : KoinTest {
composeTestRule.onNodeWithText("MBTA Go").assertIsDisplayed()
}

@OptIn(ExperimentalTestApi::class)
@Test
fun testSettings() = runTest {
var hideMapToggleCalled = false
Expand All @@ -53,6 +54,8 @@ class MorePageTests : KoinTest {
KoinContext(koinApplication.koin) { MorePage(bottomBar = {}) }
}

composeTestRule.waitUntilExactlyOneExists(hasText("Settings"))
composeTestRule.onNodeWithText("Settings").performScrollTo()
composeTestRule.onNodeWithText("Settings").assertIsDisplayed()
composeTestRule.onNodeWithText("Hide Maps").performClick()

Expand Down
2 changes: 2 additions & 0 deletions androidApp/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,7 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<meta-data android:name="google_analytics_adid_collection_enabled" android:value="false" />
</application>
</manifest>
6 changes: 6 additions & 0 deletions androidApp/src/main/res/values/google-services.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="gcm_defaultSenderId" translatable="false">304904690247</string>
<string name="google_storage_bucket" translatable="false">mbta-app-c574d.firebasestorage.app</string>
<string name="project_id" translatable="false">mbta-app-c574d</string>
</resources>
3 changes: 3 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ compose-placeholder-material3= "1.0.8"
compose-shimmer= "1.3.1"
cyclonedx = "1.10.0"
datastorePreferencesCore = "1.1.1"
firebase-bom = "33.7.0"
kotlin = "2.1.0"
javaphoenixclient = "1.3.1"
junit = "4.13.2"
Expand Down Expand Up @@ -50,6 +51,8 @@ compose-ui-test-junit4 = { module = "androidx.compose.ui:ui-test-junit4" }
compose-ui-test-manifest = { module = "androidx.compose.ui:ui-test-manifest" }
compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" }
compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }
firebase-analytics = { module = "com.google.firebase:firebase-analytics" }
firebase-bom = { module = "com.google.firebase:firebase-bom", version.ref = "firebase-bom" }
javaPhoenixClient = { module = "com.github.dsrees:JavaPhoenixClient", version.ref = "javaphoenixclient" }
junit = { module = "junit:junit", version.ref = "junit" }
koin-androidxCompose = { module = "io.insert-koin:koin-androidx-compose" }
Expand Down
2 changes: 1 addition & 1 deletion iosApp/ci_scripts/ci_post_clone.sh
Original file line number Diff line number Diff line change
Expand Up @@ -89,4 +89,4 @@ touch .envrc
echo "export SENTRY_DSN_IOS=${SENTRY_DSN}" >> .envrc
echo "export SENTRY_ENVIRONMENT=${SENTRY_ENVIRONMENT}" >> .envrc
echo "export FIREBASE_KEY=${FIREBASE_KEY}" >> .envrc
echo "export GOOGLE_APP_ID=${GOOGLE_APP_ID}" >> .envrc
echo "export GOOGLE_APP_ID_IOS=${GOOGLE_APP_ID_IOS:-${GOOGLE_APP_ID}}" >> .envrc
2 changes: 1 addition & 1 deletion iosApp/iosApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -1382,7 +1382,7 @@
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "echo \"Adding info.plist values from .envrc\"\ncat ../.envrc | while IFS=\"=\" read -r key value; do\n key=$(echo $key | sed 's/export //') \n echo \"$key\"\n case \"$key\" in\n \"FIREBASE_KEY\" | \"GOOGLE_APP_ID\")\n if [ -n \"$value\" ]; then\n transformed_key=$key\n if [[ \"$key\" == \"FIREBASE_KEY\" ]]; then\n transformed_key=\"API_KEY\"\n fi\n plutil -replace $transformed_key -string $value \"$TARGET_BUILD_DIR/iosApp.app/GoogleService-Info.plist\"\n echo \"Google plist entry for $transformed_key added\"\n else\n echo \"Skipping google plist entry for $key - no value set, this will crash the app\"\n fi\n ;;\n \"\");;\n *)\n if [ -n \"$value\" ]; then\n plutil -replace $key -string $value \"$TARGET_BUILD_DIR/$INFOPLIST_PATH\"\n echo \"plist entry for $key added\"\n else\n echo \"Skipping plist entry for $key - no value set\"\n fi\n ;;\n esac\ndone\n\necho \"Setting GoogleService-Info BUNDLE ID\"\nplutil -replace \"BUNDLE_ID\" -string $PRODUCT_BUNDLE_IDENTIFIER \"$TARGET_BUILD_DIR/iosApp.app/GoogleService-Info.plist\"\n";
shellScript = "echo \"Adding info.plist values from .envrc\"\ncat ../.envrc | while IFS=\"=\" read -r key value; do\n key=$(echo $key | sed 's/export //') \n echo \"$key\"\n case \"$key\" in\n \"FIREBASE_KEY\" | \"GOOGLE_APP_ID_IOS\")\n if [ -n \"$value\" ]; then\n transformed_key=$key\n if [[ \"$key\" == \"FIREBASE_KEY\" ]]; then\n transformed_key=\"API_KEY\"\n else\n transformed_key=\"GOOGLE_APP_ID\"\n fi\n plutil -replace $transformed_key -string $value \"$TARGET_BUILD_DIR/iosApp.app/GoogleService-Info.plist\"\n echo \"Google plist entry for $transformed_key added\"\n else\n echo \"Skipping google plist entry for $key - no value set, this will crash the app\"\n fi\n ;;\n \"\");;\n *)\n if [ -n \"$value\" ]; then\n plutil -replace $key -string $value \"$TARGET_BUILD_DIR/$INFOPLIST_PATH\"\n echo \"plist entry for $key added\"\n else\n echo \"Skipping plist entry for $key - no value set\"\n fi\n ;;\n esac\ndone\n\necho \"Setting GoogleService-Info BUNDLE ID\"\nplutil -replace \"BUNDLE_ID\" -string $PRODUCT_BUNDLE_IDENTIFIER \"$TARGET_BUILD_DIR/iosApp.app/GoogleService-Info.plist\"\n";
};
7E1E3E807BCE8F2D4B7E5C7B /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
Expand Down

0 comments on commit ea010f8

Please sign in to comment.