From 9eacb8639e5cf43fb84bfea2dd9d8e7ddeb82a97 Mon Sep 17 00:00:00 2001 From: Achintha Isuru Date: Tue, 18 Nov 2025 12:16:42 -0500 Subject: [PATCH] feat: Add Codemagic environment variables and update Firebase configurations for multi-environment support --- codemagic-env-vars.md | 101 ++++++++++++++++++ codemagic.yaml | 9 +- .../android/app/src/dev/google-services.json | 40 ++++++- .../app/src/staging/google-services.json | 19 ++++ mobile-apps/staff-app/firebase.json | 36 ++++++- .../ios/Runner.xcodeproj/project.pbxproj | 19 ++++ 6 files changed, 214 insertions(+), 10 deletions(-) create mode 100644 codemagic-env-vars.md diff --git a/codemagic-env-vars.md b/codemagic-env-vars.md new file mode 100644 index 00000000..3cca1a4b --- /dev/null +++ b/codemagic-env-vars.md @@ -0,0 +1,101 @@ +# Codemagic Environment Variables + +This document outlines the environment variables required for the Codemagic CI/CD pipelines defined in `codemagic.yaml`. These variables should be configured in your Codemagic project under **Environment variables**. + +## Client App (`client-app`) + +--- + +### Group: `client_app_dev_credentials` + +| Variable Name | Example Value | Secure | Description | +| :--- | :--- | :--- | :--- | +| `FLAVOR` | `dev` | No | The Flutter flavor to use for the build. | +| `FIREBASE_APP_ID_ANDROID` | `1:DEV_ANDROID_APP_ID` | No | The Firebase App ID for the Android app (Dev). | +| `FIREBASE_APP_ID_IOS` | `1:DEV_IOS_APP_ID` | No | The Firebase App ID for the iOS app (Dev). | +| `FIREBASE_TESTER_GROUPS` | `developers` | No | Comma-separated list of Firebase tester groups. | +| `FIREBASE_TOKEN` | `(your_firebase_token)` | Yes | Your Firebase CLI token. | +| `GOOGLE_SERVICES_JSON` | `(contents of google-services.json)` | Yes | Contents of your `google-services.json` file for Android (Dev). | +| `GOOGLE_SERVICE_INFO_PLIST` | `(contents of GoogleService-Info.plist)` | Yes | Contents of your `GoogleService-Info.plist` file for iOS (Dev). | +| `KEYSTORE_PASSWORD` | `(your_keystore_password)` | Yes | Password for the Android keystore. | +| `KEY_ALIAS` | `(your_key_alias)` | Yes | Alias for the key in the Android keystore. | +| `KEY_PASSWORD` | `(your_key_password)` | Yes | Password for the key in the Android keystore. | + +### Group: `client_app_staging_credentials` + +| Variable Name | Example Value | Secure | Description | +| :--- | :--- | :--- | :--- | +| `FLAVOR` | `staging` | No | The Flutter flavor to use for the build. | +| `FIREBASE_APP_ID_ANDROID` | `1:STAGING_ANDROID_APP_ID` | No | The Firebase App ID for the Android app (Staging). | +| `FIREBASE_APP_ID_IOS` | `1:STAGING_IOS_APP_ID` | No | The Firebase App ID for the iOS app (Staging). | +| `FIREBASE_TESTER_GROUPS` | `qa-team, stakeholders` | No | Comma-separated list of Firebase tester groups. | +| `FIREBASE_TOKEN` | `(your_firebase_token)` | Yes | Your Firebase CLI token. | +| `GOOGLE_SERVICES_JSON` | `(contents of google-services.json)` | Yes | Contents of your `google-services.json` file for Android (Staging). | +| `GOOGLE_SERVICE_INFO_PLIST` | `(contents of GoogleService-Info.plist)` | Yes | Contents of your `GoogleService-Info.plist` file for iOS (Staging). | +| `KEYSTORE_PASSWORD` | `(your_keystore_password)` | Yes | Password for the Android keystore. | +| `KEY_ALIAS` | `(your_key_alias)` | Yes | Alias for the key in the Android keystore. | +| `KEY_PASSWORD` | `(your_key_password)` | Yes | Password for the key in the Android keystore. | + +### Group: `client_app_prod_credentials` + +| Variable Name | Example Value | Secure | Description | +| :--- | :--- | :--- | :--- | +| `FLAVOR` | `prod` | No | The Flutter flavor to use for the build. | +| `FIREBASE_APP_ID_ANDROID` | `1:PROD_ANDROID_APP_ID` | No | The Firebase App ID for the Android app (Prod). | +| `FIREBASE_APP_ID_IOS` | `1:PROD_IOS_APP_ID` | No | The Firebase App ID for the iOS app (Prod). | +| `FIREBASE_TESTER_GROUPS` | `(empty or specific group)` | No | Comma-separated list of Firebase tester groups. | +| `FIREBASE_TOKEN` | `(your_firebase_token)` | Yes | Your Firebase CLI token. | +| `GOOGLE_SERVICES_JSON` | `(contents of google-services.json)` | Yes | Contents of your `google-services.json` file for Android (Prod). | +| `GOOGLE_SERVICE_INFO_PLIST` | `(contents of GoogleService-Info.plist)` | Yes | Contents of your `GoogleService-Info.plist` file for iOS (Prod). | +| `KEYSTORE_PASSWORD` | `(your_keystore_password)` | Yes | Password for the Android keystore. | +| `KEY_ALIAS` | `(your_key_alias)` | Yes | Alias for the key in the Android keystore. | +| `KEY_PASSWORD` | `(your_key_password)` | Yes | Password for the key in the Android keystore. | + +## Staff App (`staff-app`) + +--- + +### Group: `staff_app_dev_credentials` + +| Variable Name | Example Value | Secure | Description | +| :--- | :--- | :--- | :--- | +| `FLAVOR` | `dev` | No | The Flutter flavor to use for the build. | +| `FIREBASE_APP_ID_ANDROID` | `1:DEV_ANDROID_APP_ID` | No | The Firebase App ID for the Android app (Dev). | +| `FIREBASE_APP_ID_IOS` | `1:DEV_IOS_APP_ID` | No | The Firebase App ID for the iOS app (Dev). | +| `FIREBASE_TESTER_GROUPS` | `developers` | No | Comma-separated list of Firebase tester groups. | +| `FIREBASE_TOKEN` | `(your_firebase_token)` | Yes | Your Firebase CLI token. | +| `GOOGLE_SERVICES_JSON` | `(contents of google-services.json)` | Yes | Contents of your `google-services.json` file for Android (Dev). | +| `GOOGLE_SERVICE_INFO_PLIST` | `(contents of GoogleService-Info.plist)` | Yes | Contents of your `GoogleService-Info.plist` file for iOS (Dev). | +| `KEYSTORE_PASSWORD` | `(your_keystore_password)` | Yes | Password for the Android keystore. | +| `KEY_ALIAS` | `(your_key_alias)` | Yes | Alias for the key in the Android keystore. | +| `KEY_PASSWORD` | `(your_key_password)` | Yes | Password for the key in the Android keystore. | + +### Group: `staff_app_staging_credentials` + +| Variable Name | Example Value | Secure | Description | +| :--- | :--- | :--- | :--- | +| `FLAVOR` | `staging` | No | The Flutter flavor to use for the build. | +| `FIREBASE_APP_ID_ANDROID` | `1:STAGING_ANDROID_APP_ID` | No | The Firebase App ID for the Android app (Staging). | +| `FIREBASE_APP_ID_IOS` | `1:STAGING_IOS_APP_ID` | No | The Firebase App ID for the iOS app (Staging). | +| `FIREBASE_TESTER_GROUPS` | `qa-team, stakeholders` | No | Comma-separated list of Firebase tester groups. | +| `FIREBASE_TOKEN` | `(your_firebase_token)` | Yes | Your Firebase CLI token. | +| `GOOGLE_SERVICES_JSON` | `(contents of google-services.json)` | Yes | Contents of your `google-services.json` file for Android (Staging). | +| `GOOGLE_SERVICE_INFO_PLIST` | `(contents of GoogleService-Info.plist)` | Yes | Contents of your `GoogleService-Info.plist` file for iOS (Staging). | +| `KEYSTORE_PASSWORD` | `(your_keystore_password)` | Yes | Password for the Android keystore. | +| `KEY_ALIAS` | `(your_key_alias)` | Yes | Alias for the key in the Android keystore. | +| `KEY_PASSWORD` | `(your_key_password)` | Yes | Password for the key in the Android keystore. | + +### Group: `staff_app_prod_credentials` + +| Variable Name | Example Value | Secure | Description | +| :--- | :--- | :--- | :--- | +| `FLAVOR` | `prod` | No | The Flutter flavor to use for the build. | +| `FIREBASE_APP_ID_ANDROID` | `1:PROD_ANDROID_APP_ID` | No | The Firebase App ID for the Android app (Prod). | +| `FIREBASE_APP_ID_IOS` | `1:PROD_IOS_APP_ID` | No | The Firebase App ID for the iOS app (Prod). | +| `FIREBASE_TESTER_GROUPS` | `(empty or specific group)` | No | Comma-separated list of Firebase tester groups. | +| `FIREBASE_TOKEN` | `(your_firebase_token)` | Yes | Your Firebase CLI token. | +| `GOOGLE_SERVICES_JSON` | `(contents of google-services.json)` | Yes | Contents of your `google-services.json` file for Android (Prod). | +| `GOOGLE_SERVICE_INFO_PLIST` | `(contents of GoogleService-Info.plist)` | Yes | Contents of your `GoogleService-Info.plist` file for iOS (Prod). | +| `KEYSTORE_PASSWORD` | `(your_keystore_password)` | Yes | Password for the Android keystore. | +| `KEY_ALIAS` | `(your_key_alias)` | Yes | Alias for the key in the Android keystore. | +| `KEY_PASSWORD` | `(your_key_password)` | Yes | Password for the key in the Android keystore. | diff --git a/codemagic.yaml b/codemagic.yaml index 26c9342c..4f018d36 100644 --- a/codemagic.yaml +++ b/codemagic.yaml @@ -3,15 +3,14 @@ build-script: &build-script name: Build Flutter App script: | flutter pub get - # Uncomment the line below if you use build_runner - # flutter pub run build_runner build --delete-conflicting-outputs + flutter pub run build_runner build --delete-conflicting-outputs # Build Android flutter build appbundle --flavor $FLAVOR - - # Build iOS - flutter build ipa --flavor $FLAVOR --export-options-plist=$FCI_BUILD_DIR/mobile-apps/client-app/ios/exportOptions.plist + # Build iOS + flutter build ipa --flavor $FLAVOR --export-options-plist=$FCI_WORKING_DIRECTORY/ios/exportOptions.plist + # Reusable script for distributing to Firebase distribute-script: &distribute-script name: Distribute to Firebase App Distribution diff --git a/mobile-apps/staff-app/android/app/src/dev/google-services.json b/mobile-apps/staff-app/android/app/src/dev/google-services.json index 461af975..f50a07c6 100644 --- a/mobile-apps/staff-app/android/app/src/dev/google-services.json +++ b/mobile-apps/staff-app/android/app/src/dev/google-services.json @@ -5,6 +5,42 @@ "storage_bucket": "krow-workforce-dev.firebasestorage.app" }, "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:933560802882:android:edcddb83ea4bbb517757db", + "android_client_info": { + "package_name": "com.krow.app.business.dev" + } + }, + "oauth_client": [ + { + "client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com", + "client_type": 3 + } + ], + "api_key": [ + { + "current_key": "AIzaSyDBYhflhK6DThKnS7RM-9raKdvyKzLUjY4" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [ + { + "client_id": "933560802882-grp98a1v7amflnnup68vh01tj06eaem1.apps.googleusercontent.com", + "client_type": 3 + }, + { + "client_id": "933560802882-ml2526jqnnsteent4i9li50c00hisoge.apps.googleusercontent.com", + "client_type": 2, + "ios_info": { + "bundle_id": "com.krow.app.business.dev" + } + } + ] + } + } + }, { "client_info": { "mobilesdk_app_id": "1:933560802882:android:f4587798877cbb917757db", @@ -31,10 +67,10 @@ "client_type": 3 }, { - "client_id": "933560802882-qgbq6m04moicvkff2b3i6p9agu7i4gou.apps.googleusercontent.com", + "client_id": "933560802882-ml2526jqnnsteent4i9li50c00hisoge.apps.googleusercontent.com", "client_type": 2, "ios_info": { - "bundle_id": "com.krow.app.dev" + "bundle_id": "com.krow.app.business.dev" } } ] diff --git a/mobile-apps/staff-app/android/app/src/staging/google-services.json b/mobile-apps/staff-app/android/app/src/staging/google-services.json index bbe402ea..fce47d44 100644 --- a/mobile-apps/staff-app/android/app/src/staging/google-services.json +++ b/mobile-apps/staff-app/android/app/src/staging/google-services.json @@ -5,6 +5,25 @@ "storage_bucket": "krow-workforce-staging.firebasestorage.app" }, "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:1032971403708:android:d35f6d13a9e03bcb356bb9", + "android_client_info": { + "package_name": "com.krow.app.business.staging" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyAZ4dOatvf3ZBt4qnbSlIvJ51bblHaRsRw" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + }, { "client_info": { "mobilesdk_app_id": "1:1032971403708:android:87edb39679f806ab356bb9", diff --git a/mobile-apps/staff-app/firebase.json b/mobile-apps/staff-app/firebase.json index 70580572..3beb93ba 100644 --- a/mobile-apps/staff-app/firebase.json +++ b/mobile-apps/staff-app/firebase.json @@ -32,12 +32,42 @@ "uploadDebugSymbols": false, "fileOutput": "ios/Runner/GoogleService-Info.plist" }, - "targets": { - "Runner": { + "buildConfigurations": { + "Debug-dev": { "projectId": "krow-workforce-dev", - "appId": "1:1032971403708:ios:1d9b09307e6f3983356bb9", + "appId": "1:933560802882:ios:07becdd41ac6ca627757db", "uploadDebugSymbols": false, "fileOutput": "ios/flavors/dev/GoogleService-Info.plist" + }, + "Profile-dev": { + "projectId": "krow-workforce-dev", + "appId": "1:933560802882:ios:07becdd41ac6ca627757db", + "uploadDebugSymbols": false, + "fileOutput": "ios/flavors/dev/GoogleService-Info.plist" + }, + "Release-dev": { + "projectId": "krow-workforce-dev", + "appId": "1:933560802882:ios:07becdd41ac6ca627757db", + "uploadDebugSymbols": false, + "fileOutput": "ios/flavors/dev/GoogleService-Info.plist" + }, + "Debug-staging": { + "projectId": "krow-workforce-staging", + "appId": "1:1032971403708:ios:1d9b09307e6f3983356bb9", + "uploadDebugSymbols": false, + "fileOutput": "ios/flavors/staging/GoogleService-Info.plist" + }, + "Profile-staging": { + "projectId": "krow-workforce-staging", + "appId": "1:1032971403708:ios:1d9b09307e6f3983356bb9", + "uploadDebugSymbols": false, + "fileOutput": "ios/flavors/staging/GoogleService-Info.plist" + }, + "Release-staging": { + "projectId": "krow-workforce-staging", + "appId": "1:1032971403708:ios:1d9b09307e6f3983356bb9", + "uploadDebugSymbols": false, + "fileOutput": "ios/flavors/staging/GoogleService-Info.plist" } } }, diff --git a/mobile-apps/staff-app/ios/Runner.xcodeproj/project.pbxproj b/mobile-apps/staff-app/ios/Runner.xcodeproj/project.pbxproj index f1b0ef8a..6ea19fff 100644 --- a/mobile-apps/staff-app/ios/Runner.xcodeproj/project.pbxproj +++ b/mobile-apps/staff-app/ios/Runner.xcodeproj/project.pbxproj @@ -249,6 +249,7 @@ 3B06AD1E1E4923F5004D2608 /* Thin Binary */, 924B93AB74D97EF4B42824EC /* [CP] Embed Pods Frameworks */, 8A3E049698DB74713226DAC2 /* [CP] Copy Pods Resources */, + CA84EF6F10FA3C39D36D57BC /* FlutterFire: "flutterfire bundle-service-file" */, ); buildRules = ( ); @@ -456,6 +457,24 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build\n"; }; + CA84EF6F10FA3C39D36D57BC /* FlutterFire: "flutterfire bundle-service-file" */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "FlutterFire: \"flutterfire bundle-service-file\""; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\n#!/bin/bash\nPATH=\"${PATH}:$FLUTTER_ROOT/bin:${PUB_CACHE}/bin:$HOME/.pub-cache/bin\"\nflutterfire bundle-service-file --plist-destination=\"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app\" --build-configuration=${CONFIGURATION} --platform=ios --apple-project-path=\"${SRCROOT}\"\n"; + }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */