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..510626127 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..4460c2e83 100644 --- a/mifospay/build.gradle.kts +++ b/mifospay/build.gradle.kts @@ -9,6 +9,16 @@ */ import org.mifospay.MifosBuildType +/* + * 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-wallet/blob/master/LICENSE.md + */ + plugins { alias(libs.plugins.mifospay.android.application) alias(libs.plugins.mifospay.android.application.compose) @@ -21,29 +31,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") ?: "Mifospay" + keyAlias = System.getenv("KEYSTORE_ALIAS") ?: "key0" + keyPassword = System.getenv("KEYSTORE_ALIAS_PASSWORD") ?: "Mifos@123" + 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 +77,7 @@ android { excludes.add("/META-INF/{AL2.0,LGPL2.1}") } } + testOptions { unitTests { isIncludeAndroidResources = true @@ -146,4 +167,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/prodRelease-badging.txt b/mifospay/prodRelease-badging.txt index 88d68cddf..8cdf267e8 100644 --- a/mifospay/prodRelease-badging.txt +++ b/mifospay/prodRelease-badging.txt @@ -1,4 +1,4 @@ -package: name='org.mifospay' versionCode='1' versionName='1.0' platformBuildVersionName='14' platformBuildVersionCode='34' compileSdkVersion='34' compileSdkVersionCodename='14' +package: name='org.mifospay' versionCode='1' versionName='0.0.1-beta.0.833+20240905T230255Z' platformBuildVersionName='14' platformBuildVersionCode='34' compileSdkVersion='34' compileSdkVersionCodename='14' sdkVersion:'26' targetSdkVersion:'34' uses-permission: name='android.permission.INTERNET' @@ -115,13 +115,11 @@ application-label-zh-CN:'Mifos Pay' application-label-zh-HK:'Mifos Pay' application-label-zh-TW:'Mifos Pay' application-label-zu:'Mifos Pay' -application-icon-120:'res/mipmap/ic_launcher.png' application-icon-160:'res/mipmap/ic_launcher.png' application-icon-240:'res/mipmap/ic_launcher.png' application-icon-320:'res/mipmap/ic_launcher.png' application-icon-480:'res/mipmap/ic_launcher.png' application-icon-640:'res/mipmap/ic_launcher.png' -application-icon-65534:'res/mipmap/ic_launcher.png' application: label='Mifos Pay' icon='res/mipmap/ic_launcher.png' launchable-activity: name='org.mifospay.MainActivity' label='' icon='' property: name='android.adservices.AD_SERVICES_CONFIG' resource='res/xml/ga_ad_services_config.xml' @@ -141,5 +139,5 @@ other-services supports-screens: 'small' 'normal' 'large' 'xlarge' supports-any-density: 'true' locales: '--_--' 'af' 'am' 'ar' 'as' 'az' 'be' 'bg' 'bn' 'bs' 'ca' 'cs' 'da' 'de' 'de-DE' 'el' 'en-AU' 'en-CA' 'en-GB' 'en-IN' 'en-XC' 'eo' 'es' 'es-US' 'et' 'eu' 'fa' 'fi' 'fr' 'fr-CA' 'ga' 'gd' 'gl' 'gu' 'hi' 'hr' 'hu' 'hy' 'in' 'in-ID' 'is' 'it' 'it-IT' 'iw' 'ja' 'jv' 'ka' 'kk' 'km' 'kn' 'ko' 'ku' 'ky' 'lb' 'lo' 'lt' 'lv' 'mk' 'ml' 'mn' 'mr' 'ms' 'my' 'nb' 'ne' 'nl' 'no' 'or' 'pa' 'pl' 'pt' 'pt-BR' 'pt-PT' 'ro' 'ru' 'ru-RU' 'si' 'sk' 'sl' 'so' 'sq' 'sr' 'sr-Latn' 'sv' 'sw' 'ta' 'te' 'th' 'tl' 'tr' 'tr-TR' 'uk' 'ur' 'uz' 'vi' 'zh' 'zh-CN' 'zh-HK' 'zh-TW' 'zu' -densities: '120' '160' '240' '320' '480' '640' '65534' +densities: '160' '240' '320' '480' '640' native-code: 'arm64-v8a' 'armeabi-v7a' 'x86' 'x86_64' diff --git a/mifospay/release_keystore.keystore b/mifospay/release_keystore.keystore new file mode 100644 index 000000000..0ba61aef4 Binary files /dev/null and b/mifospay/release_keystore.keystore differ 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/scripts/pre-commit.sh b/scripts/pre-commit.sh index 9ddd35a29..c49bfe109 100644 --- a/scripts/pre-commit.sh +++ b/scripts/pre-commit.sh @@ -37,16 +37,19 @@ run_spotless_checks() { # Function to run ktlint checks run_dependency_guard() { printf "\nšŸš€ Brace yourself! We're about to generate dependency guard baseline!" - ./gradlew dependencyGuardBaseline + ./gradlew dependencyGuardBaseline > /tmp/dependency-result KT_EXIT_CODE=$? if [ ${KT_EXIT_CODE} -ne 0 ]; then + cat /tmp/dependency-result + rm /tmp/dependency-result printf "\n*********************************************************************************" echo " šŸ’„ Oh no! Something went wrong! šŸ’„" echo " šŸ’” Unable to generate dependency baseline. šŸ› ļø" printf "*********************************************************************************\n" exit ${KT_EXIT_CODE} else + rm /tmp/dependency-result echo "šŸŽ‰ Bravo! Dependency baseline has been generated successfully! Keep rocking that clean code! šŸš€šŸ’«" fi } @@ -74,16 +77,19 @@ run_detekt_checks() { # Function to run Version Catalog checks run_version_catalog_checks() { echo "\nšŸš€ Version catalog linter is now analyzing your catalog for potential issues!" - ./gradlew formatVersionCatalog + ./gradlew formatVersionCatalog > /tmp/catalog-result DETEKT_EXIT_CODE=$? if [ ${DETEKT_EXIT_CODE} -ne 0 ]; then + cat /tmp/catalog-result + rm /tmp/catalog-result echo "\n*********************************************************************************" echo " šŸ’„ Oh no! Version Catalog found issues in the code! Time to fix those issues! šŸ’„" echo " šŸ’” Tip: Review the Version Catalog logs to resolve these issues. šŸ› ļø" echo "*********************************************************************************" exit ${DETEKT_EXIT_CODE} else + rm /tmp/catalog-result echo "šŸŽ‰ Fantastic work! Your Version catalog has been formatted successfully šŸš€šŸŒŸ" fi } diff --git a/scripts/pre-push.sh b/scripts/pre-push.sh index d2c0f6779..cad5ba9a1 100644 --- a/scripts/pre-push.sh +++ b/scripts/pre-push.sh @@ -28,7 +28,9 @@ run_spotless_checks() { echo " šŸ’” Tip: Check the reported issues and fix formatting errors. šŸ› ļø" echo "*********************************************************************************" echo "šŸš€ Attempting to apply Spotless formatting fixes..." - ./gradlew spotlessApply --daemon + ./gradlew spotlessApply --daemon > /tmp/spotless-result + rm /tmp/spotless-result + echo "šŸŽ‰ Stellar job! Your code is pristine and has passed Spotless's formatting checks without a hitch! Keep shining bright! āœØšŸš€" else rm /tmp/spotless-result echo "šŸŽ‰ Stellar job! Your code is pristine and has passed Spotless's formatting checks without a hitch! Keep shining bright! āœØšŸš€" @@ -58,36 +60,46 @@ run_detekt_checks() { # Function to run ktlint checks run_dependency_guard() { printf "\nšŸš€ Brace yourself! We're about to generate dependency guard baseline!" - ./gradlew dependencyGuard + ./gradlew dependencyGuard > /tmp/dependency-result KT_EXIT_CODE=$? if [ ${KT_EXIT_CODE} -ne 0 ]; then + cat /tmp/dependency-result + rm /tmp/dependency-result printf "\n*********************************************************************************" echo " šŸ’„ Oh no! Something went wrong! šŸ’„" echo " šŸ’” Unable to generate dependency baseline. šŸ› ļø" printf "*********************************************************************************\n" echo "šŸš€ Attempting to generate dependency baseline again..." - ./gradlew dependencyGuardBaseline - else + ./gradlew dependencyGuardBaseline > /tmp/dependency-result + rm /tmp/dependency-result echo "šŸŽ‰ Bravo! Dependency baseline has been generated successfully! Keep rocking that clean code! šŸš€šŸ’«" + else + rm /tmp/dependency-result + echo "šŸŽ‰ Bravo! Dependency baseline has been checked successfully! Keep rocking that clean code! šŸš€šŸ’«" fi } # Function to run Version Catalog checks run_version_catalog_checks() { echo "\nšŸš€ Version catalog linter is now analyzing your catalog for potential issues!" - ./gradlew checkVersionCatalog + ./gradlew checkVersionCatalog > /tmp/catalog-result DETEKT_EXIT_CODE=$? if [ ${DETEKT_EXIT_CODE} -ne 0 ]; then + cat /tmp/catalog-result + rm /tmp/catalog-result echo "\n*********************************************************************************" echo " šŸ’„ Oh no! Version Catalog found issues in the code! Time to fix those issues! šŸ’„" echo " šŸ’” Tip: Review the Version Catalog logs to resolve these issues. šŸ› ļø" echo "*********************************************************************************" echo "šŸš€ Attempting to format the Version Catalog again..." - ./gradlew formatVersionCatalog - else + ./gradlew formatVersionCatalog > /tmp/catalog-result + rm /tmp/catalog-result echo "šŸŽ‰ Fantastic work! Your Version catalog has been formatted successfully šŸš€šŸŒŸ" + else + rm /tmp/catalog-result + echo "šŸŽ‰ Fantastic work! Your Version catalog has been formatted properly šŸš€šŸŒŸ" fi } 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"