diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml
index d4090147c..099f4acc2 100644
--- a/.github/workflows/pr-check.yml
+++ b/.github/workflows/pr-check.yml
@@ -1,4 +1,4 @@
-name: Workflow for master/development branches
+name: Workflow for kmp-impl branch
on:
pull_request:
diff --git a/.github/workflows/upload-demo-app-on-firebase.yaml b/.github/workflows/upload-demo-app-on-firebase.yaml
new file mode 100644
index 000000000..0405c0a11
--- /dev/null
+++ b/.github/workflows/upload-demo-app-on-firebase.yaml
@@ -0,0 +1,40 @@
+name: Upload Demo App on Firebase
+
+on:
+ workflow_dispatch:
+ inputs:
+ label:
+ description: 'Run tests and upload demo app on Firebase'
+ required: true
+ default: 'firebase-test-on'
+ type: string
+ tester_groups:
+ description: 'Comma-separated list of tester groups'
+ required: true
+ default: 'mifos-mobile-testers'
+ type: string
+
+ pull_request:
+ types: [ synchronize, opened, reopened, edited, closed, labeled ]
+
+jobs:
+ upload_demo_app_on_firebase:
+ runs-on: macos-latest
+ if: github.event.label.name == github.event.inputs.label
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+
+ - name: ☁️ Deploy Android App on Firebase
+ uses: openMF/kmp-android-firebase-publish-action@v1.0.0
+ with:
+ release_type: 'demo'
+ android_package_name: 'androidApp'
+ keystore_file: ${{ secrets.ORIGINAL_KEYSTORE_FILE }}
+ keystore_password: ${{ secrets.ORIGINAL_KEYSTORE_FILE_PASSWORD }}
+ keystore_alias: ${{ secrets.ORIGINAL_KEYSTORE_ALIAS }}
+ keystore_alias_password: ${{ secrets.ORIGINAL_KEYSTORE_ALIAS_PASSWORD }}
+ google_services: ${{ secrets.GOOGLESERVICES }}
+ firebase_creds: ${{ secrets.FIREBASECREDS }}
+ tester_groups: ${{ inputs.tester_groups }}
\ No newline at end of file
diff --git a/androidApp/src/demo/ic_launcher-playstore.png b/androidApp/src/demo/ic_launcher-playstore.png
new file mode 100644
index 000000000..b5ba435e3
Binary files /dev/null and b/androidApp/src/demo/ic_launcher-playstore.png differ
diff --git a/androidApp/src/demo/res/mipmap-anydpi-v26/ic_launcher.xml b/androidApp/src/demo/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 000000000..036d09bc5
--- /dev/null
+++ b/androidApp/src/demo/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/androidApp/src/demo/res/mipmap-anydpi-v26/ic_launcher_round.xml b/androidApp/src/demo/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 000000000..036d09bc5
--- /dev/null
+++ b/androidApp/src/demo/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/androidApp/src/demo/res/mipmap-hdpi/ic_launcher.webp b/androidApp/src/demo/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 000000000..b66cf7614
Binary files /dev/null and b/androidApp/src/demo/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/androidApp/src/demo/res/mipmap-hdpi/ic_launcher_foreground.webp b/androidApp/src/demo/res/mipmap-hdpi/ic_launcher_foreground.webp
new file mode 100644
index 000000000..e8f26bb75
Binary files /dev/null and b/androidApp/src/demo/res/mipmap-hdpi/ic_launcher_foreground.webp differ
diff --git a/androidApp/src/demo/res/mipmap-hdpi/ic_launcher_round.webp b/androidApp/src/demo/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 000000000..3187a2f6c
Binary files /dev/null and b/androidApp/src/demo/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/androidApp/src/demo/res/mipmap-mdpi/ic_launcher.webp b/androidApp/src/demo/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 000000000..475e2b0fe
Binary files /dev/null and b/androidApp/src/demo/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/androidApp/src/demo/res/mipmap-mdpi/ic_launcher_foreground.webp b/androidApp/src/demo/res/mipmap-mdpi/ic_launcher_foreground.webp
new file mode 100644
index 000000000..6d780ac33
Binary files /dev/null and b/androidApp/src/demo/res/mipmap-mdpi/ic_launcher_foreground.webp differ
diff --git a/androidApp/src/demo/res/mipmap-mdpi/ic_launcher_round.webp b/androidApp/src/demo/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 000000000..03176eda3
Binary files /dev/null and b/androidApp/src/demo/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/androidApp/src/demo/res/mipmap-xhdpi/ic_launcher.webp b/androidApp/src/demo/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 000000000..0be89c424
Binary files /dev/null and b/androidApp/src/demo/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/androidApp/src/demo/res/mipmap-xhdpi/ic_launcher_foreground.webp b/androidApp/src/demo/res/mipmap-xhdpi/ic_launcher_foreground.webp
new file mode 100644
index 000000000..92b3594dd
Binary files /dev/null and b/androidApp/src/demo/res/mipmap-xhdpi/ic_launcher_foreground.webp differ
diff --git a/androidApp/src/demo/res/mipmap-xhdpi/ic_launcher_round.webp b/androidApp/src/demo/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 000000000..c4b16e0e1
Binary files /dev/null and b/androidApp/src/demo/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/androidApp/src/demo/res/mipmap-xxhdpi/ic_launcher.webp b/androidApp/src/demo/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 000000000..dcf0f71e5
Binary files /dev/null and b/androidApp/src/demo/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/androidApp/src/demo/res/mipmap-xxhdpi/ic_launcher_foreground.webp b/androidApp/src/demo/res/mipmap-xxhdpi/ic_launcher_foreground.webp
new file mode 100644
index 000000000..9d598bb75
Binary files /dev/null and b/androidApp/src/demo/res/mipmap-xxhdpi/ic_launcher_foreground.webp differ
diff --git a/androidApp/src/demo/res/mipmap-xxhdpi/ic_launcher_round.webp b/androidApp/src/demo/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 000000000..9f31e244d
Binary files /dev/null and b/androidApp/src/demo/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/androidApp/src/demo/res/mipmap-xxxhdpi/ic_launcher.webp b/androidApp/src/demo/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 000000000..bd6e6ee15
Binary files /dev/null and b/androidApp/src/demo/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/androidApp/src/demo/res/mipmap-xxxhdpi/ic_launcher_foreground.webp b/androidApp/src/demo/res/mipmap-xxxhdpi/ic_launcher_foreground.webp
new file mode 100644
index 000000000..40de1e04c
Binary files /dev/null and b/androidApp/src/demo/res/mipmap-xxxhdpi/ic_launcher_foreground.webp differ
diff --git a/androidApp/src/demo/res/mipmap-xxxhdpi/ic_launcher_round.webp b/androidApp/src/demo/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 000000000..af2248418
Binary files /dev/null and b/androidApp/src/demo/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/androidApp/src/demo/res/values/ic_launcher_background.xml b/androidApp/src/demo/res/values/ic_launcher_background.xml
new file mode 100644
index 000000000..87a07fb9f
--- /dev/null
+++ b/androidApp/src/demo/res/values/ic_launcher_background.xml
@@ -0,0 +1,13 @@
+
+
+
+ #120A48
+
\ No newline at end of file
diff --git a/fastlane/FastFile b/fastlane/FastFile
index 3b56927fc..7b3a4dc1b 100644
--- a/fastlane/FastFile
+++ b/fastlane/FastFile
@@ -16,7 +16,7 @@ platform :android do
options[:keyPassword] ||= "mifos1234"
# Generate version
- generateVersion = generateFirebaseVersion()
+ generateVersion = generateVersion()
buildAndSignApp(
taskName: "assemble",
@@ -28,8 +28,8 @@ platform :android do
)
end
- desc "Bundle Play Store release"
- lane :bundlePlayStoreRelease do |options|
+ desc "Bundle Release APK"
+ lane :bundleReleaseApks do |options|
options[:storeFile] ||= "release_keystore.keystore"
options[:storePassword] ||= "mifos1234"
options[:keyAlias] ||= "mifos-mobile"
@@ -38,39 +38,90 @@ platform :android do
# Generate version
generateVersion = generateVersion()
- # Generate Release Note
- releaseNotes = generateFullReleaseNote()
+ buildAndSignApp(
+ taskName: "assemble",
+ buildType: "Release",
+ storeFile: options[:storeFile],
+ storePassword: options[:storePassword],
+ keyAlias: options[:keyAlias],
+ keyPassword: options[:keyPassword],
+ )
+ end
- # Write the generated release notes to default.txt
- buildConfigPath = "metadata/android/en-US/changelogs/default.txt"
+ desc "Publish Release Artifacts to Firebase App Distribution"
+ lane :deployReleaseApkOnFirebase do |options|
+ options[:appId] ||= "1:728434912738:android:d853a78f14af0c381a1dbb"
+ options[:apkFile] ||= "androidApp/build/outputs/apk/prod/release/androidApp-prod-release.apk"
+ options[:serviceCredsFile] ||= "secrets/firebaseAppDistributionServiceCredentialsFile.json"
+ options[:groups] ||= "mifos-mobile-testers"
- # Create directories if they don't exist
- require 'fileutils'
- FileUtils.mkdir_p(File.dirname(buildConfigPath))
+ options[:storeFile] ||= "release_keystore.keystore"
+ options[:storePassword] ||= "mifos1234"
+ options[:keyAlias] ||= "mifos-mobile"
+ options[:keyPassword] ||= "mifos1234"
- File.write(buildConfigPath, releaseNotes)
+ # Generate version
+ generateVersion = generateVersion(
+ platform: "firebase",
+ appId: options[:appId],
+ serviceCredsFile: options[:serviceCredsFile]
+ )
+
+ # Generate Release Note
+ releaseNotes = generateFullReleaseNote()
buildAndSignApp(
- taskName: "bundle",
+ taskName: "assembleProd",
buildType: "Release",
storeFile: options[:storeFile],
storePassword: options[:storePassword],
keyAlias: options[:keyAlias],
keyPassword: options[:keyPassword],
)
+
+ firebase_app_distribution(
+ app: options[:appId],
+ android_artifact_type: "APK",
+ android_artifact_path: options[:apkFile],
+ service_credentials_file: options[:serviceCredsFile],
+ groups: options[:groups],
+ release_notes: "#{releaseNotes}",
+ )
end
- desc "Publish Release Play Store artifacts to Firebase App Distribution"
- lane :deploy_on_firebase do |options|
+ desc "Publish Demo Artifacts to Firebase App Distribution"
+ lane :deployDemoApkOnFirebase do |options|
+ options[:appId] ||= "1:728434912738:android:7845cce9777d9cf11a1dbb"
options[:apkFile] ||= "androidApp/build/outputs/apk/demo/release/androidApp-demo-release.apk"
options[:serviceCredsFile] ||= "secrets/firebaseAppDistributionServiceCredentialsFile.json"
options[:groups] ||= "mifos-mobile-testers"
+ options[:storeFile] ||= "release_keystore.keystore"
+ options[:storePassword] ||= "mifos1234"
+ options[:keyAlias] ||= "mifos-mobile"
+ options[:keyPassword] ||= "mifos1234"
+
+ # Generate version with app ID
+ generateVersion = generateVersion(
+ platform: "firebase",
+ appId: options[:appId],
+ serviceCredsFile: options[:serviceCredsFile]
+ )
+
# Generate Release Note
- releaseNotes = generateFullReleaseNote()
+ releaseNotes = generateReleaseNote()
+
+ buildAndSignApp(
+ taskName: "assembleDemo",
+ buildType: "Release",
+ storeFile: options[:storeFile],
+ storePassword: options[:storePassword],
+ keyAlias: options[:keyAlias],
+ keyPassword: options[:keyPassword],
+ )
firebase_app_distribution(
- app: "1:728434912738:android:d853a78f14af0c381a1dbb",
+ app: options[:appId],
android_artifact_type: "APK",
android_artifact_path: options[:apkFile],
service_credentials_file: options[:serviceCredsFile],
@@ -80,8 +131,39 @@ platform :android do
end
desc "Deploy internal tracks to Google Play"
- lane :deploy_internal do |options|
+ lane :deployInternal do |options|
options[:aabFile] ||= "androidApp/build/outputs/bundle/prodRelease/androidApp-prod-release.aab"
+ options[:storeFile] ||= "release_keystore.keystore"
+ options[:storePassword] ||= "mifos1234"
+ options[:keyAlias] ||= "mifos-mobile"
+ options[:keyPassword] ||= "mifos1234"
+
+ # Generate version
+ generateVersion = generateVersion(
+ platform: "playstore"
+ )
+
+ # Generate Release Note
+ releaseNotes = generateFullReleaseNote()
+
+ # Write the generated release notes to default.txt
+ buildConfigPath = "metadata/android/en-US/changelogs/default.txt"
+
+ # Create directories if they don't exist
+ require 'fileutils'
+ FileUtils.mkdir_p(File.dirname(buildConfigPath))
+
+ File.write(buildConfigPath, releaseNotes)
+
+ buildAndSignApp(
+ taskName: "bundleProd",
+ buildType: "Release",
+ storeFile: options[:storeFile],
+ storePassword: options[:storePassword],
+ keyAlias: options[:keyAlias],
+ keyPassword: options[:keyPassword],
+ )
+
upload_to_play_store(
track: 'internal',
aab: options[:aabFile],
@@ -92,7 +174,7 @@ platform :android do
end
desc "Promote internal tracks to beta on Google Play"
- lane :promote_to_beta do
+ lane :promoteToBeta do
upload_to_play_store(
track: 'internal',
track_promote_to: 'beta',
@@ -143,83 +225,75 @@ platform :android do
)
end
- desc "Generate Play Store Version"
- lane :generateVersion do
- # Get current version codes from both production and beta
- prod_codes = google_play_track_version_codes(
- track: 'production',
- )
- beta_codes = google_play_track_version_codes(
- track: 'beta',
- )
+ desc "Generate Version for different platforms"
+ lane :generateVersion do |options|
+ # Default to 'git' if no platform specified
+ platform = (options[:platform] || 'git').downcase
- # Find highest version code
- latest_code = (prod_codes + beta_codes).max || 1
- new_version_code = latest_code + 1
-
- # Generate version file
+ # Generate version file for all platforms
gradle(tasks: ["versionFile"])
- # Set version from file
- ENV['VERSION'] = File.read("../version.txt").strip
-
- # Set it as environment variable or use directly
- ENV['VERSION_CODE'] = new_version_code.to_s
-
- UI.success("Set VERSION=#{ENV['VERSION']} VERSION_CODE=#{ENV['VERSION_CODE']}")
- end
+ # Set version from file with fallback
+ ENV['VERSION'] = File.read("../version.txt").strip rescue "1.0.0"
- desc "Generate Firebase Version"
- lane :generateFirebaseVersion do |options|
- options[:serviceCredsFile] ||= "secrets/firebaseAppDistributionServiceCredentialsFile.json"
-
- begin
- # Get latest release from Firebase App Distribution
- latest_release = firebase_app_distribution_get_latest_release(
- app: "1:728434912738:android:d853a78f14af0c381a1dbb",
- service_credentials_file: options[:serviceCredsFile]
+ case platform
+ when 'playstore'
+ # Get current version codes from both production and beta
+ prod_codes = google_play_track_version_codes(
+ track: 'production',
+ )
+ beta_codes = google_play_track_version_codes(
+ track: 'beta',
)
- # Extract the build version from latest release
- latest_build_version = if latest_release
- latest_release[:buildVersion].to_i
- else
- 1 # Default to 0 if no releases found
- end
-
- # Increment the build version
- new_build_version = latest_build_version + 1
+ # Find highest version code
+ latest_code = (prod_codes + beta_codes).max || 1
+ ENV['VERSION_CODE'] = (latest_code + 1).to_s
- # Generate version file
- gradle(task: "versionFile")
+ when 'firebase'
+ service_creds = options[:serviceCredsFile] || "secrets/firebaseAppDistributionServiceCredentialsFile.json"
+ app_id = options[:appId] || "1:728434912738:android:d853a78f14af0c381a1dbb"
- # Set version from file
- version = File.read("../version.txt").strip rescue "1.0.0" # Default version if file not found
+ begin
+ # Get latest release from Firebase App Distribution
+ latest_release = firebase_app_distribution_get_latest_release(
+ app: app_id,
+ service_credentials_file: service_creds
+ )
+
+ # Extract and increment the build version
+ latest_build_version = latest_release ? latest_release[:buildVersion].to_i : 0
+ ENV['VERSION_CODE'] = (latest_build_version + 1).to_s
+
+ rescue => e
+ UI.error("Error generating Firebase version: #{e.message}")
+ UI.error(e.backtrace.join("\n"))
+ raise e
+ end
- # Set environment variables
- ENV['VERSION'] = version
- ENV['VERSION_CODE'] = new_build_version.to_s
+ when 'git'
+ # Calculate version code from git history
+ commit_count = `git rev-list --count HEAD`.to_i
+ tag_count = `git tag | grep -v beta | wc -l`.to_i
+ ENV['VERSION_CODE'] = (commit_count << 1).to_s
- # Output the results
- UI.success("Latest Firebase build version: #{latest_build_version}")
- UI.success("New build version: #{new_build_version}")
- UI.success("Set VERSION=#{ENV['VERSION']} VERSION_CODE=#{ENV['VERSION_CODE']}")
+ else
+ UI.user_error!("Unsupported platform: #{platform}. Supported platforms are: playstore, firebase, git")
+ end
- # Return the values for potential further use
- {
- version: ENV['VERSION'],
- version_code: ENV['VERSION_CODE']
- }
+ # Output the results
+ UI.success("Generated version for #{platform}")
+ UI.success("Set VERSION=#{ENV['VERSION']} VERSION_CODE=#{ENV['VERSION_CODE']}")
- rescue => e
- UI.error("Error generating Firebase version: #{e.message}")
- UI.error(e.backtrace.join("\n"))
- raise e
- end
+ # Return the values for potential further use
+ {
+ version: ENV['VERSION'],
+ version_code: ENV['VERSION_CODE']
+ }
end
desc "Generate release notes"
- lane :generateReleaseNotes do |options|
+ lane :generateReleaseNote do |options|
releaseNotes = changelog_from_git_commits(
commits_count: 1,
)
@@ -247,7 +321,7 @@ platform :android do
end
# Get the tag from options or find the latest tag
- from_tag = options[:from_tag]
+ from_tag = options[:fromTag]
if from_tag
UI.message "Using specified tag: #{from_tag}"
# Verify the tag exists
@@ -410,7 +484,7 @@ platform :ios do
increment_version()
build_ios()
- releaseNotes = generateReleaseNotes()
+ releaseNotes = generateReleaseNote()
release = firebase_app_distribution(
app: "1:728434912738:ios:86a7badfaed88b841a1dbb",
service_credentials_file: options[:serviceCredsFile],
@@ -421,7 +495,7 @@ platform :ios do
end
desc "Generate release notes"
- lane :generateReleaseNotes do
+ lane :generateReleaseNote do
branchName = `git rev-parse --abbrev-ref HEAD`.chomp()
releaseNotes = changelog_from_git_commits(
commits_count: 1,
diff --git a/fastlane/README.md b/fastlane/README.md
index 0c2644ecf..ad2f4e1bb 100644
--- a/fastlane/README.md
+++ b/fastlane/README.md
@@ -31,34 +31,42 @@ Assemble debug APKs.
Assemble Release APK
-### android bundlePlayStoreRelease
+### android bundleReleaseApks
```sh
-[bundle exec] fastlane android bundlePlayStoreRelease
+[bundle exec] fastlane android bundleReleaseApks
```
-Bundle Play Store release
+Bundle Release APK
-### android deploy_on_firebase
+### android deployReleaseApkOnFirebase
```sh
-[bundle exec] fastlane android deploy_on_firebase
+[bundle exec] fastlane android deployReleaseApkOnFirebase
```
-Publish Release Play Store artifacts to Firebase App Distribution
+Publish Release Artifacts to Firebase App Distribution
-### android deploy_internal
+### android deployDemoApkOnFirebase
```sh
-[bundle exec] fastlane android deploy_internal
+[bundle exec] fastlane android deployDemoApkOnFirebase
+```
+
+Publish Demo Artifacts to Firebase App Distribution
+
+### android deployOnInternal
+
+```sh
+[bundle exec] fastlane android deployOnInternal
```
Deploy internal tracks to Google Play
-### android promote_to_beta
+### android promoteToBeta
```sh
-[bundle exec] fastlane android promote_to_beta
+[bundle exec] fastlane android promoteToBeta
```
Promote internal tracks to beta on Google Play
@@ -77,20 +85,12 @@ Promote beta tracks to production on Google Play
[bundle exec] fastlane android generateVersion
```
-Generate Play Store Version
-
-### android generateFirebaseVersion
-
-```sh
-[bundle exec] fastlane android generateFirebaseVersion
-```
-
-Generate Firebase Version
+Generate Version for different platforms
-### android generateReleaseNotes
+### android generateReleaseNote
```sh
-[bundle exec] fastlane android generateReleaseNotes
+[bundle exec] fastlane android generateReleaseNote
```
Generate release notes
@@ -132,10 +132,10 @@ Build iOS application
Upload iOS application to Firebase App Distribution
-### ios generateReleaseNotes
+### ios generateReleaseNote
```sh
-[bundle exec] fastlane ios generateReleaseNotes
+[bundle exec] fastlane ios generateReleaseNote
```
Generate release notes