ci: Configured GitHub Workflow For Play Store & FAD Publishing (#2738)
2
.github/ISSUE_TEMPLATE.md
vendored
@ -1 +1 @@
|
||||
### We're moving towards to use [Jira](https://mifosforge.jira.com/jira/software/c/projects/MM/issues/) for issue tracking, and Join our [slack](https://join.slack.com/t/mifos/shared_invite/zt-2wvi9t82t-DuSBdqdQVOY9fsqsLjkKPA) channel `mifos-mobile` to discuss all things about Mifos Mobile development. and do not cross post your messages in multiple channels. ask your question in the appropriate channel.
|
||||
#### We are transitioning to [Jira](https://mifosforge.jira.com/jira/software/c/projects/MM/issues/) for issue tracking. Additionally, we encourage you to join our Slack channel #mifos-mobile to discuss all aspects of Mifos Mobile development. Please ensure that your messages are not cross-posted in multiple channels. Kindly direct your questions to the most appropriate channel for efficient communication.
|
||||
56
.github/actions/create-release-notes/action.yml
vendored
@ -1,56 +0,0 @@
|
||||
name: 'Create Release Notes'
|
||||
description: 'Creates the current releases release notes'
|
||||
inputs:
|
||||
tag-name:
|
||||
description: 'Name of the tag that will be used for this release'
|
||||
required: true
|
||||
gh-token:
|
||||
description: 'The GitHub token used to get details from the API'
|
||||
required: true
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Get Previous Release Tag
|
||||
uses: actions/github-script@v7
|
||||
id: latest-release-tag
|
||||
with:
|
||||
github-token: ${{ inputs.gh-token }}
|
||||
result-encoding: string
|
||||
script: |
|
||||
const { data } = await github.rest.repos.getLatestRelease({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
})
|
||||
return data.tag_name
|
||||
- name: Get Generated Release Notes
|
||||
uses: actions/github-script@v7
|
||||
id: generate-notes
|
||||
with:
|
||||
github-token: ${{ inputs.gh-token }}
|
||||
result-encoding: string
|
||||
script: |
|
||||
const { data } = await github.rest.repos.generateReleaseNotes({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
tag_name: '${{ inputs.tag-name }}',
|
||||
target_commitish: 'development',
|
||||
previous_tag_name: '${{ steps.latest-release-tag.outputs.result }}',
|
||||
})
|
||||
return data.body.replaceAll('`', '\'').replaceAll('"', '\'')
|
||||
- name: Generate Release Notes
|
||||
id: version-generator
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p ./androidApp/build/outputs/
|
||||
|
||||
echo "Previous Release Tag:"
|
||||
echo "${{ steps.latest-release-tag.outputs.result }}"
|
||||
|
||||
echo "Full Changelog:"
|
||||
CHANGELOG="${{ steps.generate-notes.outputs.result }}"
|
||||
echo -e "$CHANGELOG"
|
||||
printf "$CHANGELOG" > ./androidApp/build/outputs/changelogGithub
|
||||
|
||||
echo "Beta Changelog:"
|
||||
git log --format="* %s" HEAD^..HEAD
|
||||
git log --format="* %s" HEAD^..HEAD > ./androidApp/build/outputs/changelogBeta
|
||||
54
.github/actions/create-release-number/action.yml
vendored
@ -1,54 +0,0 @@
|
||||
name: 'Create Release Numbers'
|
||||
description: 'Creates the current release number based on Gradle or Git history'
|
||||
outputs:
|
||||
version-code:
|
||||
description: 'The numeric app version'
|
||||
value: ${{ steps.version-generator.outputs.version-code }}
|
||||
version:
|
||||
description: 'The app version'
|
||||
value: ${{ steps.version-generator.outputs.version }}
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Set Build Number and Version
|
||||
id: version-generator
|
||||
shell: bash
|
||||
run: |
|
||||
# Try to get version from Gradle
|
||||
./gradlew versionFile
|
||||
GRADLE_VERSION=$(cat version.txt)
|
||||
|
||||
if [ "$GRADLE_VERSION" = "unspecified" ] || [ -z "$GRADLE_VERSION" ]; then
|
||||
echo "Gradle version is unspecified or empty. Generating version from Git."
|
||||
|
||||
# Get the latest tag
|
||||
LATEST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "v0.0.0")
|
||||
|
||||
# Extract major, minor, patch from the tag
|
||||
IFS='.' read -r MAJOR MINOR PATCH <<< "${LATEST_TAG#v}"
|
||||
|
||||
# Count commits since the last tag
|
||||
COMMITS_SINCE_TAG=$(git rev-list ${LATEST_TAG}..HEAD --count)
|
||||
|
||||
# Calculate new patch version
|
||||
NEW_PATCH=$((PATCH + COMMITS_SINCE_TAG))
|
||||
|
||||
# Generate version name
|
||||
VERSION="${MAJOR}.${MINOR}.${NEW_PATCH}"
|
||||
else
|
||||
echo "Using Gradle-generated version."
|
||||
VERSION=$GRADLE_VERSION
|
||||
fi
|
||||
|
||||
# Calculate version code
|
||||
COMMITS=$(git rev-list --count HEAD)
|
||||
TAGS=$(git tag | grep -v beta | wc -l)
|
||||
VC=$((((COMMITS+TAGS) * 3) << 1))
|
||||
|
||||
echo "Version: $VERSION"
|
||||
echo "Number of Commits: $COMMITS"
|
||||
echo "Number of Tags: $TAGS"
|
||||
echo "Version Code: $VC"
|
||||
|
||||
echo "version-code=$VC" >> $GITHUB_OUTPUT
|
||||
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||
40
.github/actions/inflate-secrets/action.yml
vendored
@ -1,40 +0,0 @@
|
||||
name: 'Inflate Secrets'
|
||||
description: 'Inflates the secret values into the appropriate files'
|
||||
inputs:
|
||||
keystore:
|
||||
description: 'The keystore to inflate'
|
||||
required: true
|
||||
google-services:
|
||||
description: 'The google-services.json to inflate'
|
||||
required: true
|
||||
playstore-creds:
|
||||
description: 'The playstore credentials to inflate'
|
||||
required: true
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Mock debug google-services.json
|
||||
shell: bash
|
||||
run: |
|
||||
cp .github/mock-google-services.json androidApp/google-services.json
|
||||
|
||||
- name: Inflate release_keystore.keystore
|
||||
shell: bash
|
||||
env:
|
||||
KEYSTORE: ${{ inputs.keystore }}
|
||||
run: |
|
||||
echo $KEYSTORE | base64 --decode > androidApp/release_keystore.keystore
|
||||
|
||||
- name: Inflate google-services.json
|
||||
shell: bash
|
||||
env:
|
||||
GOOGLE_SERVICES: ${{ inputs.google-services }}
|
||||
run: |
|
||||
echo $GOOGLE_SERVICES > androidApp/google-services.json
|
||||
|
||||
- name: Inflate playStorePublishServiceCredentialsFile.json
|
||||
shell: bash
|
||||
env:
|
||||
CREDS: ${{ inputs.playstore-creds }}
|
||||
run: |
|
||||
echo $CREDS > androidApp/playStorePublishServiceCredentialsFile.json
|
||||
55
.github/mock-google-services.json
vendored
@ -1,55 +0,0 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "project_number",
|
||||
"firebase_url": "firebase_url",
|
||||
"project_id": "project_id",
|
||||
"storage_bucket": "storage_bucket"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "mobilesdk_app_id",
|
||||
"android_client_info": {
|
||||
"package_name": "org.mifos.mobile"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "client_id",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "org.mifos.mobile",
|
||||
"certificate_hash": "2f8ce9c728acf6b9c50750b328742d5391c0b303"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "client_id",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "current_key"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"analytics_service": {
|
||||
"status": 1
|
||||
},
|
||||
"appinvite_service": {
|
||||
"status": 2,
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "client_id",
|
||||
"client_type": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
"ads_service": {
|
||||
"status": 2
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
}
|
||||
96
.github/workflows/android-release.yml
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
# GitHub Actions Workflow for Kotlin Android Application Deployment
|
||||
#
|
||||
# OVERVIEW:
|
||||
# This workflow supports building and publishing applications across multiple platforms:
|
||||
# - Android (APK/AAB)
|
||||
#
|
||||
# PREREQUISITES:
|
||||
# Ensure your project is configured with:
|
||||
# - Gradle build system
|
||||
# - Kotlin Multiplatform Project with Android, iOS, Desktop, and Web modules
|
||||
# - Fastlane for deployment automation
|
||||
# - Separate modules/package names for each platform
|
||||
#
|
||||
# REQUIRED SECRETS:
|
||||
# Configure the following secrets in GitHub repository settings:
|
||||
# - ORIGINAL_KEYSTORE_FILE: Base64 encoded Android release keystore
|
||||
# - ORIGINAL_KEYSTORE_FILE_PASSWORD: Keystore password
|
||||
# - ORIGINAL_KEYSTORE_ALIAS: Keystore alias
|
||||
# - ORIGINAL_KEYSTORE_ALIAS_PASSWORD: Keystore alias password
|
||||
|
||||
# - UPLOAD_KEYSTORE_FILE: Base64 encoded Android release keystore
|
||||
# - UPLOAD_KEYSTORE_FILE_PASSWORD: Keystore password
|
||||
# - UPLOAD_KEYSTORE_ALIAS: Keystore alias
|
||||
# - UPLOAD_KEYSTORE_ALIAS_PASSWORD: Keystore alias password
|
||||
|
||||
# - GOOGLESERVICES: Google Services configuration JSON
|
||||
# - PLAYSTORECREDS: Play Store service account credentials
|
||||
# - FIREBASECREDS: Firebase distribution credentials
|
||||
|
||||
# WORKFLOW INPUTS:
|
||||
# - release_type: 'internal' (default) or 'beta'
|
||||
# - target_branch: Branch to use for release (default: 'dev')
|
||||
# - android_package_name: Name of Android module
|
||||
|
||||
# USAGE:
|
||||
# 1. Ensure all required secrets are configured
|
||||
# 2. Customize package names in workflow inputs
|
||||
# 3. Toggle platform-specific publishing flags
|
||||
# 4. Trigger workflow manually or via GitHub Actions UI
|
||||
|
||||
# https://github.com/openMF/mifos-mobile-github-actions/blob/main/.github/workflows/android-build-and-publish.yaml
|
||||
|
||||
# ##############################################################################
|
||||
# DON'T EDIT THIS FILE UNLESS NECESSARY #
|
||||
# ##############################################################################
|
||||
name: Android Build and Publish
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_type:
|
||||
type: choice
|
||||
options:
|
||||
- internal
|
||||
- beta
|
||||
default: internal
|
||||
description: Release Type
|
||||
|
||||
target_branch:
|
||||
type: string
|
||||
default: 'development'
|
||||
description: 'Target branch for release'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
id-token: write
|
||||
pages: write
|
||||
|
||||
concurrency:
|
||||
group: "reusable"
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
android_build_and_publish:
|
||||
name: Android Build and Publish
|
||||
uses: openMF/mifos-mobile-github-actions/.github/workflows/android-build-and-publish.yaml@main
|
||||
with:
|
||||
release_type: ${{ inputs.release_type }}
|
||||
target_branch: ${{ inputs.target_branch }}
|
||||
android_package_name: 'androidApp' # <-- Change this to your android package name
|
||||
tester_groups: 'mifos-mobile-testers' # <-- Change this to your Firebase tester group
|
||||
secrets:
|
||||
original_keystore_file: ${{ secrets.ORIGINAL_KEYSTORE_FILE }}
|
||||
original_keystore_file_password: ${{ secrets.ORIGINAL_KEYSTORE_FILE_PASSWORD }}
|
||||
original_keystore_alias: ${{ secrets.ORIGINAL_KEYSTORE_ALIAS }}
|
||||
original_keystore_alias_password: ${{ secrets.ORIGINAL_KEYSTORE_ALIAS_PASSWORD }}
|
||||
|
||||
upload_keystore_file: ${{ secrets.UPLOAD_KEYSTORE_FILE }}
|
||||
upload_keystore_file_password: ${{ secrets.UPLOAD_KEYSTORE_FILE_PASSWORD }}
|
||||
upload_keystore_alias: ${{ secrets.UPLOAD_KEYSTORE_ALIAS }}
|
||||
upload_keystore_alias_password: ${{ secrets.UPLOAD_KEYSTORE_ALIAS_PASSWORD }}
|
||||
|
||||
google_services: ${{ secrets.GOOGLESERVICES }}
|
||||
firebase_creds: ${{ secrets.FIREBASECREDS }}
|
||||
playstore_creds: ${{ secrets.PLAYSTORECREDS }}
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
61
.github/workflows/master_dev_ci.yml
vendored
@ -71,8 +71,7 @@ jobs:
|
||||
**/build/reports/detekt/detekt.md
|
||||
|
||||
|
||||
|
||||
|
||||
# Dependency Guard is a tool that checks for known vulnerabilities in your dependencies
|
||||
dependency_guard:
|
||||
needs: setup
|
||||
runs-on: ubuntu-latest
|
||||
@ -109,64 +108,8 @@ jobs:
|
||||
disable_globbing: true
|
||||
commit_message: "🤖 Updates baselines for Dependency Guard"
|
||||
|
||||
tests_and_lint:
|
||||
needs: setup
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-java@v4
|
||||
with:
|
||||
distribution: 'zulu'
|
||||
java-version: 17
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
./gradlew testDebug :lint:test :androidApp:lintRelease :lint:lint
|
||||
|
||||
- name: Upload reports
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-and-lint-reports
|
||||
path: |
|
||||
**/build/reports/lint-results-*.html
|
||||
**/build/test-results/test*UnitTest/**.xml
|
||||
|
||||
|
||||
# Add `createDebugUnitTestCoverageReport` if we ever add JVM tests for prod
|
||||
- name: Generate coverage reports for Debug variants (only API 30)
|
||||
run: ./gradlew createDebugCombinedCoverageReport
|
||||
|
||||
- name: Upload test reports
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: test-reports-${{ matrix.api-level }}
|
||||
path: '**/build/reports/androidTests'
|
||||
|
||||
- name: Display local test coverage (only API 30)
|
||||
id: jacoco
|
||||
uses: madrapps/jacoco-report@v1.6.1
|
||||
with:
|
||||
title: Combined test coverage report
|
||||
min-coverage-overall: 40
|
||||
min-coverage-changed-files: 60
|
||||
paths: |
|
||||
${{ github.workspace }}/**/build/reports/jacoco/**/*Report.xml
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload local coverage reports (XML + HTML) (only API 30)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: coverage-reports
|
||||
if-no-files-found: error
|
||||
compression-level: 1
|
||||
overwrite: false
|
||||
path: '**/build/reports/jacoco/'
|
||||
|
||||
build:
|
||||
needs: [ checks, dependency_guard, tests_and_lint ]
|
||||
needs: [ checks, dependency_guard ]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
66
.github/workflows/monthly-release.yaml
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
# Automated Monthly Release Versioning Workflow
|
||||
# ============================================
|
||||
|
||||
# Purpose:
|
||||
# - Automatically create consistent monthly version tags
|
||||
# - Implement a calendar-based versioning strategy
|
||||
# - Facilitate easy tracking of monthly releases
|
||||
|
||||
# Versioning Strategy:
|
||||
# - Tag format: YYYY.MM.0 (e.g., 2024.01.0 for January 2024)
|
||||
# - First digit: Full year
|
||||
# - Second digit: Month (01-12)
|
||||
# - Third digit: Patch version (starts at 0, allows for potential updates)
|
||||
|
||||
# Key Features:
|
||||
# - Runs automatically on the first day of each month at 3:30 AM UTC
|
||||
# - Can be manually triggered via workflow_dispatch
|
||||
# - Uses GitHub Actions to generate tags programmatically
|
||||
# - Provides a predictable and systematic versioning approach
|
||||
|
||||
# Prerequisites:
|
||||
# - Repository configured with GitHub Actions
|
||||
# - Permissions to create tags
|
||||
# - Access to actions/checkout and tag creation actions
|
||||
|
||||
# Workflow Triggers:
|
||||
# - Scheduled monthly run
|
||||
# - Manual workflow dispatch
|
||||
# - Callable from other workflows
|
||||
|
||||
# Actions Used:
|
||||
# 1. actions/checkout@v4 - Checks out repository code
|
||||
# 2. josStorer/get-current-time - Retrieves current timestamp
|
||||
# 3. rickstaa/action-create-tag - Creates Git tags
|
||||
|
||||
# Example Generated Tags:
|
||||
# - 2024.01.0 (January 2024 initial release)
|
||||
# - 2024.02.0 (February 2024 initial release)
|
||||
# - 2024.02.1 (Potential patch for February 2024)
|
||||
|
||||
# https://github.com/openMF/mifos-mobile-github-actions/blob/main/.github/workflows/monthly-version-tag.yaml
|
||||
|
||||
# ##############################################################################
|
||||
# DON'T EDIT THIS FILE UNLESS NECESSARY #
|
||||
# ##############################################################################
|
||||
|
||||
name: Tag Monthly Release
|
||||
|
||||
on:
|
||||
# Allow manual triggering of the workflow
|
||||
workflow_dispatch:
|
||||
# Schedule the workflow to run monthly
|
||||
schedule:
|
||||
# Runs at 03:30 UTC on the first day of every month
|
||||
# Cron syntax: minute hour day-of-month month day-of-week
|
||||
- cron: '30 3 1 * *'
|
||||
|
||||
concurrency:
|
||||
group: "monthly-release"
|
||||
cancel-in-progress: false
|
||||
|
||||
jobs:
|
||||
monthly_release:
|
||||
name: Tag Monthly Release
|
||||
uses: openMF/mifos-mobile-github-actions/.github/workflows/monthly-version-tag.yaml@main
|
||||
secrets: inherit
|
||||
21
.github/workflows/monthly_release.yaml
vendored
@ -1,21 +0,0 @@
|
||||
name: Bump our Calendar Version
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: '30 3 1 * *'
|
||||
jobs:
|
||||
tag:
|
||||
name: Tag Monthly Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get Current Time
|
||||
uses: josStorer/get-current-time@v2.1.2
|
||||
id: current-time
|
||||
|
||||
- name: Bump Calendar Version
|
||||
uses: rickstaa/action-create-tag@v1.7.2
|
||||
with:
|
||||
tag: ${{ steps.current-time.outputs.year }}.${{ steps.current-time.outputs.month }}.0
|
||||
75
.github/workflows/promote-to-production.yml
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
# GitHub Actions Workflow for Play Store Release Promotion
|
||||
#
|
||||
# PURPOSE:
|
||||
# This workflow automates the process of promoting a beta release
|
||||
# to the production track on Google Play Store.
|
||||
#
|
||||
# PREREQUISITES:
|
||||
# 1. Fastlane setup with Android deployment configurations
|
||||
# 2. Configured Fastlane lanes:
|
||||
# - `promote_to_production`: Handles beta to production promotion
|
||||
#
|
||||
# REQUIRED CONFIGURATION:
|
||||
# - Secrets:
|
||||
# PLAYSTORECREDS: Google Play Store service account JSON credentials
|
||||
#
|
||||
# INPUTS:
|
||||
# - android_package_name: Name of the Android project module
|
||||
# (REQUIRED, must match your project's module structure)
|
||||
#
|
||||
# WORKFLOW TRIGGERS:
|
||||
# - Can be called manually or triggered by other workflows
|
||||
# - Typically used after beta testing and validation
|
||||
#
|
||||
# DEPLOYMENT PROCESS:
|
||||
# 1. Checks out repository code
|
||||
# 2. Sets up Ruby and Fastlane environment
|
||||
# 3. Inflates Play Store credentials
|
||||
# 4. Runs Fastlane lane to promote beta to production
|
||||
#
|
||||
# IMPORTANT NOTES:
|
||||
# - Requires proper Fastlane configuration in your project
|
||||
# - Ensures consistent and automated Play Store deployments
|
||||
# - Configurable retry mechanism for upload stability
|
||||
#
|
||||
# RECOMMENDED FASTLANE LANE IMPLEMENTATION:
|
||||
# ```ruby
|
||||
# lane :promote_to_production do
|
||||
# upload_to_play_store(
|
||||
# track: 'beta',
|
||||
# track_promote_to: 'production',
|
||||
# json_key: './playStorePublishServiceCredentialsFile.json'
|
||||
# )
|
||||
# end
|
||||
# ```
|
||||
|
||||
# https://github.com/openMF/mifos-mobile-github-actions/blob/main/.github/workflows/promote-to-production.yaml
|
||||
|
||||
# ##############################################################################
|
||||
# DON'T EDIT THIS FILE UNLESS NECESSARY #
|
||||
# ##############################################################################
|
||||
|
||||
name: Promote Release to Play Store
|
||||
|
||||
# Workflow triggers:
|
||||
# 1. Manual trigger with option to publish to Play Store
|
||||
# 2. Automatic trigger when a GitHub release is published
|
||||
on:
|
||||
workflow_dispatch:
|
||||
release:
|
||||
types: [ released ]
|
||||
|
||||
concurrency:
|
||||
group: "production-deploy"
|
||||
cancel-in-progress: false
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
# Job to promote app from beta to production in Play Store
|
||||
play_promote_production:
|
||||
name: Promote Beta to Production Play Store
|
||||
uses: openMF/mifos-mobile-github-actions/.github/workflows/promote-to-production.yaml@main
|
||||
secrets:
|
||||
playstore_creds: ${{ secrets.PLAYSTORECREDS }}
|
||||
162
.github/workflows/release_to_internal_or_beta.yml
vendored
@ -1,162 +0,0 @@
|
||||
name: Internal Or Beta Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_type:
|
||||
required: false
|
||||
default: 'internal'
|
||||
description: Please select the release type
|
||||
type: choice
|
||||
options:
|
||||
- internal
|
||||
- beta
|
||||
|
||||
env:
|
||||
SUPPLY_UPLOAD_MAX_RETRIES: 5
|
||||
|
||||
jobs:
|
||||
app_build:
|
||||
name: Github Release
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4.2.2
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '3.2'
|
||||
bundler-cache: true
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
|
||||
- uses: ./.github/actions/create-release-number
|
||||
name: Create Release Number
|
||||
id: rel_number
|
||||
|
||||
- uses: ./.github/actions/inflate-secrets
|
||||
name: Inflate Secrets
|
||||
with:
|
||||
keystore: ${{ secrets.ORIGINAL_KEYSTORE_FILE }}
|
||||
google-services: ${{ secrets.GOOGLESERVICES }}
|
||||
playstore-creds: ${{ secrets.PLAYSTORECREDS }}
|
||||
|
||||
- uses: ./.github/actions/create-release-notes
|
||||
name: Create Release Notes
|
||||
with:
|
||||
tag-name: ${{ steps.rel_number.outputs.version }}
|
||||
gh-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build Release
|
||||
env:
|
||||
KEYSTORE_PATH: ${{ secrets.KEYSTORE_NAME }}
|
||||
KEYSTORE_PASSWORD: ${{ secrets.ORIGINAL_KEYSTORE_FILE_PASSWORD }}
|
||||
KEYSTORE_ALIAS: ${{ secrets.ORIGINAL_KEYSTORE_ALIAS }}
|
||||
KEYSTORE_ALIAS_PASSWORD: ${{ secrets.ORIGINAL_KEYSTORE_ALIAS_PASSWORD }}
|
||||
VERSION_CODE: ${{ steps.rel_number.outputs.version-code }}
|
||||
run: |
|
||||
./gradlew :androidApp:assembleRelease
|
||||
|
||||
- name: Archive Build
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
path: ./**/*.apk
|
||||
|
||||
- name: Create Version File
|
||||
if: github.event.inputs.release_type == 'beta'
|
||||
shell: bash
|
||||
env:
|
||||
VERSION_CODE: ${{ steps.rel_number.outputs.version-code }}
|
||||
run: |
|
||||
echo $VERSION_CODE > ./androidApp/build/outputs/version_code.txt
|
||||
|
||||
- name: Create Github Pre-Release
|
||||
if: github.event.inputs.release_type == 'beta'
|
||||
uses: softprops/action-gh-release@v2.0.8
|
||||
with:
|
||||
tag_name: ${{ steps.rel_number.outputs.version }}
|
||||
body_path: ./androidApp/build/outputs/changelogGithub
|
||||
draft: false
|
||||
prerelease: true
|
||||
files: |
|
||||
./androidApp/build/outputs/apk/release/androidApp-release.apk
|
||||
./androidApp/build/outputs/version_code.txt
|
||||
|
||||
- name: Print `git status`
|
||||
run: git status
|
||||
|
||||
play_publish:
|
||||
name: Play Publish
|
||||
runs-on: ubuntu-latest
|
||||
concurrency:
|
||||
group: playstore_deploy
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v4.2.2
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '3.2'
|
||||
bundler-cache: true
|
||||
|
||||
- name: Install Fastlane
|
||||
run: |
|
||||
gem install bundler:2.2.27
|
||||
bundle config path vendor/bundle
|
||||
bundle install --jobs 4 --retry 3
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v4
|
||||
|
||||
- uses: ./.github/actions/create-release-number
|
||||
name: Create Release Number
|
||||
id: rel_number
|
||||
|
||||
- uses: ./.github/actions/inflate-secrets
|
||||
name: Inflate Secrets
|
||||
with:
|
||||
keystore: ${{ secrets.UPLOAD_KEYSTORE_FILE }}
|
||||
google-services: ${{ secrets.GOOGLESERVICES }}
|
||||
playstore-creds: ${{ secrets.PLAYSTORECREDS }}
|
||||
|
||||
- uses: ./.github/actions/create-release-notes
|
||||
name: Create Release Notes
|
||||
with:
|
||||
tag-name: ${{ steps.rel_number.outputs.version }}
|
||||
gh-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build Release
|
||||
env:
|
||||
KEYSTORE_PATH: ${{ secrets.KEYSTORE_NAME }}
|
||||
KEYSTORE_PASSWORD: ${{ secrets.UPLOAD_KEYSTORE_FILE_PASSWORD }}
|
||||
KEYSTORE_ALIAS: ${{ secrets.UPLOAD_KEYSTORE_ALIAS }}
|
||||
KEYSTORE_ALIAS_PASSWORD: ${{ secrets.UPLOAD_KEYSTORE_ALIAS_PASSWORD }}
|
||||
VERSION_CODE: ${{ steps.rel_number.outputs.version-code }}
|
||||
run: |
|
||||
./gradlew :androidApp:bundleRelease
|
||||
|
||||
- name: Deploy to Play Store Internal
|
||||
run: bundle exec fastlane android deploy_internal
|
||||
|
||||
- name: Promote Internal to Beta
|
||||
if: github.event.inputs.release_type == 'beta'
|
||||
run: bundle exec fastlane android promote_to_beta
|
||||
35
.github/workflows/release_to_production.yml
vendored
@ -1,35 +0,0 @@
|
||||
name: Promote Beta to Production Play Store
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
SUPPLY_UPLOAD_MAX_RETRIES: 5
|
||||
|
||||
jobs:
|
||||
play_promote_production:
|
||||
name: Play Publish Production
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '3.2'
|
||||
bundler-cache: true
|
||||
|
||||
- name: Install Fastlane
|
||||
run: |
|
||||
gem install bundler:2.2.27
|
||||
bundle config path vendor/bundle
|
||||
bundle install --jobs 4 --retry 3
|
||||
|
||||
- uses: ./.github/actions/inflate-secrets
|
||||
name: Inflate Secrets
|
||||
with:
|
||||
keystore: ${{ secrets.ORIGINAL_KEYSTORE_FILE }}
|
||||
google-services: ${{ secrets.GOOGLESERVICES }}
|
||||
playstore-creds: ${{ secrets.PLAYSTORECREDS }}
|
||||
|
||||
- name: Promote Beta to Production Play Store
|
||||
run: bundle exec fastlane android promote_to_production
|
||||
@ -31,7 +31,7 @@ jobs:
|
||||
github.rest.actions.createWorkflowDispatch({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
workflow_id: 'release_to_internal_or_beta.yml',
|
||||
workflow_id: 'android-release.yml',
|
||||
ref: 'development',
|
||||
inputs: {
|
||||
"release_type": "beta",
|
||||
22
.gitignore
vendored
@ -9,7 +9,6 @@
|
||||
.externalNativeBuild
|
||||
.idea
|
||||
/*.iml
|
||||
.kotlin
|
||||
|
||||
# files for the dex VM
|
||||
*.dex
|
||||
@ -22,13 +21,25 @@ bin/
|
||||
gen/
|
||||
out/
|
||||
build/
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
iosApp/Podfile.lock
|
||||
iosApp/Pods/*
|
||||
iosApp/iosApp.xcworkspace/*
|
||||
iosApp/iosApp.xcodeproj/*
|
||||
!iosApp/iosApp.xcodeproj/project.pbxproj
|
||||
mifospay-shared/mifospay-shared.podspec
|
||||
|
||||
# Eclipse project files
|
||||
.classpath
|
||||
.project
|
||||
|
||||
# Windows thumbnail db
|
||||
.DS_Store
|
||||
|
||||
# IDEA/Android Studio project files, because
|
||||
# the project can be imported from settings.gradle.kts
|
||||
*.iml
|
||||
.idea/*
|
||||
!.idea/copyright
|
||||
# Keep the code styles.
|
||||
@ -37,7 +48,6 @@ build/
|
||||
!/.idea/codeStyles/Project.xml
|
||||
!/.idea/codeStyles/codeStyleConfig.xml
|
||||
|
||||
|
||||
# Kotlin
|
||||
.kotlin
|
||||
|
||||
@ -48,13 +58,17 @@ captures/
|
||||
app/app.iml
|
||||
app/manifest-merger-release-report.txt
|
||||
|
||||
release_keystore.keystore
|
||||
# Exclude Google services from prod flavour
|
||||
androidApp/src/prod/google-services.json
|
||||
|
||||
#*.keystore
|
||||
|
||||
version.txt
|
||||
|
||||
fastlane/report.xml
|
||||
firebaseAppDistributionServiceCredentialsFile.json
|
||||
playStorePublishServiceCredentialsFile.json
|
||||
|
||||
# Ruby stuff we don't care about
|
||||
.bundle/
|
||||
vendor/
|
||||
secrets/
|
||||
1
.ruby-version
Normal file
@ -0,0 +1 @@
|
||||
3.3.5
|
||||
73
Gemfile.lock
@ -10,20 +10,20 @@ GEM
|
||||
artifactory (3.0.17)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.3.0)
|
||||
aws-partitions (1.979.0)
|
||||
aws-sdk-core (3.209.1)
|
||||
aws-partitions (1.1035.0)
|
||||
aws-sdk-core (3.215.0)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.651.0)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
aws-sigv4 (~> 1.9)
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
aws-sdk-kms (1.94.0)
|
||||
aws-sdk-core (~> 3, >= 3.207.0)
|
||||
aws-sdk-kms (1.96.0)
|
||||
aws-sdk-core (~> 3, >= 3.210.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-s3 (1.166.0)
|
||||
aws-sdk-core (~> 3, >= 3.207.0)
|
||||
aws-sdk-s3 (1.177.0)
|
||||
aws-sdk-core (~> 3, >= 3.210.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sigv4 (1.10.0)
|
||||
aws-sigv4 (1.11.0)
|
||||
aws-eventstream (~> 1, >= 1.0.2)
|
||||
babosa (1.0.4)
|
||||
base64 (0.2.0)
|
||||
@ -38,7 +38,7 @@ GEM
|
||||
domain_name (0.6.20240107)
|
||||
dotenv (2.8.1)
|
||||
emoji_regex (3.2.3)
|
||||
excon (0.111.0)
|
||||
excon (0.112.0)
|
||||
faraday (1.10.4)
|
||||
faraday-em_http (~> 1.0)
|
||||
faraday-em_synchrony (~> 1.0)
|
||||
@ -58,8 +58,8 @@ GEM
|
||||
faraday-em_synchrony (1.0.0)
|
||||
faraday-excon (1.1.0)
|
||||
faraday-httpclient (1.0.1)
|
||||
faraday-multipart (1.0.4)
|
||||
multipart-post (~> 2)
|
||||
faraday-multipart (1.1.0)
|
||||
multipart-post (~> 2.0)
|
||||
faraday-net_http (1.0.2)
|
||||
faraday-net_http_persistent (1.2.0)
|
||||
faraday-patron (1.0.0)
|
||||
@ -67,8 +67,8 @@ GEM
|
||||
faraday-retry (1.0.3)
|
||||
faraday_middleware (1.2.1)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.3.1)
|
||||
fastlane (2.222.0)
|
||||
fastimage (2.4.0)
|
||||
fastlane (2.226.0)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.8, < 3.0.0)
|
||||
artifactory (~> 3.0)
|
||||
@ -84,6 +84,7 @@ GEM
|
||||
faraday-cookie_jar (~> 0.0.6)
|
||||
faraday_middleware (~> 1.0)
|
||||
fastimage (>= 2.1.0, < 3.0.0)
|
||||
fastlane-sirp (>= 1.0.0)
|
||||
gh_inspector (>= 1.1.2, < 2.0.0)
|
||||
google-apis-androidpublisher_v3 (~> 0.3)
|
||||
google-apis-playcustomapp_v1 (~> 0.1)
|
||||
@ -107,8 +108,14 @@ GEM
|
||||
tty-spinner (>= 0.8.0, < 1.0.0)
|
||||
word_wrap (~> 1.0.0)
|
||||
xcodeproj (>= 1.13.0, < 2.0.0)
|
||||
xcpretty (~> 0.3.0)
|
||||
xcpretty (~> 0.4.0)
|
||||
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
|
||||
fastlane-plugin-firebase_app_distribution (0.10.0)
|
||||
google-apis-firebaseappdistribution_v1 (~> 0.3.0)
|
||||
google-apis-firebaseappdistribution_v1alpha (~> 0.2.0)
|
||||
fastlane-plugin-increment_build_number (0.0.4)
|
||||
fastlane-sirp (1.0.0)
|
||||
sysrandom (~> 1.0)
|
||||
gh_inspector (1.1.3)
|
||||
google-apis-androidpublisher_v3 (0.54.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
@ -120,6 +127,10 @@ GEM
|
||||
representable (~> 3.0)
|
||||
retriable (>= 2.0, < 4.a)
|
||||
rexml
|
||||
google-apis-firebaseappdistribution_v1 (0.3.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-firebaseappdistribution_v1alpha (0.2.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-iamcredentials_v1 (0.17.0)
|
||||
google-apis-core (>= 0.11.0, < 2.a)
|
||||
google-apis-playcustomapp_v1 (0.13.0)
|
||||
@ -147,23 +158,23 @@ GEM
|
||||
os (>= 0.9, < 2.0)
|
||||
signet (>= 0.16, < 2.a)
|
||||
highline (2.0.3)
|
||||
http-cookie (1.0.7)
|
||||
http-cookie (1.0.8)
|
||||
domain_name (~> 0.5)
|
||||
httpclient (2.8.3)
|
||||
jmespath (1.6.2)
|
||||
json (2.7.2)
|
||||
jwt (2.9.1)
|
||||
json (2.9.1)
|
||||
jwt (2.10.1)
|
||||
base64
|
||||
mini_magick (4.13.2)
|
||||
mini_mime (1.1.5)
|
||||
multi_json (1.15.0)
|
||||
multipart-post (2.4.1)
|
||||
nanaimo (0.3.0)
|
||||
nanaimo (0.4.0)
|
||||
naturally (2.2.1)
|
||||
nkf (0.2.0)
|
||||
optparse (0.5.0)
|
||||
optparse (0.6.0)
|
||||
os (1.1.4)
|
||||
plist (3.7.1)
|
||||
plist (3.7.2)
|
||||
public_suffix (6.0.1)
|
||||
rake (13.2.1)
|
||||
representable (3.2.0)
|
||||
@ -171,10 +182,10 @@ GEM
|
||||
trailblazer-option (>= 0.1.1, < 0.2.0)
|
||||
uber (< 0.2.0)
|
||||
retriable (3.1.2)
|
||||
rexml (3.3.7)
|
||||
rouge (2.0.7)
|
||||
rexml (3.4.0)
|
||||
rouge (3.28.0)
|
||||
ruby2_keywords (0.0.5)
|
||||
rubyzip (2.3.2)
|
||||
rubyzip (2.4.1)
|
||||
security (0.1.5)
|
||||
signet (0.19.0)
|
||||
addressable (~> 2.8)
|
||||
@ -184,6 +195,7 @@ GEM
|
||||
simctl (1.6.10)
|
||||
CFPropertyList
|
||||
naturally
|
||||
sysrandom (1.0.5)
|
||||
terminal-notifier (2.0.0)
|
||||
terminal-table (3.0.2)
|
||||
unicode-display_width (>= 1.1.1, < 3)
|
||||
@ -195,25 +207,26 @@ GEM
|
||||
uber (0.1.0)
|
||||
unicode-display_width (2.6.0)
|
||||
word_wrap (1.0.0)
|
||||
xcodeproj (1.25.0)
|
||||
xcodeproj (1.27.0)
|
||||
CFPropertyList (>= 2.3.3, < 4.0)
|
||||
atomos (~> 0.1.3)
|
||||
claide (>= 1.0.2, < 2.0)
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.3.0)
|
||||
rexml (>= 3.3.2, < 4.0)
|
||||
xcpretty (0.3.0)
|
||||
rouge (~> 2.0.7)
|
||||
nanaimo (~> 0.4.0)
|
||||
rexml (>= 3.3.6, < 4.0)
|
||||
xcpretty (0.4.0)
|
||||
rouge (~> 3.28.0)
|
||||
xcpretty-travis-formatter (1.0.1)
|
||||
xcpretty (~> 0.2, >= 0.0.7)
|
||||
|
||||
PLATFORMS
|
||||
arm64-darwin-22
|
||||
ruby
|
||||
x64-mingw-ucrt
|
||||
x86_64-linux
|
||||
|
||||
DEPENDENCIES
|
||||
fastlane
|
||||
fastlane-plugin-firebase_app_distribution
|
||||
fastlane-plugin-increment_build_number
|
||||
|
||||
BUNDLED WITH
|
||||
2.5.18
|
||||
|
||||
@ -35,7 +35,7 @@ android {
|
||||
|
||||
signingConfigs {
|
||||
create("release") {
|
||||
storeFile = file(System.getenv("KEYSTORE_PATH") ?: "debug_keystore.jks")
|
||||
storeFile = file(System.getenv("KEYSTORE_PATH") ?: "../keystores/release_keystore.keystore")
|
||||
storePassword = System.getenv("KEYSTORE_PASSWORD") ?: "mifos1234"
|
||||
keyAlias = System.getenv("KEYSTORE_ALIAS") ?: "mifos-mobile"
|
||||
keyPassword = System.getenv("KEYSTORE_ALIAS_PASSWORD") ?: "mifos1234"
|
||||
@ -63,6 +63,17 @@ android {
|
||||
compose = true
|
||||
buildConfig = true
|
||||
}
|
||||
|
||||
lint {
|
||||
xmlReport = true
|
||||
checkDependencies = true
|
||||
abortOnError = false
|
||||
// Disable this rule until we ship the libraries to some maven.
|
||||
disable += "ResourceName"
|
||||
baseline = File("lint-baseline.xml")
|
||||
explainIssues = true
|
||||
htmlReport = true
|
||||
}
|
||||
}
|
||||
|
||||
dependencyGuard {
|
||||
|
||||
@ -1,54 +1,62 @@
|
||||
{
|
||||
"project_info": {
|
||||
"project_number": "622027757397",
|
||||
"firebase_url": "https://mifosmaps.firebaseio.com",
|
||||
"project_id": "mifosmaps",
|
||||
"storage_bucket": "mifosmaps.appspot.com"
|
||||
"project_number": "project_number",
|
||||
"firebase_url": "firebase_url",
|
||||
"project_id": "project_id",
|
||||
"storage_bucket": "storage_bucket"
|
||||
},
|
||||
"client": [
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "1:622027757397:android:29f731fdcd3a65a6",
|
||||
"mobilesdk_app_id": "mobilesdk_app_id",
|
||||
"android_client_info": {
|
||||
"package_name": "org.mifos.mobile"
|
||||
}
|
||||
},
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "current_key"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "mobilesdk_app_id",
|
||||
"android_client_info": {
|
||||
"package_name": "org.mifos.mobile.demo.debug"
|
||||
}
|
||||
},
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "current_key"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "mobilesdk_app_id",
|
||||
"android_client_info": {
|
||||
"package_name": "org.mifos.mobile.demo"
|
||||
}
|
||||
},
|
||||
"oauth_client": [
|
||||
{
|
||||
"client_id": "622027757397-ju1gahmo27fjfc39v5drlnn3838rleiq.apps.googleusercontent.com",
|
||||
"client_type": 1,
|
||||
"android_info": {
|
||||
"package_name": "org.mifos.mobile",
|
||||
"certificate_hash": "2f8ce9c728acf6b9c50750b328742d5391c0b303"
|
||||
}
|
||||
},
|
||||
{
|
||||
"client_id": "622027757397-k76e8mb3s75ktuj5c011ng0r7mnmbgkr.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
],
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "AIzaSyCsoeQjAaAum-1VFKJL9vxOhGN8E9s0Plw"
|
||||
"current_key": "current_key"
|
||||
}
|
||||
],
|
||||
"services": {
|
||||
"analytics_service": {
|
||||
"status": 1
|
||||
},
|
||||
"appinvite_service": {
|
||||
"status": 2,
|
||||
"other_platform_oauth_client": [
|
||||
{
|
||||
"client_id": "622027757397-o2k3acan0jdhf7t0uddd9o4fd72bedda.apps.googleusercontent.com",
|
||||
"client_type": 3
|
||||
}
|
||||
]
|
||||
},
|
||||
"ads_service": {
|
||||
"status": 2
|
||||
]
|
||||
},
|
||||
{
|
||||
"client_info": {
|
||||
"mobilesdk_app_id": "mobilesdk_app_id",
|
||||
"android_client_info": {
|
||||
"package_name": "org.mifos.mobile.debug"
|
||||
}
|
||||
}
|
||||
},
|
||||
"api_key": [
|
||||
{
|
||||
"current_key": "current_key"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"configuration_version": "1"
|
||||
|
||||
@ -17,22 +17,26 @@
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_VISUAL_USER_SELECTED" />
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
|
||||
<uses-feature android:name="android.hardware.camera.any" />
|
||||
|
||||
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission
|
||||
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||
android:maxSdkVersion="32" />
|
||||
|
||||
<uses-permission android:name="com.google.android.gms.permission.AD_ID" tools:node="remove"/>
|
||||
<uses-permission
|
||||
android:name="com.google.android.gms.permission.AD_ID"
|
||||
tools:node="remove" />
|
||||
|
||||
<application
|
||||
android:name=".MifosSelfServiceApp"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:label="@string/feature_about_app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.MifosSplash">
|
||||
<activity
|
||||
@ -56,6 +60,7 @@
|
||||
<meta-data
|
||||
android:name="com.google.android.geo.API_KEY"
|
||||
android:value="@string/google_maps_key" />
|
||||
|
||||
<activity
|
||||
android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
|
||||
android:configChanges="orientation|screenSize"
|
||||
|
||||
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 84 KiB |
BIN
androidApp/src/main/res/drawable/splash_icon.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Mifos Initiative
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file,
|
||||
You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md
|
||||
-->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item>
|
||||
<color android:color="@color/white" />
|
||||
</item>
|
||||
|
||||
<item
|
||||
android:width="160dp"
|
||||
android:height="160dp"
|
||||
android:drawable="@drawable/mifos_splash_screen_logo"
|
||||
android:gravity="center" />
|
||||
</layer-list>
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Mifos Initiative
|
||||
Copyright 2025 Mifos Initiative
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file,
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Mifos Initiative
|
||||
Copyright 2025 Mifos Initiative
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file,
|
||||
|
||||
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 6.1 KiB |
|
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 15 KiB |
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
Copyright 2024 Mifos Initiative
|
||||
Copyright 2025 Mifos Initiative
|
||||
|
||||
This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
|
||||
If a copy of the MPL was not distributed with this file,
|
||||
@ -9,5 +9,5 @@
|
||||
See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md
|
||||
-->
|
||||
<resources>
|
||||
<color name="ic_launcher_background">#F6F8F7</color>
|
||||
<color name="ic_launcher_background">#450951</color>
|
||||
</resources>
|
||||
@ -1,2 +1,2 @@
|
||||
json_key_file("androidApp/playStorePublishServiceCredentialsFile.json")
|
||||
json_key_file("secrets/playStorePublishServiceCredentialsFile.json")
|
||||
package_name("org.mifos.mobile") # e.g. org.mifos.mobile
|
||||
@ -1,11 +1,90 @@
|
||||
default_platform(:android)
|
||||
|
||||
platform :android do
|
||||
desc "Assemble debug APKs."
|
||||
lane :assembleDebugApks do |options|
|
||||
gradle(
|
||||
tasks: ["assembleDebug"],
|
||||
)
|
||||
end
|
||||
|
||||
desc "Assemble Release APK"
|
||||
lane :assembleReleaseApks do |options|
|
||||
options[:storeFile] ||= "release_keystore.keystore"
|
||||
options[:storePassword] ||= "mifos1234"
|
||||
options[:keyAlias] ||= "mifos-mobile"
|
||||
options[:keyPassword] ||= "mifos1234"
|
||||
|
||||
# Generate version
|
||||
generateVersion = generateVersion()
|
||||
|
||||
buildAndSignApp(
|
||||
taskName: "assemble",
|
||||
buildType: "Release",
|
||||
storeFile: options[:storeFile],
|
||||
storePassword: options[:storePassword],
|
||||
keyAlias: options[:keyAlias],
|
||||
keyPassword: options[:keyPassword],
|
||||
)
|
||||
end
|
||||
|
||||
desc "Bundle Play Store release"
|
||||
lane :bundlePlayStoreRelease do |options|
|
||||
options[:storeFile] ||= "release_keystore.keystore"
|
||||
options[:storePassword] ||= "mifos1234"
|
||||
options[:keyAlias] ||= "mifos-mobile"
|
||||
options[:keyPassword] ||= "mifos1234"
|
||||
|
||||
# Generate version
|
||||
generateVersion = generateVersion()
|
||||
|
||||
# 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: "bundle",
|
||||
buildType: "Release",
|
||||
storeFile: options[:storeFile],
|
||||
storePassword: options[:storePassword],
|
||||
keyAlias: options[:keyAlias],
|
||||
keyPassword: options[:keyPassword],
|
||||
)
|
||||
end
|
||||
|
||||
desc "Publish Release Play Store artifacts to Firebase App Distribution"
|
||||
lane :deploy_on_firebase do |options|
|
||||
options[:apkFile] ||= "androidApp/build/outputs/apk/prod/release/androidApp-prod-release.apk"
|
||||
options[:serviceCredsFile] ||= "secrets/firebaseAppDistributionServiceCredentialsFile.json"
|
||||
options[:groups] ||= "mifos-mobile-testers"
|
||||
|
||||
# Generate Release Note
|
||||
releaseNotes = generateFullReleaseNote()
|
||||
|
||||
firebase_app_distribution(
|
||||
app: "1:728434912738:android:d853a78f14af0c381a1dbb",
|
||||
android_artifact_type: "APK",
|
||||
android_artifact_path: options[:apkFile],
|
||||
service_credentials_file: options[:serviceCredsFile],
|
||||
groups: options[:groups],
|
||||
release_notes: "#{releaseNotes}",
|
||||
)
|
||||
end
|
||||
|
||||
desc "Deploy internal tracks to Google Play"
|
||||
lane :deploy_internal do
|
||||
supply(
|
||||
lane :deploy_internal do |options|
|
||||
options[:aabFile] ||= "androidApp/build/outputs/bundle/prodRelease/androidApp-prod-release.aab"
|
||||
upload_to_play_store(
|
||||
track: 'internal',
|
||||
aab: 'androidApp/build/outputs/bundle/release/androidApp-release.aab',
|
||||
aab: options[:aabFile],
|
||||
skip_upload_metadata: true,
|
||||
skip_upload_images: true,
|
||||
skip_upload_screenshots: true,
|
||||
@ -14,7 +93,7 @@ platform :android do
|
||||
|
||||
desc "Promote internal tracks to beta on Google Play"
|
||||
lane :promote_to_beta do
|
||||
supply(
|
||||
upload_to_play_store(
|
||||
track: 'internal',
|
||||
track_promote_to: 'beta',
|
||||
skip_upload_changelogs: true,
|
||||
@ -26,12 +105,278 @@ platform :android do
|
||||
|
||||
desc "Promote beta tracks to production on Google Play"
|
||||
lane :promote_to_production do
|
||||
supply(
|
||||
upload_to_play_store(
|
||||
track: 'beta',
|
||||
track_promote_to: 'production',
|
||||
skip_upload_changelogs: true,
|
||||
sync_image_upload: true,
|
||||
skip_upload_metadata: true,
|
||||
skip_upload_images: true,
|
||||
skip_upload_screenshots: true,
|
||||
)
|
||||
end
|
||||
|
||||
desc "Generate artifacts for the given [build] signed with the provided [keystore] and credentials."
|
||||
private_lane :buildAndSignApp do |options|
|
||||
# Get the project root directory
|
||||
project_dir = File.expand_path('..', Dir.pwd)
|
||||
|
||||
# Construct the absolute path to the keystore
|
||||
keystore_path = File.join(project_dir, 'keystores', options[:storeFile])
|
||||
|
||||
# Check if keystore exists
|
||||
unless File.exist?(keystore_path)
|
||||
UI.error "Keystore file not found at: #{keystore_path}"
|
||||
UI.error "Please ensure the keystore file exists at the correct location"
|
||||
exit 1 # Exit with error code 1
|
||||
end
|
||||
|
||||
gradle(
|
||||
task: options[:taskName],
|
||||
build_type: options[:buildType],
|
||||
properties: {
|
||||
"android.injected.signing.store.file" => keystore_path,
|
||||
"android.injected.signing.store.password" => options[:storePassword],
|
||||
"android.injected.signing.key.alias" => options[:keyAlias],
|
||||
"android.injected.signing.key.password" => options[:keyPassword],
|
||||
},
|
||||
print_command: false,
|
||||
)
|
||||
end
|
||||
|
||||
desc "Generate 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',
|
||||
)
|
||||
|
||||
# Find highest version code
|
||||
latest_code = (prod_codes + beta_codes).max || 1
|
||||
new_version_code = latest_code + 1
|
||||
|
||||
# Generate version file
|
||||
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
|
||||
|
||||
desc "Generate release notes"
|
||||
lane :generateReleaseNotes do |options|
|
||||
releaseNotes = changelog_from_git_commits(
|
||||
commits_count: 1,
|
||||
)
|
||||
releaseNotes
|
||||
end
|
||||
|
||||
desc "Generate release notes from specified tag or latest release tag"
|
||||
lane :generateFullReleaseNote do |options|
|
||||
# Platform-independent way to get the latest tag
|
||||
def get_latest_tag
|
||||
begin
|
||||
# Try to get the latest tag without redirection
|
||||
latest = `git describe --tags --abbrev=0`.strip
|
||||
return latest unless latest.empty?
|
||||
rescue
|
||||
begin
|
||||
# Alternative approach if the first one fails
|
||||
latest = `git tag --sort=-creatordate`.split("\n").first
|
||||
return latest unless latest.nil? || latest.empty?
|
||||
rescue
|
||||
return nil
|
||||
end
|
||||
end
|
||||
nil
|
||||
end
|
||||
|
||||
# Get the tag from options or find the latest tag
|
||||
from_tag = options[:from_tag]
|
||||
if from_tag
|
||||
UI.message "Using specified tag: #{from_tag}"
|
||||
# Verify the tag exists
|
||||
unless system("git rev-parse #{from_tag}")
|
||||
UI.user_error! "Tag #{from_tag} not found!"
|
||||
return
|
||||
end
|
||||
else
|
||||
from_tag = get_latest_tag
|
||||
if from_tag && !from_tag.empty?
|
||||
UI.message "Using latest tag: #{from_tag}"
|
||||
else
|
||||
UI.message "No tags found. Getting all commits..."
|
||||
end
|
||||
end
|
||||
|
||||
# Get commits since the tag
|
||||
commits = if from_tag && !from_tag.empty?
|
||||
`git log #{from_tag}..HEAD --pretty=format:"%B"`.split("\n")
|
||||
else
|
||||
`git log --pretty=format:"%B"`.split("\n")
|
||||
end
|
||||
|
||||
# Process commits to get actual commit messages and remove Co-authored-by lines
|
||||
processed_commits = []
|
||||
current_commit = []
|
||||
|
||||
commits.each do |line|
|
||||
# Skip empty lines and Co-authored-by lines
|
||||
next if line.empty? || line.start_with?("Co-authored-by:")
|
||||
|
||||
if line.start_with?("Merge pull request")
|
||||
# For merge commits, we want to get the actual commit message
|
||||
next
|
||||
elsif current_commit.empty? || !line.start_with?(" ")
|
||||
# If it's a new commit message, store the previous one (if exists) and start a new one
|
||||
processed_commits << current_commit.join(" ") unless current_commit.empty?
|
||||
current_commit = [line]
|
||||
else
|
||||
# Continue with current commit message
|
||||
current_commit << line
|
||||
end
|
||||
end
|
||||
# Add the last commit
|
||||
processed_commits << current_commit.join(" ") unless current_commit.empty?
|
||||
|
||||
# Remove empty strings and duplicates
|
||||
processed_commits = processed_commits.reject(&:empty?).uniq
|
||||
|
||||
# Initialize categories
|
||||
notes = {
|
||||
"feat" => [], # Features
|
||||
"fix" => [], # Bug fixes
|
||||
"perf" => [], # Performance
|
||||
"refactor" => [], # Refactoring
|
||||
"style" => [], # Style
|
||||
"docs" => [], # Documentation
|
||||
"test" => [], # Tests
|
||||
"build" => [], # Build
|
||||
"ci" => [], # CI
|
||||
"chore" => [], # Maintenance
|
||||
"breaking" => [], # Breaking changes
|
||||
"other" => [] # Other
|
||||
}
|
||||
|
||||
# Categorize commits
|
||||
processed_commits.each do |commit|
|
||||
# Handle breaking changes
|
||||
if commit.include?("BREAKING CHANGE:") || commit.include?("!")
|
||||
notes["breaking"] << commit.sub(/^[^:]+:\s*/, "")
|
||||
next
|
||||
end
|
||||
|
||||
# Match conventional commit format
|
||||
if commit =~ /^(feat|fix|perf|refactor|style|docs|test|build|ci|chore)(\(.+?\))?:/
|
||||
type = $1
|
||||
notes[type] << commit.sub(/^[^:]+:\s*/, "")
|
||||
else
|
||||
notes["other"] << commit unless commit.start_with?("Merge")
|
||||
end
|
||||
end
|
||||
|
||||
# Format release notes
|
||||
sections = {
|
||||
"breaking" => "💥 Breaking Changes",
|
||||
"feat" => "🚀 New Features",
|
||||
"fix" => "🐛 Bug Fixes",
|
||||
"perf" => "⚡ Performance Improvements",
|
||||
"refactor" => "♻️ Refactoring",
|
||||
"style" => "💅 Style Changes",
|
||||
"docs" => "📚 Documentation",
|
||||
"test" => "🧪 Tests",
|
||||
"build" => "📦 Build System",
|
||||
"ci" => "👷 CI Changes",
|
||||
"chore" => "🔧 Maintenance",
|
||||
"other" => "📝 Other Changes"
|
||||
}
|
||||
|
||||
# Build release notes
|
||||
release_notes = ["# Release Notes"]
|
||||
release_notes << "\nRelease date: #{Time.now.strftime('%d-%m-%Y')}"
|
||||
|
||||
sections.each do |type, title|
|
||||
next if notes[type].empty?
|
||||
release_notes << "\n## #{title}"
|
||||
notes[type].each do |commit|
|
||||
release_notes << "\n- #{commit}"
|
||||
end
|
||||
end
|
||||
|
||||
# Print release notes
|
||||
UI.message "Generated Release Notes:"
|
||||
UI.message release_notes.join("\n")
|
||||
|
||||
# Return the release notes string
|
||||
release_notes.join("\n")
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
platform :ios do
|
||||
desc "Build iOS application"
|
||||
lane :build_ios do |options|
|
||||
# Set default configuration if not provided
|
||||
options[:configuration] ||= "Debug"
|
||||
|
||||
# automatic code signing
|
||||
update_code_signing_settings(
|
||||
use_automatic_signing: true,
|
||||
path: "mifos-ios/iosApp.xcodeproj"
|
||||
)
|
||||
build_ios_app(
|
||||
project: "mifos-ios/iosApp.xcodeproj",
|
||||
scheme: "iosApp",
|
||||
# Set configuration to debug for now
|
||||
configuration: options[:configuration],
|
||||
skip_codesigning: "true",
|
||||
output_directory: "mifos-ios/build",
|
||||
skip_archive: "true"
|
||||
)
|
||||
end
|
||||
|
||||
lane :increment_version do |options|
|
||||
options[:serviceCredsFile] ||= "secrets/firebaseAppDistributionServiceCredentialsFile.json"
|
||||
|
||||
latest_release = firebase_app_distribution_get_latest_release(
|
||||
app: "1:728434912738:ios:86a7badfaed88b841a1dbb",
|
||||
service_credentials_file: options[:serviceCredsFile]
|
||||
)
|
||||
increment_build_number(
|
||||
xcodeproj: "mifos-ios/iosApp.xcodeproj",
|
||||
build_number: latest_release[:buildVersion].to_i + 1
|
||||
)
|
||||
end
|
||||
|
||||
desc "Upload iOS application to Firebase App Distribution"
|
||||
lane :deploy_on_firebase do |options|
|
||||
options[:serviceCredsFile] ||= "secrets/firebaseAppDistributionServiceCredentialsFile.json"
|
||||
options[:groups] ||= "mifos-mobile-testers"
|
||||
|
||||
increment_version()
|
||||
build_ios()
|
||||
releaseNotes = generateReleaseNotes()
|
||||
release = firebase_app_distribution(
|
||||
app: "1:728434912738:ios:86a7badfaed88b841a1dbb",
|
||||
service_credentials_file: options[:serviceCredsFile],
|
||||
release_notes_file: "#{releaseNotes}",
|
||||
groups: options[:groups]
|
||||
)
|
||||
|
||||
end
|
||||
|
||||
desc "Generate release notes"
|
||||
lane :generateReleaseNotes do
|
||||
branchName = `git rev-parse --abbrev-ref HEAD`.chomp()
|
||||
releaseNotes = changelog_from_git_commits(
|
||||
commits_count: 1,
|
||||
)
|
||||
releaseNotes
|
||||
end
|
||||
end
|
||||
@ -1,3 +1,5 @@
|
||||
# Autogenerated by fastlane
|
||||
#
|
||||
# Ensure this file is checked in to source control!
|
||||
gem 'fastlane-plugin-firebase_app_distribution'
|
||||
gem 'fastlane-plugin-increment_build_number'
|
||||
|
||||
@ -15,6 +15,38 @@ For _fastlane_ installation instructions, see [Installing _fastlane_](https://do
|
||||
|
||||
## Android
|
||||
|
||||
### android assembleDebugApks
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane android assembleDebugApks
|
||||
```
|
||||
|
||||
Assemble debug APKs.
|
||||
|
||||
### android assembleReleaseApks
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane android assembleReleaseApks
|
||||
```
|
||||
|
||||
Assemble Release APK
|
||||
|
||||
### android bundlePlayStoreRelease
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane android bundlePlayStoreRelease
|
||||
```
|
||||
|
||||
Bundle Play Store release
|
||||
|
||||
### android deploy_on_firebase
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane android deploy_on_firebase
|
||||
```
|
||||
|
||||
Publish Release Play Store artifacts to Firebase App Distribution
|
||||
|
||||
### android deploy_internal
|
||||
|
||||
```sh
|
||||
@ -39,6 +71,67 @@ Promote internal tracks to beta on Google Play
|
||||
|
||||
Promote beta tracks to production on Google Play
|
||||
|
||||
### android generateVersion
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane android generateVersion
|
||||
```
|
||||
|
||||
Generate Version
|
||||
|
||||
### android generateReleaseNotes
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane android generateReleaseNotes
|
||||
```
|
||||
|
||||
Generate release notes
|
||||
|
||||
### android generateFullReleaseNote
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane android generateFullReleaseNote
|
||||
```
|
||||
|
||||
Generate release notes from specified tag or latest release tag
|
||||
|
||||
----
|
||||
|
||||
|
||||
## iOS
|
||||
|
||||
### ios build_ios
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane ios build_ios
|
||||
```
|
||||
|
||||
Build iOS application
|
||||
|
||||
### ios increment_version
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane ios increment_version
|
||||
```
|
||||
|
||||
|
||||
|
||||
### ios deploy_on_firebase
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane ios deploy_on_firebase
|
||||
```
|
||||
|
||||
Upload iOS application to Firebase App Distribution
|
||||
|
||||
### ios generateReleaseNotes
|
||||
|
||||
```sh
|
||||
[bundle exec] fastlane ios generateReleaseNotes
|
||||
```
|
||||
|
||||
Generate release notes
|
||||
|
||||
----
|
||||
|
||||
This README.md is auto-generated and will be re-generated every time [_fastlane_](https://fastlane.tools) is run.
|
||||
|
||||
6
fastlane/metadata/android/en-US/changelogs/default.txt
Normal file
@ -0,0 +1,6 @@
|
||||
fix: API endpoint (#2733)
|
||||
* MM-102 KMP dependencies setup (#2729)
|
||||
* fix: API endpoint
|
||||
---------
|
||||
Co-authored-by: Sk Niyaj Ali <skniyajali0@gmail.com>
|
||||
Co-authored-by: Pronay Sarker <pronaycoding@gmail.com>s
|
||||
@ -1,3 +1,5 @@
|
||||
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
|
||||
|
||||
plugins {
|
||||
alias(libs.plugins.kotlinMultiplatform)
|
||||
alias(libs.plugins.android.library)
|
||||
@ -6,7 +8,11 @@ plugins {
|
||||
}
|
||||
|
||||
kotlin {
|
||||
androidTarget()
|
||||
androidTarget() {
|
||||
compilerOptions {
|
||||
jvmTarget.set(JvmTarget.JVM_17)
|
||||
}
|
||||
}
|
||||
|
||||
listOf(
|
||||
iosX64(),
|
||||
|
||||