{"id":24167308,"url":"https://github.com/openMF/mifos-x-actionhub","last_synced_at":"2025-09-20T11:32:34.918Z","repository":{"id":266075024,"uuid":"896620812","full_name":"openMF/mifos-mobile-github-actions","owner":"openMF","description":"GitHub Actions Workflows for Multi-Platform App Development","archived":false,"fork":false,"pushed_at":"2025-01-07T13:53:16.000Z","size":125,"stargazers_count":2,"open_issues_count":2,"forks_count":1,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-01-08T15:39:36.422Z","etag":null,"topics":["actions","ci-cd","github-actions","kmp-sample"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/openMF.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-30T21:13:09.000Z","updated_at":"2025-01-07T13:53:16.000Z","dependencies_parsed_at":"2024-12-17T09:34:23.480Z","dependency_job_id":"9cb84924-66d0-45cb-ba38-3c75a5512fc4","html_url":"https://github.com/openMF/mifos-mobile-github-actions","commit_stats":null,"previous_names":["openmf/mifos-mobile-github-actions"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openMF%2Fmifos-mobile-github-actions","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openMF%2Fmifos-mobile-github-actions/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openMF%2Fmifos-mobile-github-actions/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/openMF%2Fmifos-mobile-github-actions/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/openMF","download_url":"https://codeload.github.com/openMF/mifos-mobile-github-actions/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":233660123,"owners_count":18710026,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["actions","ci-cd","github-actions","kmp-sample"],"created_at":"2025-01-12T21:13:05.344Z","updated_at":"2025-09-20T11:32:34.901Z","avatar_url":"https://github.com/openMF.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\u003ca name=\"readme-top\"\u003e\u003c/a\u003e\n\n# GitHub Actions Workflows for Multi-Platform App Development\n\n![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge\u0026logo=github\u0026logoColor=white)\n![GitHub Actions](https://img.shields.io/badge/github%20actions-%232671E5.svg?style=for-the-badge\u0026logo=githubactions\u0026logoColor=white)\n![Github Pages](https://img.shields.io/badge/github%20pages-121013?style=for-the-badge\u0026logo=github\u0026logoColor=white)\n![Kotlin](https://img.shields.io/badge/kotlin-%237F52FF.svg?style=for-the-badge\u0026logo=kotlin\u0026logoColor=white)\n![Android](https://img.shields.io/badge/Android-3DDC84?style=for-the-badge\u0026logo=android\u0026logoColor=white)\n\n\u0026copy; 2024 [Mifos Initiative](https://github.com/openMF)\n\n\u003c/div\u003e\n\n\n\u003cdetails\u003e\n\u003csummary\u003e\u003ckbd\u003eTable of contents\u003c/kbd\u003e\u003c/summary\u003e\n\n#### TOC\n- [✨ Multi-Platform App Build and Publish Workflow](#multi-platform-app-build-and-publish-workflow)\n  - [Workflow Usage Example](#workflow-usage-example)\n- [✨ Kotlin/JS Web Application GitHub Pages Deployment Workflow](#kotlinjs-web-application-github-pages-deployment-workflow)\n  - [Workflow Configuration](#workflow-configuration)\n- [✨ Monthly Version Tagging Workflow](#monthly-version-tagging-workflow)\n  - [Workflow Configuration](#workflow-configuration-1)\n- [✨ PR Check Workflow](#pr-check-workflow)\n  - [Workflow Usage Example](#workflow-usage-example-1)\n- [✨ Promote Release to Play Store Workflow](#promote-release-to-play-store-workflow)\n  - [Configuration Steps](#configuration-steps)\n\n####\n\u003c/details\u003e\n\n## Kotlin Multiplatform Project Setup Guide\n\n### Supported Platforms\n- Android\n- iOS\n- Desktop (Windows, macOS, Linux)\n- Web (Kotlin/JS, wasmJS)\n\n### Recommended Project Structure\n```\nproject-root/\n│\n├── buildLogic/            # Shared build configuration\n├── gradle/                # Gradle wrapper and configuration\n│\n├── core/                  # Core business logic module\n│   ├── common/            # Common code shared across platforms\n│   ├── model/             # Model classes and data structures\n│   ├── data/              # Data models and repositories\n│   ├── network/           # Networking and API clients\n│   ├── domain/            # Domain-specific logic\n│   ├── ui/                # UI components and screens\n│   ├── designsystem/      # App-wide design system\n│   └── datastore/         # Local data storage\n│\n├── feature/               # Feature Specific module\n│   ├── feature-a/         # Feature-specific logic\n│   ├── feature-b/         # Feature-specific logic\n│   └── feature-c/         # Feature-specific logic\n│\n├── androidApp/            # Android-specific implementation\n├── iosApp/                # iOS-specific implementation\n├── desktopApp/            # Desktop application module\n├── webApp/                # Web application module\n│\n├── shared/                # Shared Kotlin Multiplatform code\n│   ├── src/\n│   │   ├── commonMain/    # Shared business logic\n│   │   ├── androidMain/   # Android-specific code\n│   │   ├── iosMain/       # iOS-specific code\n│   │   ├── desktopMain/   # Desktop-specific code\n│   │   ├── jsMain/        # Web-specific code\n│       └── wasmJsMain/    # Web-specific code\n│\n├── Fastfile              # Fastlane configuration\n├── Gemfile               # Ruby dependencies\n└── fastlane/             # Fastlane configurations\n```\n\n### Development Environment\n- JDK 17 or higher\n- Kotlin 1.9.x\n- Gradle 8.x\n- Android Studio Hedgehog or later\n- Xcode 15+ (for iOS development)\n- Node.js 18+ (for web development)\n\n### Required Github Secrets\n\nIn order to automate the build and deployment process, you need to configure the following secrets in your GitHub repository settings:\n\n| Platform          | Key Name                           | Description                                                                  | Encoding/Format | Required |\n|-------------------|------------------------------------|------------------------------------------------------------------------------|-----------------|----------|\n| Android           | `ORIGINAL_KEYSTORE_FILE`           | Base64 encoded release keystore                                              | Base64          | Yes      |\n| Android           | `ORIGINAL_KEYSTORE_FILE_PASSWORD`  | Keystore password                                                            | String          | Yes      |\n| Android           | `ORIGINAL_KEYSTORE_ALIAS`          | Keystore alias                                                               | String          | Yes      |\n| Android           | `ORIGINAL_KEYSTORE_ALIAS_PASSWORD` | Keystore alias password                                                      | String          | Yes      |\n|                   |                                    |                                                                              |                 |          |\n| Android           | `UPLOAD_KEYSTORE_FILE`             | Base64 encoded release keystore for upload                                   | Base64          | Yes      |\n| Android           | `UPLOAD_KEYSTORE_FILE_PASSWORD`    | Upload keystore password                                                     | String          | Yes      |\n| Android           | `UPLOAD_KEYSTORE_ALIAS`            | Upload keystore alias                                                        | String          | Yes      |\n| Android           | `UPLOAD_KEYSTORE_ALIAS_PASSWORD`   | Upload keystore alias password                                               | String          | Yes      |\n|                   |                                    |                                                                              |                 |          |\n| Google Services   | `GOOGLESERVICES`                   | Google Services JSON content                                                 | Base64          | Yes      |\n| Play Console      | `PLAYSTORECREDS`                   | Play Store service account credentials                                       | Base64          | Yes      |\n| Firebase          | `FIREBASECREDS`                    | Firebase App Distribution credentials                                        | Base64          | Yes      |\n|                   |                                    |                                                                              |                 |          |\n| iOS               | `NOTARIZATION_APPLE_ID`            | Apple ID for app notarization                                                | String          | Yes      |\n| iOS               | `NOTARIZATION_PASSWORD`            | Password for notarization process                                            | String          | Yes      |\n| iOS               | `NOTARIZATION_TEAM_ID`             | Apple Developer Team ID                                                      | String          | Yes      |\n| iOS               | `APPSTORE_KEY_ID`             | App Store Connect API key ID                                                 | String          | Yes      |\n| iOS               | `APPSTORE_ISSUER_ID`             | App Store Connect issuer ID                                                  | String          | Yes      |\n| iOS               | `APPSTORE_AUTH_KEY`             | Base64-encoded App Store Connect API key content                             | String          | Yes      |\n| iOS               | `MATCH_SSH_PRIVATE_KEY`    | Base64-encoded SSH private key for Match repository access                   | String          | Yes      |\n| iOS               | `MATCH_PASSWORD`                   | Password to decrypt the provisioning profiles and certificates used by Match | String          | Yes      |\n|                   |                                    |                                                                              |                 |          |\n| macOS             | `KEYCHAIN_PASSWORD`                   | Password for the temporary signing keychain                                 | String | Yes      |\n| macOS             | `CERTIFICATES_PASSWORD`               | Password used to import signing certificates into the keychain              | String | Yes      |\n| macOS             | `MAC_APP_DISTRIBUTION_CERTIFICATE_B64` | Base64-encoded macOS App Distribution certificate (.p12)                    | String | Yes      |\n| macOS             | `MAC_INSTALLER_DISTRIBUTION_CERTIFICATE_B64` | Base64-encoded macOS Installer Distribution certificate (.p12)       | String | Yes      |\n| macOS             | `MAC_EMBEDDED_PROVISION_B64`          | Base64-encoded embedded provisioning profile (.provisionprofile)            | String | Yes      |\n| macOS             | `MAC_RUNTIME_PROVISION_B64`           | Base64-encoded runtime provisioning profile (.provisionprofile)             | String | Yes      |\n|                   |                                    |                                                                              |                 |          |\n| Desktop (Windows) | `WINDOWS_SIGNING_KEY`              | Signing key for Windows application                                          | String          | No       |\n| Desktop (Windows) | `WINDOWS_SIGNING_PASSWORD`         | Password for Windows signing key                                             | String          | No       |\n| Desktop (Windows) | `WINDOWS_SIGNING_CERTIFICATE`      | Certificate for Windows app signing                                          | String          | No       |\n|                   |                                    |                                                                              |                 |          |\n| Desktop (MacOS)   | `MACOS_SIGNING_KEY`                | Signing key for MacOS application                                            | String          | No       |\n| Desktop (MacOS)   | `MACOS_SIGNING_PASSWORD`           | Password for MacOS signing key                                               | String          | No       |\n| Desktop (MacOS)   | `MACOS_SIGNING_CERTIFICATE`        | Certificate for MacOS app signing                                            | String          | No       |\n|                   |                                    |                                                                              |                 |          |\n| Desktop (Linux)   | `LINUX_SIGNING_KEY`                | Signing key for Linux application                                            | String          | No       |\n| Desktop (Linux)   | `LINUX_SIGNING_PASSWORD`           | Password for Linux signing key                                               | String          | No       |\n| Desktop (Linux)   | `LINUX_SIGNING_CERTIFICATE`        | Certificate for Linux app signing                                            | String          | No       |\n\n\n### Fastlane Setup\n\n#### Install Fastlane\n```bash\n# Install Ruby (if not already installed)\nbrew install ruby\n\n# Install Fastlane\ngem install fastlane\n\n# Create Gemfile\nbundle init\n\n# Add Fastlane to Gemfile\nbundle add fastlane\n```\n\n#### Fastfile Configuration\n`Fastfile`:\n```ruby\ndefault_platform(:android)\n\nplatform :android do\n  desc \"Assemble debug APKs.\"\n  lane :assembleDebugApks do |options|\n    gradle(\n      tasks: [\"assembleDebug\"],\n    )\n  end\n\n  desc \"Assemble Release APK\"\n  lane :assembleReleaseApks do |options|\n    options[:storeFile] ||= \"release_keystore.keystore\"\n    options[:storePassword] ||= \"Mifospay\"\n    options[:keyAlias] ||= \"key0\"\n    options[:keyPassword] ||= \"Mifos@123\"\n\n    # Generate version\n    generateVersion = generateVersion()\n\n    buildAndSignApp(\n      taskName: \"assemble\",\n      buildType: \"Release\",\n      storeFile: options[:storeFile],\n      storePassword: options[:storePassword],\n      keyAlias: options[:keyAlias],\n      keyPassword: options[:keyPassword],\n    )\n  end\n\n  desc \"Bundle Play Store release\"\n  lane :bundlePlayStoreRelease do |options|\n    options[:storeFile] ||= \"release_keystore.keystore\"\n    options[:storePassword] ||= \"Mifospay\"\n    options[:keyAlias] ||= \"key0\"\n    options[:keyPassword] ||= \"Mifos@123\"\n\n    # Generate version\n    generateVersion = generateVersion()\n\n    # Generate Release Note\n    releaseNotes = generateReleaseNotes(\n      repoName: \"mobile-wallet-testing\",\n    )\n\n    # Write the generated release notes to default.txt\n    buildConfigPath = \"metadata/android/en-GB/changelogs/default.txt\"\n    File.write(buildConfigPath, releaseNotes)\n\n    buildAndSignApp(\n      taskName: \"bundle\",\n      buildType: \"Release\",\n      storeFile: options[:storeFile],\n      storePassword: options[:storePassword],\n      keyAlias: options[:keyAlias],\n      keyPassword: options[:keyPassword],\n    )\n  end\n\n  desc \"Publish Release Play Store artifacts to Firebase App Distribution\"\n  lane :deploy_on_firebase do |options|\n    options[:apkFile] ||= \"mifospay-android/build/outputs/apk/prod/release/mifospay-android-prod-release.apk\"\n    options[:serviceCredsFile] ||= \"secrets/firebaseAppDistributionServiceCredentialsFile.json\"\n    options[:groups] ||= \"mifos-wallet-testers\"\n\n    # Generate Release Note\n    releaseNotes = generateReleaseNotes(\n      repoName: \"mobile-wallet-testing\",\n    )\n\n    firebase_app_distribution(\n      app: \"1:64530857057:android:f8d67b786db1b844\",\n      android_artifact_type: \"APK\",\n      android_artifact_path: options[:apkFile],\n      service_credentials_file: options[:serviceCredsFile],\n      groups: options[:groups],\n      release_notes: \"#{releaseNotes}\",\n    )\n  end\n\n  desc \"Deploy internal tracks to Google Play\"\n  lane :deploy_internal do |options|\n    options[:aabFile] ||= \"mifospay-android/build/outputs/bundle/prodRelease/mifospay-android-prod-release.aab\"\n    upload_to_play_store(\n      track: 'internal',\n      aab: options[:aabFile],\n      skip_upload_metadata: true,\n      skip_upload_images: true,\n      skip_upload_screenshots: true,\n    )\n  end\n\n  desc \"Promote internal tracks to beta on Google Play\"\n  lane :promote_to_beta do\n    upload_to_play_store(\n      track: 'internal',\n      track_promote_to: 'beta',\n      skip_upload_changelogs: true,\n      skip_upload_metadata: true,\n      skip_upload_images: true,\n      skip_upload_screenshots: true,\n    )\n  end\n\n  desc \"Promote beta tracks to production on Google Play\"\n  lane :promote_to_production do\n    upload_to_play_store(\n      track: 'beta',\n      track_promote_to: 'production',\n      skip_upload_changelogs: true,\n      skip_upload_metadata: true,\n      skip_upload_images: true,\n      skip_upload_screenshots: true,\n    )\n  end\n\n  desc \"Generate artifacts for the given [build] signed with the provided [keystore] and credentials.\"\n  private_lane :buildAndSignApp do |options|\n    # Get the project root directory\n    project_dir = File.expand_path('..', Dir.pwd)\n\n    # Construct the absolute path to the keystore\n    keystore_path = File.join(project_dir, 'keystores', options[:storeFile])\n\n    # Check if keystore exists\n    unless File.exist?(keystore_path)\n      UI.error \"Keystore file not found at: #{keystore_path}\"\n      UI.error \"Please ensure the keystore file exists at the correct location\"\n      exit 1  # Exit with error code 1\n    end\n\n    gradle(\n      task: options[:taskName],\n      build_type: options[:buildType],\n      properties: {\n        \"android.injected.signing.store.file\" =\u003e keystore_path,\n        \"android.injected.signing.store.password\" =\u003e options[:storePassword],\n        \"android.injected.signing.key.alias\" =\u003e options[:keyAlias],\n        \"android.injected.signing.key.password\" =\u003e options[:keyPassword],\n      },\n      print_command: false,\n    )\n  end\n\n  desc \"Generate Version\"\n  lane :generateVersion do\n    # Generate version file\n    gradle(tasks: [\"versionFile\"])\n\n    # Set version from file\n    ENV['VERSION'] = File.read(\"../version.txt\").strip\n\n    # Calculate and set version code\n    commit_count = `git rev-list --count HEAD`.to_i\n    tag_count = `git tag | grep -v beta | wc -l`.to_i\n    ENV['VERSION_CODE'] = ((commit_count + tag_count) \u003c\u003c 1).to_s\n\n    UI.success(\"Set VERSION=#{ENV['VERSION']} VERSION_CODE=#{ENV['VERSION_CODE']}\")\n  end\n\n  desc \"Generate release notes\"\n  lane :generateReleaseNotes do |options|\n    branchName = `git rev-parse --abbrev-ref HEAD`.chomp()\n    releaseNotes = changelog_from_git_commits(\n      commits_count: 1,\n    )\n    releaseNotes\n  end\n\nend\n\nplatform :ios do\n\n  #############################\n  # Shared Private Lane Helpers\n  #############################\n\n  private_lane :setup_ci_if_needed do\n      unless ENV['CI']\n          UI.message(\"🖥️ Running locally, skipping CI-specific setup.\")\n      else\n          setup_ci\n      end\n  end\n\n  private_lane :load_api_key do |options|\n      app_store_connect_api_key(\n        key_id: options[:appstore_key_id] || \"HA469T6757\",\n        issuer_id: options[:appstore_issuer_id] || \"8er9e361-9603-4c3e-b147-be3b1o816099\",\n        key_filepath: options[:key_filepath] || \"./secrets/Auth_Key.p8\",\n        duration: 1200\n      )\n  end\n\n  private_lane :fetch_certificates_with_match do |options|\n      match(\n        type: options[:match_type] || \"adhoc\",\n        app_identifier: options[:app_identifier] || \"com.example.9af3c1d2\",\n        readonly: true,\n        git_url: options[:git_url] || \"git@github.com:openMF/ios-provisioning-profile.git\",\n        git_branch: options[:git_branch] || \"master\",\n        git_private_key: options[:git_private_key] || \"./secrets/match_ci_key\",\n        force_for_new_devices: true,\n        api_key: Actions.lane_context[SharedValues::APP_STORE_CONNECT_API_KEY]\n      )\n  end\n\n  private_lane :build_ios_project do |options|\n      app_identifier = options[:app_identifier] || \"com.example.9af3c1d2\"\n      provisioning_profile_name = options[:provisioning_profile_name] || \"match AdHoc com.example.9af3c1d2\"\n\n      cocoapods(\n        podfile: \"cmp-ios/Podfile\",\n        clean_install: true,\n        repo_update: true\n      )\n      \n      update_code_signing_settings(\n        use_automatic_signing: false,\n        path: \"cmp-ios/iosApp.xcodeproj\",\n        targets: \"iosApp\",\n        team_id: \"G432R4FZP6\",\n        code_sign_identity: \"Apple Distribution\",\n        profile_name: provisioning_profile_name,\n        bundle_identifier: \"com.example.9af3c1d2\"\n      )\n      \n      build_ios_app(\n        scheme: \"iosApp\",\n        workspace: cmp-ios/iosApp.xcworkspace,\n        output_name: \"iosApp.ipa\",\n        output_directory: \"cmp-ios/build\",\n        skip_codesigning: \"Release\"\n      )\n  end\n\n  ###################\n  # Main Public lanes\n  ###################\n\n  desc \"Build Ios application\"\n  lane :build_ios do |options|\n    options[:scheme] ||= \"iosApp\"\n    options[:project_path] ||= \"cmp-ios/iosApp.xcodeproj\"\n    options[:output_name] ||= \"iosApp.ipa\"\n    options[:output_directory] ||= \"cmp-ios/build\"\n\n    cocoapods(\n      podfile: \"cmp-ios/Podfile\",\n      clean_install: true,\n      repo_update: true\n    )\n      \n    build_ios_app(\n      scheme: options[:scheme],\n      project: options[:project_path],\n      output_name: options[:output_name],\n      output_directory: options[:output_directory],\n      skip_codesigning: true,\n      skip_archive: true\n    )\n  end\n\n  desc \"Build Signed Ios application\"\n  lane :build_signed_ios do |options|\n    setup_ci_if_needed\n    load_api_key(options)\n    fetch_certificates_with_match(options)\n    build_ios_project(options)\n  end\n\n  desc \"Increment build number from latest Firebase release\"\n  lane :increment_version do |options|\n  service_file = options[:serviceCredsFile] || \"./secrets/firebaseAppDistributionServiceCredentialsFile.json\"\n\n    latest_release = firebase_app_distribution_get_latest_release(\n      app: options[:firebase_app_id] || \"1:728434912738:ios:1d81f8e53ca7a6f31a1dbb\",\n      service_credentials_file: service_file\n    )\n\n    if latest_release\n      increment_build_number(\n        xcodeproj: \"cmp-ios/iosApp.xcodeproj\",\n        build_number: latest_release[:buildVersion].to_i + 1\n      )\n    else\n      UI.important(\"⚠️ No existing Firebase release found. Skipping build number increment.\")\n    end\n  end\n\n  desc \"Generate release notes\"\n  lane :generateReleaseNote do\n    branchName = `git rev-parse --abbrev-ref HEAD`.chomp()\n    releaseNotes = changelog_from_git_commits(\n      commits_count: 1,\n    )\n    releaseNotes\n  end\n\n  desc \"Upload iOS application to Firebase App Distribution\"\n  lane :deploy_on_firebase do |options|\n  service_file = options[:serviceCredsFile] || \"./secrets/firebaseAppDistributionServiceCredentialsFile.json\"\n  groups = options[:groups] || \"mifos-mobile-testers\"\n  firebase_app_id = options[:firebase_app_id] ||= \"1:728434912738:ios:1d81f8e53ca7a6f31a1dbb\"\n\n    increment_version(serviceCredsFile: service_file)\n\n    build_signed_ios(\n        options.merge(\n            match_type: \"adhoc\",\n            provisioning_profile_name: \"match AdHoc com.example.9af3c1d2\"\n        )\n    )\n\n    releaseNotes = generateReleaseNote()\n\n    firebase_app_distribution(\n      app: firebase_app_id,\n      service_credentials_file: service_file,,\n      release_notes: releaseNotes,\n      groups: groups\n    )\n  end\n\n  desc \"Upload beta build to TestFlight\"\n  lane :beta do |options|\n\n      setup_ci_if_needed\n      load_api_key(options)\n      fetch_certificates_with_match(\n        options.merge(match_type: \"appstore\")\n      )\n\n      increment_version_number(\n        xcodeproj: \"cmp-ios/iosApp.xcodeproj\",\n        version_number: \"1.0.0\"\n      )\n\n      latest_build_number = latest_testflight_build_number(\n        app_identifier: options[:app_identifier] || \"com.example.9af3c1d2\",\n        api_key: Actions.lane_context[SharedValues::APP_STORE_CONNECT_API_KEY]\n      )\n\n      increment_build_number(\n        xcodeproj: \"cmp-ios/iosApp.xcodeproj\",\n        build_number: latest_build_number + 1\n      )\n\n      build_ios_project(\n        options.merge(\n            provisioning_profile_name: \"match AppStore com.example.9af3c1d2\"\n        )\n      )\n\n      pilot(\n        api_key: Actions.lane_context[SharedValues::APP_STORE_CONNECT_API_KEY],\n        skip_waiting_for_build_processing: true\n      )\n  end\n  \n  desc \"Upload iOS Application to AppStore\"\n  lane :release do |options|\n\n      setup_ci_if_needed\n      load_api_key(options)\n      fetch_certificates_with_match(\n        options.merge(match_type: \"appstore\")\n      )\n\n      increment_version_number(\n        xcodeproj: \"cmp-ios/iosApp.xcodeproj\",\n        version_number: \"1.0.0\"\n      )\n\n      latest_build_number = latest_testflight_build_number(\n        app_identifier: options[:app_identifier] || \"com.example.9af3c1d2\",\n        api_key: Actions.lane_context[SharedValues::APP_STORE_CONNECT_API_KEY]\n      )\n\n      increment_build_number(\n        xcodeproj: \"cmp-ios/iosApp.xcodeproj\",\n        build_number: latest_build_number + 1\n      )\n      \n      update_plist(\n        plist_path: \"cmp-ios/iosApp/Info.plist\",\n        block: proc do |plist|\n          plist['NSContactsUsageDescription'] = 'This app requires access to your contacts to enable autofill and collaboration features.'\n          plist['NSLocationWhenInUseUsageDescription'] = 'This app does not use your location to suggest services near you.'\n          plist['NSBluetoothAlwaysUsageDescription'] = 'This app does not use Bluetooth to communicate with nearby devices.'\n        end\n      )\n\n      build_ios_project(\n        options.merge(\n            provisioning_profile_name: \"match AppStore com.example.9af3c1d2\"\n        )\n      )\n      \n      deliver(\n        screenshots_path: \"./fastlane/screenshots_ios\",\n        metadata_path: options[:metadata_path] || \"./fastlane/metadata\",\n        submit_for_review: true,\n        automatic_release: true,\n        api_key: Actions.lane_context[SharedValues::APP_STORE_CONNECT_API_KEY],\n        skip_app_version_update: true,\n        force: true,\n        precheck_include_in_app_purchases: false,\n        overwrite_screenshots: true,\n        app_rating_config_path: options[:app_rating_config_path] || \"./fastlane/age_rating.json\",\n        submission_information: {\n          add_id_info_uses_idfa: false,\n          add_id_info_limits_tracking: false,\n          add_id_info_serves_ads: false,\n          add_id_info_tracks_action: false,\n          add_id_info_tracks_install: false,\n          content_rights_has_rights: true,\n          content_rights_contains_third_party_content: false,\n          export_compliance_platform: 'ios',\n          export_compliance_compliance_required: false,\n          export_compliance_encryption_updated: false,\n          export_compliance_app_type: nil,\n          export_compliance_uses_encryption: false,\n          export_compliance_is_exempt: true,\n          export_compliance_contains_third_party_cryptography: false,\n          export_compliance_contains_proprietary_cryptography: false,\n          export_compliance_available_on_french_store: true\n        }\n      )\n  end\nend\n```\n\n### Code Quality Checks\n- Static code analysis (Detekt)\n- Code formatting (Spotless)\n- Dependency guard\n- Unit and UI testing\n\n### Release Management\n- Semantic versioning\n- Automated beta deployments\n- Cross-platform release automation\n\n### Resources\n- [Kotlin Multiplatform Documentation](https://kotlinlang.org/docs/multiplatform.html)\n- [Compose Multiplatform Guide](https://www.jetbrains.com/lp/compose-multiplatform/)\n- [Fastlane Documentation](https://docs.fastlane.tools/)\n\n\u003cdiv align=\"right\"\u003e\n\n[![Back To Top](https://img.shields.io/badge/Back%20To%20Top-Blue?style=flat)](#readme-top)\n\n\u003c/div\u003e\n\n---\n\n# Multi-Platform App Build and Publish Workflow\n\n\u003e \\[!TIP]\n\u003e  ####  _[multi_platform_build_and_publish.yaml](.github/workflows/multi-platform-build-and-publish.yaml)_ 👀️\n\n```mermaid\nflowchart TB\n    %% Main workflow trigger\n    Start[/\"Workflow Trigger\"/]\n    \n    %% Android section\n    subgraph Android[\"Android Pipeline\"]\n        direction TB\n        A_Build[\"Build Android App\"]\n        A_Build --\u003e A_Firebase[\"Deploy to Firebase\"]\n        A_Build --\u003e A_Check{\"Publish to\\nPlay Store?\"}\n        A_Check --\u003e|Yes| A_Play[\"Publish to Play Store\"]\n        A_Check --\u003e|No| A_Skip[\"Skip Play Store\"]\n    end\n    \n    %% iOS section\n    subgraph iOS[\"iOS Pipeline\"]\n        direction TB\n        I_Build[\"Build iOS App\"]\n        I_Build --\u003e I_Firebase[\"Deploy to Firebase\"]\n        I_Build --\u003e I_Check{\"Publish to\\nApp Store?\"}\n        I_Check --\u003e|Yes| I_Store[\"Publish to App Store\"]\n        I_Check --\u003e|No| I_Skip[\"Skip App Store\"]\n    end\n    \n    %% Desktop section\n    subgraph Desktop[\"Desktop Pipeline\"]\n        direction TB\n        D_Build[\"Initialize Desktop Build\"]\n        D_Build --\u003e D_Win[\"Windows Build\"]\n        D_Build --\u003e D_Mac[\"macOS Build\"]\n        D_Build --\u003e D_Linux[\"Linux Build\"]\n    end\n    \n    %% Web section\n    subgraph Web[\"Web Pipeline\"]\n        direction TB\n        W_Build[\"Build Web App\"]\n        W_Build --\u003e W_Deploy[\"Deploy to GitHub Pages\"]\n    end\n    \n    %% GitHub Release section\n    subgraph Release[\"Release Pipeline\"]\n        direction TB\n        R_Version[\"Generate Version\"]\n        R_Notes[\"Generate Release Notes\"]\n        R_Artifacts[\"Collect Artifacts\"]\n        R_Create[\"Create GitHub Release\"]\n        \n        R_Version --\u003e R_Notes\n        R_Notes --\u003e R_Artifacts\n        R_Artifacts --\u003e R_Create\n    end\n    \n    %% Main workflow connections\n    Start --\u003e Android\n    Start --\u003e iOS\n    Start --\u003e Desktop\n    Start --\u003e Web\n    \n    Android --\u003e Release\n    iOS --\u003e Release\n    Desktop --\u003e Release\n    Web --\u003e Release\n    \n    %% Styling\n    classDef trigger fill:#2C3E50,color:#fff,stroke:#2C3E50\n    classDef pipeline fill:#34495E,color:#fff,stroke:#2C3E50\n    classDef process fill:#ECF0F1,stroke:#34495E,color:#2C3E50\n    classDef conditional fill:#E74C3C,stroke:#C0392B,color:#fff\n    classDef deployment fill:#27AE60,stroke:#229954,color:#fff\n    classDef release fill:#3498DB,stroke:#2980B9,color:#fff\n    \n    class Start trigger\n    class Android,iOS,Desktop,Web pipeline\n    class A_Build,I_Build,D_Build,W_Build process\n    class A_Check,I_Check conditional\n    class A_Firebase,I_Firebase,A_Play,I_Store,W_Deploy deployment\n    class R_Version,R_Notes,R_Artifacts,R_Create release\n    class D_Win,D_Mac,D_Linux process\n    class A_Skip,I_Skip process\n```\n\n## Overview\n\nThis GitHub Actions workflow provides a comprehensive solution for building and publishing multi-platform applications, supporting:\n\n- Android (APK and Play Store)\n- iOS (App Store and Firebase Distribution)\n- Desktop (Windows, macOS, Linux)\n- Web (GitHub Pages)\n\n## Prerequisites\n\n### Repository Setup\n\n1. Ensure your project is organized with separate modules for each platform:\n\n- Android module\n- iOS module\n- Desktop module\n- Web module\n\n2. Required configuration files:\n\n- `fastlane/` directory with deployment configurations\n- Gradle build files\n- GitHub Secrets configuration\n\n### Required GitHub Secrets\n\nConfigure the following secrets in your repository settings:\n\n#### Android Secrets\n\n- `ORIGINAL_KEYSTORE_FILE`: Base64 encoded release keystore\n- `ORIGINAL_KEYSTORE_FILE_PASSWORD`: Keystore password\n- `ORIGINAL_KEYSTORE_ALIAS`: Keystore alias\n- `ORIGINAL_KEYSTORE_ALIAS_PASSWORD`: Keystore alias password\n-\n- `UPLOAD_KEYSTORE_FILE`: Base64 encoded release keystore\n- `UPLOAD_KEYSTORE_FILE_PASSWORD`: Keystore password\n- `UPLOAD_KEYSTORE_ALIAS`: Keystore alias\n- `UPLOAD_KEYSTORE_ALIAS_PASSWORD`: Keystore alias password\n-\n- `GOOGLESERVICES`: Base64 encoded Google Services JSON content\n- `PLAYSTORECREDS`: Base64 encoded Play Store service account credentials\n- `FIREBASECREDS`: Base64 encoded Firebase App Distribution credentials\n\n#### iOS Secrets\n\n- Notarization Credentials:\n  - `NOTARIZATION_APPLE_ID`\n  - `NOTARIZATION_PASSWORD`\n  - `NOTARIZATION_TEAM_ID`\n- Fastlane Match Credentials:\n  - `MATCH_SSH_PRIVATE_KEY`\n  - `MATCH_PASSWORD`\n- App Store Connect API Credentials:\n  - `APPSTORE_KEY_ID`\n  - `APPSTORE_ISSUER_ID`\n  - `APPSTORE_AUTH_KEY`\n\n#### macOS Secrets\n\n- Keychain \u0026 Certificates:\n  - `KEYCHAIN_PASSWORD`: Password for temporary signing keychain\n  - `CERTIFICATES_PASSWORD`: Password used to import certificates into keychain\n\n- macOS Signing Certificates (Base64 encoded):\n  - `MAC_APP_DISTRIBUTION_CERTIFICATE_B64`: App Distribution certificate (.p12)\n  - `MAC_INSTALLER_DISTRIBUTION_CERTIFICATE_B64`: Installer Distribution certificate (.p12)\n\n- Provisioning Profiles (Base64 encoded):\n  - `MAC_EMBEDDED_PROVISION_B64`: Embedded provisioning profile (.provisionprofile)\n  - `MAC_RUNTIME_PROVISION_B64`: Runtime provisioning profile (.provisionprofile)\n\n- App Store Connect API (reused from iOS):\n  - `APPSTORE_KEY_ID`\n  - `APPSTORE_ISSUER_ID`\n  - `APPSTORE_AUTH_KEY`\n\n## Workflow Inputs\n\nThe workflow supports the following configuration inputs:\n\n### Release Configuration\n\n- `release_type`:\n  - Default: `'internal'`\n  - Options: `'internal'`, `'beta'`\n- `target_branch`:\n  - Default: `'dev'`\n  - Specifies the branch for release\n\n### Platform Package Names\n\n- `android_package_name`: Name of Android project module\n- `ios_package_name`: Name of iOS project module\n- `desktop_package_name`: Name of Desktop project module\n- `web_package_name`: Name of Web project module\n\n### Publishing Toggles\n\n- `distribute_ios_firebase`: Distribute iOS App via Firebase App Distribution (Default: `false`)\n- `distribute_ios_testflight`: Distribute iOS App via TestFlight (Default: `false`)\n- `distribute_ios_appstore`: Distribute iOS App to Appstore (Default: `false`)\n- `distribute_macos_testflight`: Distribute macOS App via TestFlight (Default: `false`)\n- `distribute_macos_appstore`: Distribute macOS App to Appstore (Default: `false`)\n- `distribute_desktop_external`: Distribute Desktop App builds outside official stores (Default: `true`)\n\n### Signing \u0026 Certificates\n\n- `app_identifier`: The unique bundle identifier for the iOS and macOS application\n- `git_url`: Git URL for certificates \u0026 provisioning profiles (Fastlane Match)\n- `git_branch`: Branch inside certificates repo for Match\n- `match_type`: Type of provisioning profile (adhoc, appstore, development)\n- `provisioning_profile_name`: Provisioning profile name to use for code signing\n- `metadata_path`: Path to metadata directory (app name, description, screenshots, etc.) for App Store submission\n\n### Firebase\n\n- `firebase_app_id`: Firebase App ID for iOS distribution\n- `tester_groups`: Firebase tester groups for internal/beta distribution\n\n### Build System\n\n- `use_cocoapods`: Whether to integrate Kotlin Multiplatform with CocoaPods (true/false)\n- `shared_module`: Gradle path to the KMP shared module (e.g., `:cmp-shared`)\n- `ci_gradle_properties_path`: Path to CI-specific Gradle properties (default: `.github/ci-gradle.properties`)\n- `compose_resources_dir`: Path to Compose resources directory (default: `cmp-shared/build/compose/cocoapods/compose-resources`)\n- `java-version`: Java version to use (default: `17`)\n- `xcode-version`: Xcode version to use (default: `16.4`)\n- `cmp_desktop_dir`: Path to the KMP desktop project used for macOS builds (default: `cmp-desktop`)\n- `keychain_name`: Temporary keychain name used for macOS signing (default: `signing.keychain-db`)\n\n## Workflow Jobs\n\n### 1. Release Information Generation\n\n- Generates version number\n- Creates release notes\n- Prepares changelog artifacts\n\n### 2. Platform-Specific Build Jobs\n\n#### Android\n\n- Builds signed APK\n- Uploads to Firebase App Distribution\n- Optionally publishes to Play Store\n\n#### iOS\n\n- Builds iOS application\n- Uploads to Firebase App Distribution\n- Prepares for App Store submission\n\n#### macOS\n\n- Builds macOS application\n- Optionally distributes to TestFlight\n- Optionally publishes to App Store\n\n#### Desktop\n\n- Builds for Windows, macOS, and Linux\n- Packages executables and installers\n\n#### Web\n\n- Builds web application\n- Deploys to GitHub Pages\n\n### 3. GitHub Release\n\n- Creates a pre-release with all built artifacts\n- Includes detailed changelog\n\n## Workflow Usage Example\n\n```yaml\nname: Multi-Platform Build and Publish\n\non:\n  workflow_dispatch:\n    inputs:\n      release_type:\n        type: choice\n        options:\n          - internal\n          - beta\n        default: internal\n        description: Release Type\n\n      target_branch:\n        type: string\n        default: 'dev'\n        description: 'Target branch for release'\n\n      publish_android:\n        type: boolean\n        default: false\n        description: Publish Android App On Play Store\n\n      distribute_ios_firebase:\n        type: boolean\n        default: false\n        description: Distribute iOS App via Firebase App Distribution\n        \n      distribute_ios_testflight:\n        type: boolean\n        default: false\n        description: Distribute iOS App via TestFlight (App Store Connect)\n\n      distribute_ios_appstore:\n        type: boolean\n        default: false\n        description: Distribute iOS App to Appstore  \n\npermissions:\n  contents: write\n  id-token: write\n  pages: write\n\nconcurrency:\n  group: \"reusable\"\n  cancel-in-progress: false\n\njobs:\n  multi_platform_build_and_publish:\n    name: Multi-Platform Build and Publish\n    uses: openMF/mifos-x-actionhub/.github/workflows/multi-platform-build-and-publish.yaml@v1.0.6\n    with:\n      java-version: 21\n      xcode-version: '16.4'\n      release_type: ${{ inputs.release_type }}\n      target_branch: ${{ inputs.target_branch }}\n      android_package_name: 'cmp-android' # \u003c-- Change this to your android package name\n      ios_package_name: 'cmp-ios' # \u003c-- Change this to your ios package name\n      desktop_package_name: 'cmp-desktop' # \u003c-- Change this to your desktop package name\n      web_package_name: 'cmp-web'   # \u003c-- Change this to your web package name\n      app_identifier: 'org.mifos.kmp.template'\n      git_url: 'git@github.com:openMF/ios-provisioning-profile.git'\n      git_branch: 'master'\n      match_type: 'adhoc'\n      provisioning_profile_name: 'match AdHoc org.mifos.kmp.template'\n      firebase_app_id: '1:728434912738:ios:1d81f8e53ca7a6f31a1dbb'\n      metadata_path: './fastlane/metadata'\n      use_cocoapods: true\n      shared_module: ':cmp-shared'\n      publish_android: ${{ inputs.publish_android }}\n      distribute_ios_firebase: ${{ inputs.distribute_ios_firebase }}\n      distribute_ios_testflight: ${{ inputs.distribute_ios_testflight }}\n      tester_groups: 'mifos-wallet-testers'\n    secrets:\n      original_keystore_file: ${{ secrets.ORIGINAL_KEYSTORE_FILE }}\n      original_keystore_file_password: ${{ secrets.ORIGINAL_KEYSTORE_FILE_PASSWORD }}\n      original_keystore_alias: ${{ secrets.ORIGINAL_KEYSTORE_ALIAS }}\n      original_keystore_alias_password: ${{ secrets.ORIGINAL_KEYSTORE_ALIAS_PASSWORD }}\n\n      upload_keystore_file: ${{ secrets.UPLOAD_KEYSTORE_FILE }}\n      upload_keystore_file_password: ${{ secrets.UPLOAD_KEYSTORE_FILE_PASSWORD }}\n      upload_keystore_alias: ${{ secrets.UPLOAD_KEYSTORE_ALIAS }}\n      upload_keystore_alias_password: ${{ secrets.UPLOAD_KEYSTORE_ALIAS_PASSWORD }}\n\n      notarization_apple_id: ${{ secrets.NOTARIZATION_APPLE_ID }}\n      notarization_password: ${{ secrets.NOTARIZATION_PASSWORD }}\n      notarization_team_id: ${{ secrets.NOTARIZATION_TEAM_ID }}\n      appstore_key_id: ${{ secrets.APPSTORE_KEY_ID }}\n      appstore_issuer_id: ${{ secrets.APPSTORE_ISSUER_ID }}\n      appstore_auth_key: ${{ secrets.APPSTORE_AUTH_KEY }}\n      match_password: ${{ secrets.MATCH_PASSWORD }}\n      match_ssh_private_key: ${{ secrets.MATCH_SSH_PRIVATE_KEY }}\n\n      windows_signing_key: ${{ secrets.WINDOWS_SIGNING_KEY }}\n      windows_signing_password: ${{ secrets.WINDOWS_SIGNING_PASSWORD }}\n      windows_signing_certificate: ${{ secrets.WINDOWS_SIGNING_CERTIFICATE }}\n\n      macos_signing_key: ${{ secrets.MACOS_SIGNING_KEY }}\n      macos_signing_password: ${{ secrets.MACOS_SIGNING_PASSWORD }}\n      macos_signing_certificate: ${{ secrets.MACOS_SIGNING_CERTIFICATE }}\n\n      linux_signing_key: ${{ secrets.LINUX_SIGNING_KEY }}\n      linux_signing_password: ${{ secrets.LINUX_SIGNING_PASSWORD }}\n      linux_signing_certificate: ${{ secrets.LINUX_SIGNING_CERTIFICATE }}\n\n      google_services: ${{ secrets.GOOGLESERVICES }}\n      firebase_creds: ${{ secrets.FIREBASECREDS }}\n      playstore_creds: ${{ secrets.PLAYSTORECREDS }}\n      token: ${{ secrets.GITHUB_TOKEN }}\n```\n\n## Important Considerations\n\n1. Ensure all platform-specific build configurations are correctly set up\n2. Test the workflow in a staging environment first\n3. Manage secrets securely\n4. Keep Fastlane and Gradle configurations up to date\n\n## Troubleshooting\n\n- Check GitHub Actions logs for detailed error messages\n- Verify all secrets are correctly configured\n- Ensure Gradle and Fastlane dependencies are compatible\n- Validate platform-specific build scripts\n\n## Limitations\n\n- Requires comprehensive platform-specific build configurations\n- Some manual setup needed for each platform\n- Depends on external services (Play Store, App Store, Firebase)\n\n\u003cdiv align=\"right\"\u003e\n\n[![Back To Top](https://img.shields.io/badge/Back%20To%20Top-Blue?style=flat)](#readme-top)\n\n\u003c/div\u003e\n\n---\n\n# Kotlin/JS Web Application GitHub Pages Deployment Workflow\n\n\u003e \\[!TIP]\n\u003e #### [_build-and-deploy-site.yaml_](.github/workflows/build-and-deploy-site.yaml)\n\n```mermaid\n---\nconfig:\n  theme: neo-dark\n  look: neo\n  layout: dagre\n---\nflowchart TD\n%% Trigger Stage\n    A([fa:fa-code-branch Push to Dev / Manual Trigger]) --\u003e \n    B{{\"fa:fa-server Checkout Repository\"}}\n\n%% Environment Setup\nB --\u003e C[\"fa:fa-coffee Setup Java Environment\\n🔧 JDK Configuration\"]\n\n%% Build Process\nC --\u003e D[\"fa:fa-globe Build Kotlin/JS Web App\\n🏗️ Compiling JavaScript\"]\n\n%% GitHub Pages Configuration\nD --\u003e E{\"fa:fa-cogs Configure GitHub Pages\\n⚙️ Static Site Generation\"}\n\n%% Artifact Upload\nE --\u003e F[\"fa:fa-upload Upload Static Web Files\\n📦 Preparing Deployment Artifacts\"]\n\n%% Deployment Stage\nF --\u003e G{{\"fa:fa-rocket Deploy to GitHub Pages\"}}\n\n%% Deployment Outcomes\nG --\u003e|Success| H[\"fa:fa-check-circle Update Deployment Environment\\n✨ Environment Sync\"]\nG --\u003e|Failure| I[\"fa:fa-undo Rollback Deployment\\n🔙 Reverting Changes\"]\n\n%% Styling\nclassDef triggerNode fill:#2196F3,color:white,stroke:#1565C0,stroke-width:2px;\nclassDef processNode fill:#4CAF50,color:white,stroke:#2E7D32,stroke-width:2px;\nclassDef decisionNode fill:#FF9800,color:white,stroke:#EF6C00,stroke-width:2px;\nclassDef successNode fill:#8BC34A,color:white,stroke:#558B2F,stroke-width:2px;\nclassDef failureNode fill:#F44336,color:white,stroke:#C62828,stroke-width:2px;\n\nclass A triggerNode;\nclass B,C,D,F processNode;\nclass E,G decisionNode;\nclass H successNode;\nclass I failureNode;\n```\n\n## Overview\n\nThis GitHub Actions workflow automates the build and deployment of a Kotlin/JS web application to GitHub Pages. It simplifies the process of publishing your web application by automatically handling the build and deployment steps whenever changes are merged into the development branch.\n\n## Prerequisites\n\nBefore using this workflow, ensure you have the following:\n\n### Repository Setup\n\n1. A Kotlin Multiplatform/JS web application project using Gradle\n2. A Gradle configuration that supports `jsBrowserDistribution` task\n3. GitHub repository with GitHub Pages enabled\n\n### Build Configuration\n\n- Configurable java version (default 17)\n- Kotlin/JS project with a web module\n- Gradle wrapper in the project root\n\n## Workflow Configuration\n\n### 1. How to Setup the Workflow\n\nThis workflow is designed as a reusable workflow. You'll need to call it from another workflow file. Create a workflow file (e.g., `.github/workflows/deploy.yml`) that looks like this:\n\n```yaml\nname: Build And Deploy Web App\n\n# Trigger conditions for the workflow\non:\n  pull_request:\n    branches: [ \"dev\" ]\n    types: [ closed ]\n  workflow_dispatch:\n\n# Concurrency settings to manage multiple workflow runs\n# This ensures orderly deployment to production environment\nconcurrency:\n  group: \"web-pages\"\n  cancel-in-progress: false\n\npermissions:\n  contents: read  # Read repository contents\n  pages: write    # Write to GitHub Pages\n  id-token: write # Write authentication tokens\n  pull-requests: write # Write to pull requests\n\njobs:\n  build_and_deploy_web:\n    name: Build And Deploy Web App\n    uses: openMF/mifos-x-actionhub/.github/workflows/build-and-deploy-site.yaml@v1.0.6\n    secrets: inherit\n    with:\n      web_package_name: 'mifospay-web'\n      java-version: 21\n```\n\nReplace `'your-web-module-name'` with the actual name of your web module in the Gradle project.\n\n### 2. GitHub Pages Configuration\n\n#### Repository Settings\n\n1. Go to your repository's \"Settings\" tab\n2. Navigate to \"Pages\" section\n3. Under \"Source\", select \"GitHub Actions\" as the deployment method\n\n### 3. Gradle Configuration\n\nEnsure your `build.gradle.kts` or `build.gradle` supports JavaScript distribution:\n\n```kotlin\nkotlin {\n    js(IR) {\n        browser {\n            // Browser-specific configuration\n            binaries.executable()\n        }\n    }\n}\n```\n\n## Workflow Details As Per Above Example\n\n### Workflow Triggers\n\n- Automatically triggered on push to the `dev` branch\n- Can be manually triggered via GitHub Actions UI\n\n### Environment\n\n- Java version is configurable via java-version (default 17).\n- Uses Zulu OpenJDK distribution\n\n### Deployment Steps\n\n1. Checkout repository\n2. Setup Java environment\n3. Build web application using `jsBrowserDistribution`\n4. Configure GitHub Pages\n5. Upload build artifacts\n6. Deploy to GitHub Pages\n\n## Troubleshooting\n\n### Common Issues\n\n- Ensure Gradle wrapper is executable (`chmod +x gradlew`)\n- Verify web module name matches exactly in workflow configuration\n- Check that `jsBrowserDistribution` task works locally\n\n### Debugging\n\n- Review workflow run logs in the \"Actions\" tab of your GitHub repository\n- Verify build artifacts are generated correctly\n- Check GitHub Pages settings\n\n## Security Considerations\n\n- Workflow uses minimal required permissions\n- Concurrency settings prevent conflicting deployments\n\n## Version Compatibility\n\n- Tested with:\n  - GitHub Actions: v4-v5\n  - configurable (java-version input; default 17)\n  - Kotlin/JS: Latest versions\n\n\u003cdiv align=\"right\"\u003e\n\n[![Back To Top](https://img.shields.io/badge/Back%20To%20Top-Blue?style=flat)](#readme-top)\n\n\u003c/div\u003e\n\n---\n\n# Monthly Version Tagging Workflow\n\n\u003e \\[!TIP]\n\u003e\n\u003e #### [_monthly-version-tag.yaml_](.github/workflows/monthly-version-tag.yaml)\n\n```mermaid\nflowchart TD\n    A([Workflow Starts]) --\u003e B[Checkout Repository]\n    B --\u003e C[Get Current Timestamp]\n    \n    C --\u003e D[Create Version Tag]\n    D --\u003e E[Tag Format: YYYY.MM.0]\n    \n    style A fill:#2196F3,color:white\n    style B fill:#4CAF50,color:white\n    style C fill:#FF9800,color:white\n    style D fill:#9C27B0,color:white\n    style E fill:#03A9F4,color:white\n```\n\n## Overview\n\nThis GitHub Actions workflow automates the creation of monthly version tags for your repository. It follows a calendar-based versioning scheme, generating tags that represent the year and month of release.\n\n## Versioning Scheme\n\nThe workflow creates tags in the format: `YYYY.MM.0`\n\n- `YYYY`: Full four-digit year\n- `MM`: Two-digit month\n- `.0`: Initial release for the month (allows for potential patch releases)\n\n**Example Tags:**\n\n- `2024.01.0` (January 2024's initial release)\n- `2024.12.0` (December 2024's initial release)\n\n## Prerequisites\n\n### Repository Setup\n\n1. GitHub repository with write access to tags\n2. GitHub Actions enabled\n\n### Workflow Configuration\n\n#### Create Workflow File\n\nCreate a new workflow file in `.github/workflows/monthly-version-tag.yml`:\n\n```yaml\nname: Tag Monthly Release\n\non:\n  # Allow manual triggering of the workflow\n  workflow_dispatch:\n  # Schedule the workflow to run monthly\n  schedule:\n    # Runs at 03:30 UTC on the first day of every month\n    # Cron syntax: minute hour day-of-month month day-of-week\n    - cron: '30 3 1 * *'\n\nconcurrency:\n  group: \"monthly-release\"\n  cancel-in-progress: false\n\njobs:\n  monthly_release:\n    name: Tag Monthly Release\n    uses: openMF/mifos-x-actionhub/.github/workflows/monthly-version-tag.yaml@v1.0.6\n    secrets: inherit\n```\n\n## Workflow Details\n\n### Trigger Conditions\n\n- **Automatic:** First day of each month at 3:30 AM UTC\n- **Manual:** Can be triggered via GitHub Actions UI\n\n### Environment\n\n- Runs on Ubuntu latest\n- Uses GitHub Actions environment\n\n### Workflow Steps\n\n1. Checkout repository\n2. Retrieve current timestamp\n3. Create version tag based on current year and month\n\n## Third-Party Actions Used\n\n### 1. `josStorer/get-current-time@v2.1.2`\n\n- Provides current date and time information\n- Extracts year and month for tag creation\n\n### 2. `rickstaa/action-create-tag@v1.7.2`\n\n- Creates Git tags in the repository\n- Supports custom tag naming\n\n## Customization Options\n\n### Modify Versioning Scheme\n\n- Adjust tag format in the `tag` parameter\n- Add additional logic for more complex versioning\n\n### Change Scheduling\n\n- Modify the cron schedule to suit your release cadence\n- Adjust timezone or specific day of the month\n\n## Security Considerations\n\n- Workflow uses minimal repository permissions\n- Runs on a trusted GitHub-hosted runner\n\n## Troubleshooting\n\n### Common Issues\n\n- Verify GitHub Actions permissions\n- Check repository branch protection rules\n- Ensure no existing tags conflict\n\n### Debugging\n\n- Review workflow run logs in the \"Actions\" tab\n- Manually trigger workflow to test configuration\n\n## Version Compatibility\n\n- Tested with:\n  - GitHub Actions: v4\n  - Ubuntu: Latest\n  - Third-party actions: Specified versions\n\n## Best Practices\n\n- Use this for consistent, predictable versioning\n- Consider combining with release notes or changelog generation\n- Review tags periodically to maintain clarity\n\n\u003cdiv align=\"right\"\u003e\n\n[![Back To Top](https://img.shields.io/badge/Back%20To%20Top-Blue?style=flat)](#readme-top)\n\n\u003c/div\u003e\n\n---\n\n# PR Check Workflow\n\n\u003e \\[!TIP]\n\u003e #### [_pr_check.yml_](.github/workflows/pr-check.yaml)\n\n```mermaid\nflowchart TD\n    A[Code Commit/PR] --\u003e B[Static Analysis Checks]\n    B --\u003e C[Parallel Builds]\n    C --\u003e D1[Android App Build]\n    C --\u003e D2[Desktop App Build]\n    C --\u003e D3[Web App Build]\n    C --\u003e D4[iOS App Build]\n    D1 --\u003e E[Artifacts Generated]\n    D2 --\u003e E\n    D3 --\u003e E\n    D4 --\u003e E\n\n    style A fill:#2196F3,color:white\n    style B fill:#4CAF50,color:white\n    style C fill:#FF9800,color:white\n    style D1 fill:#9C27B0,color:white\n    style D2 fill:#673AB7,color:white\n    style D3 fill:#F44336,color:white\n    style D4 fill:#03A9F4,color:white\n```\n\n## Overview\n\nThis reusable GitHub Actions workflow provides a comprehensive Continuous Integration (CI) pipeline for multi-platform mobile and desktop applications, specifically designed for projects using Gradle and Kotlin Multiplatform (KMP).\n\n## Key Features\n- Automated code quality checks\n- Dependency management and verification\n- Cross-platform builds:\n  - Android APK generation\n  - Desktop application builds (Windows, Linux, MacOS)\n  - Web application compilation\n  - iOS app build support\n\n## Prerequisites\n- Java (configurable, defaults to 17)\n- Gradle\n- Configured build scripts for:\n  - Android module\n  - Desktop module\n  - Web module\n  - iOS module\n- Installed Gradle plugins for code quality checks\n\n## Workflow Jobs\n\n### 1. Static Analysis Checks\n- Runs initial code quality verification\n- Uses custom static analysis check action\n\n### 2. Android App Build\n- Builds debug APK for the specified Android module\n- Runs on Ubuntu latest\n\n### 3. Desktop App Build\n- Builds desktop applications for:\n  - Windows\n  - Linux\n  - MacOS\n- Uses cross-platform build strategy\n\n### 4. Web Application Build\n- Compiles web application\n- Runs on Windows latest\n\n### 5. iOS App Build\n- Builds iOS application\n- Runs on MacOS latest\n\n## Configuration Parameters\n\n| Parameter              | Description                                                                                            | Type    | Required |\n|------------------------|--------------------------------------------------------------------------------------------------------|---------|----------|\n| `android_package_name` | Name of the Android project module                                                                     | String  | Yes      |\n| `desktop_package_name` | Name of the Desktop project module                                                                     | String  | Yes      |\n| `web_package_name`     | Name of the Web project module                                                                         | String  | Yes      |\n| `ios_package_name`     | Name of the iOS project module                                                                         | String  | Yes      |\n| `build_ios`            | Enable iOS build                                                                                       | Boolean | No       |\n| `use_cocoapods`        | Whether to use CocoaPods for integrating the shared module into the iOS app                            | Boolean | Yes      |\n| `shared_module`        | Gradle path to the shared Kotlin Multiplatform module used in the iOS app (e.g., :cmp-shared, :shared) | String  | Required **if `build_ios` = true**      |\n| `use_cocoapods`        | Whether to use CocoaPods for integrating the shared module into the iOS app                            | Boolean| Required **if `build_ios` = true** |\n| `java-version`         | Java version to use (e.g., 17, 21)                                                                     | String | No       |\n| `xcode-version`        | Xcode version to use (e.g., 16.4)                                                                      | String | No       |\n\n## Workflow Trigger Conditions\n- Triggered on workflow call\n- Supports concurrency management\n- Cancels previous runs if a new one is triggered\n\n## Usage Example\n\n```yaml\nname: PR Checks\n\non:\n  pull_request:\n    branches: [ dev, main ]\n\njobs:\n  pr_checks:\n    name: PR Checks\n    uses: openMF/mifos-x-actionhub/.github/workflows/pr-check.yaml@v1.0.6\n    with:\n      android_package_name: 'cmp-android'\n      desktop_package_name: 'cmp-desktop'\n      web_package_name: 'cmp-web'\n      ios_package_name: 'cmp-ios'\n      build_ios: true # \u003c-- Change to 'false' if you don't want to build iOS\n      use_cocoapods: true\n      shared_module: ':cmp-shared'\n      java-version: '21' # \u003c-- Set according to the JDK your project uses (default is 17)\n      xcode-version: '16.4'\n```\n\n\u003cdiv align=\"right\"\u003e\n\n[![Back To Top](https://img.shields.io/badge/Back%20To%20Top-Blue?style=flat)](#readme-top)\n\n\u003c/div\u003e\n\n---\n\n# Promote Release to Play Store Workflow\n\u003e \\[!TIP]\n\u003e #### [_promote_to_production.yml_](.github/workflows/promote-to-production.yaml)\n\n```mermaid\nflowchart TD\n    A([Workflow Starts]) --\u003e B[Checkout Repository]\n    B --\u003e C[Configure Ruby Environment]\n\n    C --\u003e D[Install Fastlane\\nand Plugins]\n    D --\u003e E[Inflate Play Store Secrets]\n\n    E --\u003e F[Promote Beta to\\nProduction Play Store]\n\n    style A fill:#2196F3,color:white\n    style B fill:#4CAF50,color:white\n    style C fill:#FF9800,color:white\n    style D fill:#9C27B0,color:white\n    style E fill:#FF5722,color:white\n    style F fill:#03A9F4,color:white\n```\n\n### Overview\nThis workflow automates the promotion of a beta release to the production environment on the Google Play Store.\n\n### Workflow Trigger\n- Callable workflow (can be invoked from other workflows)\n\n### Prerequisites\n1. **Ruby Environment**\n- Requires Ruby setup (uses `ruby/setup-ruby` action)\n- Bundler version 2.2.27\n- Fastlane installed with specific plugins\n\n2. **Required Plugins**\n- `firebase_app_distribution`\n- `increment_build_number`\n\n### Configuration Steps\n1. **Repository Setup**\n- Ensure your repository is properly structured for Android app deployment\n- Have a `Fastfile` configured with `promote_to_production` lane\n\n2. **Fastlane Configuration**\n   Create a `Fastfile` in your `fastlane` directory with a `promote_to_production` lane:\n   ```ruby\n   default(:android)\n   lane :promote_to_production do\n     # Your specific Play Store promotion logic\n     supply(\n       track: 'beta',\n       track_promote_to: 'production'\n     )\n   end\n   ```\n\n3. **GitHub Secrets**\n- Ensure you have Play Store credentials configured in your repository secrets\n- Typically includes:\n  - `$PLAYSTORE_CREDS`: Google Play Service Account JSON\n  - Other authentication credentials as needed\n\n### Workflow Parameters\n- No direct input parameters\n- Uses environment variable `SUPPLY_UPLOAD_MAX_RETRIES` (default: 5)\n\n### Best Practices\n- Ensure your beta release is thoroughly tested before promotion\n- Use version tagging and semantic versioning\n- Keep Play Store credentials secure\n\n### Example Workflow\n```yaml\nname: Promote Release to Play Store\n\n# Workflow triggers:\n# 1. Manual trigger with option to publish to Play Store\n# 2. Automatic trigger when a GitHub release is published\non:\n  workflow_dispatch:\n    inputs:\n      publish_to_play_store:\n        required: false\n        default: false\n        description: Publish to Play Store?\n        type: boolean\n  release:\n    types: [ released ]\n\nconcurrency:\n  group: \"production-deploy\"\n  cancel-in-progress: false\n\npermissions:\n  contents: write\n\njobs:\n  # Job to promote app from beta to production in Play Store\n  play_promote_production:\n    name: Promote Beta to Production Play Store\n    uses: openMF/mifos-x-actionhub/.github/workflows/promote-to-production.yaml@v1.0.6\n    if: ${{ inputs.publish_to_play_store == true }}\n    secrets: inherit\n    with:\n      android_package_name: 'mifospay-android'\n```\n\n\u003cdiv align=\"right\"\u003e\n\n[![Back To Top](https://img.shields.io/badge/Back%20To%20Top-Blue?style=flat)](#readme-top)\n\n\u003c/div\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FopenMF%2Fmifos-x-actionhub","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FopenMF%2Fmifos-x-actionhub","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FopenMF%2Fmifos-x-actionhub/lists"}