From fe4fd28171964060242f723a86e7ddfb295f92aa Mon Sep 17 00:00:00 2001 From: Sk Niyaj Ali Date: Fri, 6 Sep 2024 03:43:49 +0530 Subject: [PATCH] Configured CI/CD And Fastlane to Release App to Play Store This commit introduces a comprehensive CI/CD pipeline using Github Actions and Fastlane. The following workflows have been added: - **On Push:** Builds, archives, and creates Github pre-releases for beta builds. Deploys to Playstore internal track and promotes to beta if specified. - **Play Publish:** Builds and deploys to Playstore internal track. Optionally promotes to beta. - ** Production Deploy:** Promotes beta releases to production on the Playstore. - **Bump our Calendar Version:** Creates monthly releases. - **Tag Weekly Release:** Tags weekly releases and triggers the On Push workflow for beta builds. Additionally, Fastlane has been configured to handle deployments to the Playstore and Amazon Appstore. Secret inflation and release note generation have been automated using Github Actions. --- .../actions/create-release-notes/action.yml | 56 +++++ .../actions/create-release-number/action.yml | 27 +++ .github/actions/inflate-secrets/action.yml | 41 ++++ .github/mock-google-services.json | 63 +++++ .github/workflows/monthly.yaml | 21 ++ .github/workflows/onPush.yml | 154 ++++++++++++ .github/workflows/release_to_production.yml | 31 +++ .github/workflows/weekly.yaml | 39 ++++ .gitignore | 11 + Gemfile | 6 + Gemfile.lock | 219 ++++++++++++++++++ build.gradle.kts | 7 + fastlane/AppFile | 2 + fastlane/FastFile | 60 +++++ fastlane/PluginFile | 5 + mifospay/build.gradle.kts | 42 ++-- mifospay/google-services.json | 6 +- mifospay/src/main/res/values/splash.xml | 9 +- settings.gradle.kts | 10 + 19 files changed, 787 insertions(+), 22 deletions(-) create mode 100644 .github/actions/create-release-notes/action.yml create mode 100644 .github/actions/create-release-number/action.yml create mode 100644 .github/actions/inflate-secrets/action.yml create mode 100644 .github/mock-google-services.json create mode 100644 .github/workflows/monthly.yaml create mode 100644 .github/workflows/onPush.yml create mode 100644 .github/workflows/release_to_production.yml create mode 100644 .github/workflows/weekly.yaml create mode 100644 Gemfile create mode 100644 Gemfile.lock create mode 100644 fastlane/AppFile create mode 100644 fastlane/FastFile create mode 100644 fastlane/PluginFile diff --git a/.github/actions/create-release-notes/action.yml b/.github/actions/create-release-notes/action.yml new file mode 100644 index 000000000..dce0e7be5 --- /dev/null +++ b/.github/actions/create-release-notes/action.yml @@ -0,0 +1,56 @@ +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: 'dev', + 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 ./app/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" > ./mifospay/build/outputs/changelogGithub + + echo "Beta Changelog:" + git log --format="* %s" HEAD^..HEAD + git log --format="* %s" HEAD^..HEAD > ./mifospay/build/outputs/changelogBeta diff --git a/.github/actions/create-release-number/action.yml b/.github/actions/create-release-number/action.yml new file mode 100644 index 000000000..d9d16cf61 --- /dev/null +++ b/.github/actions/create-release-number/action.yml @@ -0,0 +1,27 @@ +name: 'Create Release Numbers' +description: 'Creates the current release number based on checked out code' +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 + id: version-generator + shell: bash + run: | + ./gradlew versionFile + COMMITS=`git rev-list --count HEAD` + TAGS=`git tag | grep -v beta | wc -l` + VC=$((((COMMITS+TAGS) * 3) << 1)) + echo Number Commits $COMMITS + echo Number Tags $TAGS + echo Version Code $VC + echo "version-code=$VC" >> $GITHUB_OUTPUT + VERSION=`cat version.txt` + echo Version $VERSION + echo "version=$VERSION" >> $GITHUB_OUTPUT diff --git a/.github/actions/inflate-secrets/action.yml b/.github/actions/inflate-secrets/action.yml new file mode 100644 index 000000000..d9a013eda --- /dev/null +++ b/.github/actions/inflate-secrets/action.yml @@ -0,0 +1,41 @@ +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 mifospay/src/demo/google-services.json + cp .github/mock-google-services.json mifospay/src/prod/google-services.json + + - name: Inflate release_keystore.keystore + shell: bash + env: + KEYSTORE: ${{ inputs.keystore }} + run: | + echo $KEYSTORE | base64 --decode > mifospay/release_keystore.keystore + + - name: Inflate google-services.json + shell: bash + env: + GOOGLE_SERVICES: ${{ inputs.google-services }} + run: | + echo $GOOGLE_SERVICES > mifospay/google-services.json + + - name: Inflate playStorePublishServiceCredentialsFile.json + shell: bash + env: + CREDS: ${{ inputs.playstore-creds }} + run: | + echo $CREDS > mifospay/playStorePublishServiceCredentialsFile.json diff --git a/.github/mock-google-services.json b/.github/mock-google-services.json new file mode 100644 index 000000000..2f054dffe --- /dev/null +++ b/.github/mock-google-services.json @@ -0,0 +1,63 @@ +{ + "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.mifospay" + } + }, + "api_key": [ + { + "current_key": "current_key" + } + ] + }, + { + "client_info": { + "mobilesdk_app_id": "mobilesdk_app_id", + "android_client_info": { + "package_name": "org.mifospay.demo.debug" + } + }, + "api_key": [ + { + "current_key": "current_key" + } + ] + }, + { + "client_info": { + "mobilesdk_app_id": "mobilesdk_app_id", + "android_client_info": { + "package_name": "org.mifospay.demo" + } + }, + "api_key": [ + { + "current_key": "current_key" + } + ] + }, + { + "client_info": { + "mobilesdk_app_id": "mobilesdk_app_id", + "android_client_info": { + "package_name": "org.mifospay.debug" + } + }, + "api_key": [ + { + "current_key": "current_key" + } + ] + } + ], + "configuration_version": "1" +} diff --git a/.github/workflows/monthly.yaml b/.github/workflows/monthly.yaml new file mode 100644 index 000000000..9f173e9ed --- /dev/null +++ b/.github/workflows/monthly.yaml @@ -0,0 +1,21 @@ +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 diff --git a/.github/workflows/onPush.yml b/.github/workflows/onPush.yml new file mode 100644 index 000000000..791b679e2 --- /dev/null +++ b/.github/workflows/onPush.yml @@ -0,0 +1,154 @@ +name: On Push + +on: + workflow_dispatch: + inputs: + beta: + description: 'true if this is a beta release' + required: false + default: 'false' + push: + branches: + - master + +env: + SUPPLY_UPLOAD_MAX_RETRIES: 5 + +jobs: + app_build: + name: Github, Firebase, and Sentry 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_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 :mifospay:assembleRelease + + - name: Archive Build + uses: actions/upload-artifact@v4 + with: + path: ./**/*.apk + + - name: Create Version File + if: github.event.inputs.beta == 'true' + shell: bash + env: + VERSION_CODE: ${{ steps.rel_number.outputs.version-code }} + run: | + echo $VERSION_CODE > ./app/build/outputs/version_code.txt + + - name: Create Github Pre-Release + if: github.event.inputs.beta == 'true' + uses: softprops/action-gh-release@v2.0.8 + with: + tag_name: ${{ steps.rel_number.outputs.version }} + body_path: ./app/build/outputs/changelogGithub + draft: false + prerelease: true + files: | + ./mifospay/build/outputs/apk/demo/release/mifospay-demo-release.apk + ./mifospay/build/outputs/apk/prod/release/mifospay-prod-release.apk + ./mifospay/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: 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_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 :mifospay:bundleRelease + + - name: Deploy to Playstore Internal + run: bundle exec fastlane deploy_internal + + - name: Promote Internal to Beta + if: github.event.inputs.beta == 'true' + run: bundle exec fastlane promote_to_beta diff --git a/.github/workflows/release_to_production.yml b/.github/workflows/release_to_production.yml new file mode 100644 index 000000000..347ccc4ba --- /dev/null +++ b/.github/workflows/release_to_production.yml @@ -0,0 +1,31 @@ +name: Production Deploy + +on: + workflow_dispatch: + release: + types: [ released ] + +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 + + - 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 promote_to_production diff --git a/.github/workflows/weekly.yaml b/.github/workflows/weekly.yaml new file mode 100644 index 000000000..2e5281576 --- /dev/null +++ b/.github/workflows/weekly.yaml @@ -0,0 +1,39 @@ +name: Tag Weekly Release + +on: + workflow_dispatch: + schedule: + - cron: '0 4 * * 0' +jobs: + tag: + name: Tag Weekly Release + runs-on: ubuntu-latest + 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' + + - name: Tag Weekly Release + env: + GITHUB_TOKEN: ${{ secrets.TAG_PUSH_TOKEN }} + run: ./gradlew :reckonTagPush -Preckon.stage=final + + - name: Trigger Workflow + uses: actions/github-script@v7 + with: + script: | + github.rest.actions.createWorkflowDispatch({ + owner: context.repo.owner, + repo: context.repo.repo, + workflow_id: 'onPush.yml', + ref: 'master', + inputs: { + "beta": "true", + }, + }) diff --git a/.gitignore b/.gitignore index 1696ea9b4..8425b70b0 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,14 @@ app/manifest-merger-release-report.txt # Exclude Google services from prod flavour mifospay/src/prod/google-services.json + +*.keystore + +version.txt + +firebaseAppDistributionServiceCredentialsFile.json +playStorePublishServiceCredentialsFile.json + +# Ruby stuff we don't care about +.bundle/ +vendor/ diff --git a/Gemfile b/Gemfile new file mode 100644 index 000000000..1e4d11c03 --- /dev/null +++ b/Gemfile @@ -0,0 +1,6 @@ +source "https://rubygems.org" + +gem "fastlane" + +plugins_path = File.join(File.dirname(__FILE__), 'fastlane', 'Pluginfile') +eval_gemfile(plugins_path) if File.exist?(plugins_path) \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 000000000..fe069a866 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,219 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.7) + base64 + nkf + rexml + addressable (2.8.7) + public_suffix (>= 2.0.2, < 7.0) + artifactory (3.0.17) + atomos (0.1.3) + aws-eventstream (1.3.0) + aws-partitions (1.971.0) + aws-sdk-core (3.203.0) + aws-eventstream (~> 1, >= 1.3.0) + aws-partitions (~> 1, >= 1.651.0) + aws-sigv4 (~> 1.9) + jmespath (~> 1, >= 1.6.1) + aws-sdk-kms (1.89.0) + aws-sdk-core (~> 3, >= 3.203.0) + aws-sigv4 (~> 1.5) + aws-sdk-s3 (1.160.0) + aws-sdk-core (~> 3, >= 3.203.0) + aws-sdk-kms (~> 1) + aws-sigv4 (~> 1.5) + aws-sigv4 (1.9.1) + aws-eventstream (~> 1, >= 1.0.2) + babosa (1.0.4) + base64 (0.2.0) + claide (1.1.0) + colored (1.2) + colored2 (3.1.2) + commander (4.6.0) + highline (~> 2.0.0) + declarative (0.0.20) + digest-crc (0.6.5) + rake (>= 12.0.0, < 14.0.0) + domain_name (0.6.20240107) + dotenv (2.8.1) + emoji_regex (3.2.3) + excon (0.111.0) + faraday (1.10.3) + faraday-em_http (~> 1.0) + faraday-em_synchrony (~> 1.0) + faraday-excon (~> 1.1) + faraday-httpclient (~> 1.0) + faraday-multipart (~> 1.0) + faraday-net_http (~> 1.0) + faraday-net_http_persistent (~> 1.0) + faraday-patron (~> 1.0) + faraday-rack (~> 1.0) + faraday-retry (~> 1.0) + ruby2_keywords (>= 0.0.4) + faraday-cookie_jar (0.0.7) + faraday (>= 0.8.0) + http-cookie (~> 1.0.0) + faraday-em_http (1.0.0) + 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-net_http (1.0.2) + faraday-net_http_persistent (1.2.0) + faraday-patron (1.0.0) + faraday-rack (1.0.0) + faraday-retry (1.0.3) + faraday_middleware (1.2.0) + faraday (~> 1.0) + fastimage (2.3.1) + fastlane (2.222.0) + CFPropertyList (>= 2.3, < 4.0.0) + addressable (>= 2.8, < 3.0.0) + artifactory (~> 3.0) + aws-sdk-s3 (~> 1.0) + babosa (>= 1.0.3, < 2.0.0) + bundler (>= 1.12.0, < 3.0.0) + colored (~> 1.2) + commander (~> 4.6) + dotenv (>= 2.1.1, < 3.0.0) + emoji_regex (>= 0.1, < 4.0) + excon (>= 0.71.0, < 1.0.0) + faraday (~> 1.0) + faraday-cookie_jar (~> 0.0.6) + faraday_middleware (~> 1.0) + fastimage (>= 2.1.0, < 3.0.0) + gh_inspector (>= 1.1.2, < 2.0.0) + google-apis-androidpublisher_v3 (~> 0.3) + google-apis-playcustomapp_v1 (~> 0.1) + google-cloud-env (>= 1.6.0, < 2.0.0) + google-cloud-storage (~> 1.31) + highline (~> 2.0) + http-cookie (~> 1.0.5) + json (< 3.0.0) + jwt (>= 2.1.0, < 3) + mini_magick (>= 4.9.4, < 5.0.0) + multipart-post (>= 2.0.0, < 3.0.0) + naturally (~> 2.2) + optparse (>= 0.1.1, < 1.0.0) + plist (>= 3.1.0, < 4.0.0) + rubyzip (>= 2.0.0, < 3.0.0) + security (= 0.1.5) + simctl (~> 1.6.3) + terminal-notifier (>= 2.0.0, < 3.0.0) + terminal-table (~> 3) + tty-screen (>= 0.6.3, < 1.0.0) + 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-travis-formatter (>= 0.0.3, < 2.0.0) + fastlane-plugin-increment_version_code (0.4.3) + gh_inspector (1.1.3) + google-apis-androidpublisher_v3 (0.54.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-core (0.11.3) + addressable (~> 2.5, >= 2.5.1) + googleauth (>= 0.16.2, < 2.a) + httpclient (>= 2.8.1, < 3.a) + mini_mime (~> 1.0) + representable (~> 3.0) + retriable (>= 2.0, < 4.a) + rexml + google-apis-iamcredentials_v1 (0.17.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-playcustomapp_v1 (0.13.0) + google-apis-core (>= 0.11.0, < 2.a) + google-apis-storage_v1 (0.31.0) + google-apis-core (>= 0.11.0, < 2.a) + google-cloud-core (1.7.1) + google-cloud-env (>= 1.0, < 3.a) + google-cloud-errors (~> 1.0) + google-cloud-env (1.6.0) + faraday (>= 0.17.3, < 3.0) + google-cloud-errors (1.4.0) + google-cloud-storage (1.47.0) + addressable (~> 2.8) + digest-crc (~> 0.4) + google-apis-iamcredentials_v1 (~> 0.1) + google-apis-storage_v1 (~> 0.31.0) + google-cloud-core (~> 1.6) + googleauth (>= 0.16.2, < 2.a) + mini_mime (~> 1.0) + googleauth (1.8.1) + faraday (>= 0.17.3, < 3.a) + jwt (>= 1.4, < 3.0) + multi_json (~> 1.11) + os (>= 0.9, < 2.0) + signet (>= 0.16, < 2.a) + highline (2.0.3) + http-cookie (1.0.7) + domain_name (~> 0.5) + httpclient (2.8.3) + jmespath (1.6.2) + json (2.7.2) + jwt (2.8.2) + 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) + naturally (2.2.1) + nkf (0.2.0) + optparse (0.5.0) + os (1.1.4) + plist (3.7.1) + public_suffix (6.0.1) + rake (13.2.1) + representable (3.2.0) + declarative (< 0.1.0) + trailblazer-option (>= 0.1.1, < 0.2.0) + uber (< 0.2.0) + retriable (3.1.2) + rexml (3.3.7) + rouge (2.0.7) + ruby2_keywords (0.0.5) + rubyzip (2.3.2) + security (0.1.5) + signet (0.19.0) + addressable (~> 2.8) + faraday (>= 0.17.5, < 3.a) + jwt (>= 1.5, < 3.0) + multi_json (~> 1.10) + simctl (1.6.10) + CFPropertyList + naturally + terminal-notifier (2.0.0) + terminal-table (3.0.2) + unicode-display_width (>= 1.1.1, < 3) + trailblazer-option (0.1.2) + tty-cursor (0.7.1) + tty-screen (0.8.2) + tty-spinner (0.9.3) + tty-cursor (~> 0.7) + uber (0.1.0) + unicode-display_width (2.5.0) + word_wrap (1.0.0) + xcodeproj (1.25.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) + xcpretty-travis-formatter (1.0.1) + xcpretty (~> 0.2, >= 0.0.7) + +PLATFORMS + x64-mingw-ucrt + +DEPENDENCIES + fastlane + fastlane-plugin-increment_version_code + +BUNDLED WITH + 2.5.18 diff --git a/build.gradle.kts b/build.gradle.kts index 064849ef6..455b4e37b 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -34,4 +34,11 @@ plugins { alias(libs.plugins.compose.compiler) apply false alias(libs.plugins.kotlinMultiplatform) apply false alias(libs.plugins.wire) apply false +} + +tasks.register("versionFile").configure { + group = "publishing" + doLast { + File(projectDir, "version.txt").writeText(project.version.toString()) + } } \ No newline at end of file diff --git a/fastlane/AppFile b/fastlane/AppFile new file mode 100644 index 000000000..d85271893 --- /dev/null +++ b/fastlane/AppFile @@ -0,0 +1,2 @@ +json_key_file("") # Path to the json secret file - Follow https://docs.fastlane.tools/actions/supply/#setup to get one +package_name(ENV["STAGING_PACKAGE_NAME"]) # e.g. org.mifospay.demo \ No newline at end of file diff --git a/fastlane/FastFile b/fastlane/FastFile new file mode 100644 index 000000000..00428123f --- /dev/null +++ b/fastlane/FastFile @@ -0,0 +1,60 @@ +default_platform(:android) + +platform :android do + desc "Deploy internal tracks to Google Play" + lane :deploy_internal do + supply( + track: 'internal', + aab: 'app/build/outputs/bundle/prod/app-prod-release.aab', + skip_upload_metadata: true, + skip_upload_images: true, + skip_upload_screenshots: true, + ) + end + + desc "Promote internal tracks to beta on Google Play" + lane :promote_to_beta do + supply( + track: 'internal', + track_promote_to: 'beta', + skip_upload_changelogs: true, + skip_upload_metadata: true, + skip_upload_images: true, + skip_upload_screenshots: true, + ) + end + + desc "Promote beta tracks to production on Google Play" + lane :promote_to_production do + supply( + track: 'beta', + track_promote_to: 'production', + skip_upload_changelogs: true, + sync_image_upload: true, + ) + end + + desc "Prep Amazon Appstore submission" + lane :prep_amazon do + amazon_app_submission( + client_id: ENV["AMAZON_APPSTORE_CLIENT_ID"], + client_secret: ENV["AMAZON_APPSTORE_CLIENT_SECRET"], + app_id: ENV["AMAZON_APPSTORE_APP_ID"], + apk_path: "app/build/outputs/apk/prod/release/app-prod-release.apk", + upload_apk: true, + changelogs_path: "fastlane/metadata/android/en-US/changelogs/", + upload_changelogs: true, + submit_for_review: false + ) + end + + desc "Submit to Amazon Appstore" + lane :submit_amazon do + amazon_app_submission( + client_id: ENV["AMAZON_APPSTORE_CLIENT_ID"], + client_secret: ENV["AMAZON_APPSTORE_CLIENT_SECRET"], + app_id: ENV["AMAZON_APPSTORE_APP_ID"], + submit_for_review: true + ) + end +end \ No newline at end of file diff --git a/fastlane/PluginFile b/fastlane/PluginFile new file mode 100644 index 000000000..32ea0b1fb --- /dev/null +++ b/fastlane/PluginFile @@ -0,0 +1,5 @@ +# Autogenerated by fastlane +# +# Ensure this file is checked in to source control! + +gem 'fastlane-plugin-increment_version_code' \ No newline at end of file diff --git a/mifospay/build.gradle.kts b/mifospay/build.gradle.kts index ef519cd2b..5ca74ca93 100644 --- a/mifospay/build.gradle.kts +++ b/mifospay/build.gradle.kts @@ -1,3 +1,5 @@ +import org.mifospay.MifosBuildType + /* * Copyright 2024 Mifos Initiative * @@ -7,7 +9,6 @@ * * See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md */ -import org.mifospay.MifosBuildType plugins { alias(libs.plugins.mifospay.android.application) @@ -21,29 +22,39 @@ plugins { android { namespace = "org.mifospay" + defaultConfig { applicationId = "org.mifospay" - versionCode = 1 - versionName = "1.0" + versionName = project.version.toString() + versionCode = System.getenv("VERSION_CODE")?.toIntOrNull() ?: 1 vectorDrawables.useSupportLibrary = true testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } + + signingConfigs { + create("release") { + storeFile = file(System.getenv("KEYSTORE_PATH") ?: "release_keystore.keystore") + storePassword = System.getenv("KEYSTORE_PASSWORD") ?: "" + keyAlias = System.getenv("KEYSTORE_ALIAS") ?: "" + keyPassword = System.getenv("KEYSTORE_ALIAS_PASSWORD") ?: "" + enableV1Signing = true + enableV2Signing = true + } + } + buildTypes { debug { - // applicationIdSuffix = MifosBuildType.DEBUG.applicationIdSuffix + applicationIdSuffix = MifosBuildType.DEBUG.applicationIdSuffix } + release { isMinifyEnabled = true - // applicationIdSuffix = MifosBuildType.RELEASE.applicationIdSuffix - proguardFiles( - getDefaultProguardFile("proguard-android-optimize.txt"), - "proguard-rules.pro" - ) - - // To publish on the Play store a private signing key is required, but to allow anyone - // who clones the code to sign and run the release variant, use the debug signing key. - // TODO: Abstract the signing configuration to a separate file to avoid hardcoding this. - signingConfig = signingConfigs.getByName("debug") + applicationIdSuffix = MifosBuildType.RELEASE.applicationIdSuffix + isShrinkResources = true + isDebuggable = false + isJniDebuggable = false + signingConfig = signingConfigs.getByName("release") + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") } } @@ -57,6 +68,7 @@ android { excludes.add("/META-INF/{AL2.0,LGPL2.1}") } } + testOptions { unitTests { isIncludeAndroidResources = true @@ -146,4 +158,4 @@ dependencyGuard { modules = true tree = true } -} +} \ No newline at end of file diff --git a/mifospay/google-services.json b/mifospay/google-services.json index 585a9d112..9a4001bd2 100644 --- a/mifospay/google-services.json +++ b/mifospay/google-services.json @@ -9,7 +9,7 @@ "client_info": { "mobilesdk_app_id": "1:728434912738:android:49282a75468730891a1dbb", "android_client_info": { - "package_name": "org.mifos.pisp.android" + "package_name": "org.mifospay" } }, "oauth_client": [ @@ -38,7 +38,7 @@ "client_info": { "mobilesdk_app_id": "1:728434912738:android:ef7156e455c6a1a41a1dbb", "android_client_info": { - "package_name": "org.mifos.pisp.android.debug" + "package_name": "org.mifospay.demo.debug" } }, "oauth_client": [ @@ -67,7 +67,7 @@ "client_info": { "mobilesdk_app_id": "1:728434912738:android:0490c291986f0a691a1dbb", "android_client_info": { - "package_name": "org.mifospay" + "package_name": "org.mifospay.debug" } }, "oauth_client": [ diff --git a/mifospay/src/main/res/values/splash.xml b/mifospay/src/main/res/values/splash.xml index c3208953d..9bcf80035 100644 --- a/mifospay/src/main/res/values/splash.xml +++ b/mifospay/src/main/res/values/splash.xml @@ -12,13 +12,14 @@ diff --git a/settings.gradle.kts b/settings.gradle.kts index 3b96a9751..f43a17c79 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -19,6 +19,16 @@ dependencyResolutionManagement { plugins { id("org.gradle.toolchains.foojay-resolver-convention") version("0.8.0") + id("org.ajoberstar.reckon.settings") version("0.18.3") +} + +extensions.configure { + setDefaultInferredScope("patch") + stages("beta", "rc", "final") + setScopeCalc { java.util.Optional.of(org.ajoberstar.reckon.core.Scope.PATCH) } + setScopeCalc(calcScopeFromProp().or(calcScopeFromCommitMessages())) + setStageCalc(calcStageFromProp()) + setTagWriter { it.toString() } } rootProject.name = "mobile-wallet"