From 08ab22625fa34eced999c8aa36636de14e482fd2 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 29 Aug 2025 11:54:53 +0200 Subject: [PATCH 01/34] refactor: Extract KMP change detection into reusable action Encapsulates the logic for detecting KMP project changes into a dedicated GitHub Action, improving modularity and reusability across workflows. --- .github/actions/kmp-detect-changes/action.yml | 35 +++++++++++++++++++ .../workflows/kmp-cloud-detect-changes.yml | 27 +++++++------- 2 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 .github/actions/kmp-detect-changes/action.yml diff --git a/.github/actions/kmp-detect-changes/action.yml b/.github/actions/kmp-detect-changes/action.yml new file mode 100644 index 0000000..2f796b0 --- /dev/null +++ b/.github/actions/kmp-detect-changes/action.yml @@ -0,0 +1,35 @@ +name: KMP Detect Changes +description: Detects changes in KMP project to determine which platform-specific workflows should run + +inputs: + USE_GIT_LFS: + description: "Whether to download Git-LFS files" + type: boolean + required: false + default: false + +outputs: + iosFiles: + description: "Whether files affecting iOS build changed (all files except those in androidApp/)" + value: ${{ steps.file-changes.outputs.iosFiles }} + androidFiles: + description: "Whether files affecting Android build changed (all files except those in iosApp/)" + value: ${{ steps.file-changes.outputs.androidFiles }} + +runs: + using: "composite" + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + lfs: ${{ inputs.USE_GIT_LFS }} + + - name: Detect Changes + uses: dorny/paths-filter@v3 + id: file-changes + with: + filters: | + iosFiles: + - "!(androidApp/**)" + androidFiles: + - "!(iosApp/**)" diff --git a/.github/workflows/kmp-cloud-detect-changes.yml b/.github/workflows/kmp-cloud-detect-changes.yml index 152afce..3cc3602 100644 --- a/.github/workflows/kmp-cloud-detect-changes.yml +++ b/.github/workflows/kmp-cloud-detect-changes.yml @@ -3,6 +3,9 @@ name: Detect Changes # This workflow is a central decision point in the KMP project CI/CD pipeline that determines # which platform-specific workflows should run based on changed files. # +# This workflow serves as a wrapper around the reusable kmp-detect-changes action +# (.github/actions/kmp-detect-changes) to provide a callable workflow interface. +# # The following project structure is assumed: Android app in `androidApp/` path and iOS app in `iosApp/` path # relative to the repository root. # @@ -17,11 +20,15 @@ name: Detect Changes # Example: # jobs: # changes: -# uses: ./.github/workflows/util_detect_changes.yml +# uses: ./.github/workflows/kmp-cloud-detect-changes.yml # ios-build: # needs: changes # if: ${{ needs.changes.outputs.iosFiles == 'true' }} # uses: ./.github/workflows/build_ios.yml +# +# Note: For direct action usage in other workflows, you can also use: +# - name: Detect Changes +# uses: futuredapp/.github/.github/actions/kmp-detect-changes@main on: workflow_call: @@ -45,20 +52,12 @@ jobs: runs-on: ubuntu-latest outputs: # Matches all files which can affect iOS build if changed - iosFiles: ${{ steps.file-changes.outputs.iosFiles }} + iosFiles: ${{ steps.detect.outputs.iosFiles }} # Matches all files which can affect Android build if changed - androidFiles: ${{ steps.file-changes.outputs.androidFiles }} + androidFiles: ${{ steps.detect.outputs.androidFiles }} steps: - - name: Checkout - uses: actions/checkout@v4 - with: - lfs: ${{ inputs.USE_GIT_LFS }} - name: Detect Changes - uses: dorny/paths-filter@v3 - id: file-changes + id: detect + uses: ./.github/actions/kmp-detect-changes with: - filters: | - iosFiles: - - "!(androidApp/**)" - androidFiles: - - "!(iosApp/**)" + USE_GIT_LFS: ${{ inputs.USE_GIT_LFS }} From d7c5605190b98f78c7f5aa369ac2516ec14f037e Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 29 Aug 2025 11:56:12 +0200 Subject: [PATCH 02/34] fix(github-actions): Improve cache key generation for build artifacts Ensures unique cache keys per workflow and branch to prevent collisions and improve caching reliability. --- .../action.yml | 28 +++++++++++++++++-- .github/workflows/ios-selfhosted-build.yml | 2 +- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/.github/actions/universal-detect-changes-and-generate-changelog/action.yml b/.github/actions/universal-detect-changes-and-generate-changelog/action.yml index 4b58016..1b5876d 100644 --- a/.github/actions/universal-detect-changes-and-generate-changelog/action.yml +++ b/.github/actions/universal-detect-changes-and-generate-changelog/action.yml @@ -27,6 +27,9 @@ outputs: merged_branches: description: "List of merged branch names" value: ${{ steps.generate_changelog.outputs.merged_branches }} + cache_key: + description: "Cache key to store latest built commit for this branch" + value: ${{ steps.cache_keys.outputs.cache_key_prefix }}-${{ github.sha }} runs: using: "composite" @@ -40,7 +43,26 @@ runs: id: cache_keys shell: bash run: | - echo "prev_run=$(expr ${{ github.run_number }} - 1)" >> $GITHUB_OUTPUT + BRANCH_NAME="${{ github.head_ref }}" + if [ -z "$BRANCH_NAME" ]; then + BRANCH_NAME="${{ github.ref_name }}" + fi + BRANCH_SAFE=$(echo "$BRANCH_NAME" | sed 's#[^A-Za-z0-9._-]#_#g') + + # Include workflow name in cache key to avoid conflicts between workflows + WORKFLOW_NAME="${{ github.workflow }}" + WORKFLOW_SAFE=$(echo "$WORKFLOW_NAME" | sed 's#[^A-Za-z0-9._-]#_#g') + CACHE_KEY_PREFIX="latest_builded_commit-${WORKFLOW_SAFE}-${BRANCH_SAFE}" + + if [ "${{ inputs.debug }}" == "true" ]; then + echo "[DEBUG] BRANCH_SAFE='$BRANCH_SAFE'" + echo "[DEBUG] WORKFLOW_NAME='$WORKFLOW_NAME'" + echo "[DEBUG] WORKFLOW_SAFE='$WORKFLOW_SAFE'" + echo "[DEBUG] CACHE_KEY_PREFIX='$CACHE_KEY_PREFIX'" + echo "[DEBUG] CALCULATED_CACHE_KEY='$CACHE_KEY_PREFIX-${{ github.sha }}'" + fi + echo "branch=$BRANCH_SAFE" >> $GITHUB_OUTPUT + echo "cache_key_prefix=$CACHE_KEY_PREFIX" >> $GITHUB_OUTPUT - name: Restore cache for previous build commit SHA id: restore_last_build_cache @@ -48,9 +70,9 @@ runs: continue-on-error: true with: path: latest_builded_commit.txt - key: latest_builded_commit-${{ steps.cache_keys.outputs.prev_run }} + key: ${{ steps.cache_keys.outputs.cache_key_prefix }}-${{ github.sha }} restore-keys: | - latest_builded_commit- + ${{ steps.cache_keys.outputs.cache_key_prefix }}- - name: Determine commit range for changelog and skip build id: determine_range diff --git a/.github/workflows/ios-selfhosted-build.yml b/.github/workflows/ios-selfhosted-build.yml index efe70f2..6035965 100644 --- a/.github/workflows/ios-selfhosted-build.yml +++ b/.github/workflows/ios-selfhosted-build.yml @@ -139,4 +139,4 @@ jobs: uses: actions/cache/save@v4 with: path: latest_builded_commit.txt - key: latest_builded_commit-${{ github.run_number }} + key: ${{ steps.detect_changes.outputs.cache_key }} From 5014fbfea735262992355822da571da813ee5b6a Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 29 Aug 2025 16:16:22 +0200 Subject: [PATCH 03/34] feat: Add Android CI/CD GitHub Actions This commit introduces new composite GitHub Actions for Android projects to standardize CI/CD workflows. These actions include building for Firebase App Distribution, building for Google Play, running lint and unit tests, and setting up the Android environment. --- .../actions/android-build-firebase/action.yml | 91 +++++++++++++++++ .../android-build-googlePlay/action.yml | 99 +++++++++++++++++++ .github/actions/android-check/action.yml | 31 ++++++ .../android-setup-environment/action.yml | 39 ++++++++ 4 files changed, 260 insertions(+) create mode 100644 .github/actions/android-build-firebase/action.yml create mode 100644 .github/actions/android-build-googlePlay/action.yml create mode 100644 .github/actions/android-check/action.yml create mode 100644 .github/actions/android-setup-environment/action.yml diff --git a/.github/actions/android-build-firebase/action.yml b/.github/actions/android-build-firebase/action.yml new file mode 100644 index 0000000..026322d --- /dev/null +++ b/.github/actions/android-build-firebase/action.yml @@ -0,0 +1,91 @@ +name: Enterprise build +description: Builds and uploads app to Firebase App Distribution. + +inputs: + ## Required Inputs + test_gradle_task: + description: "A Gradle task(s) for executing unit tests, for example `testReleaseUnitTest` or `testDevEnterpriseUnitTest`" + required: true + package_gradle_task: + description: "A Gradle task for packaging universal APK" + required: true + default: packageEnterpriseUniversalApk + upload_gradle_task: + description: "A Gradle task for uploading APK, for example `appDistributionUploadEnterprise`" + required: true + app_distribution_groups: + description: "Comma-separated list of Firebase App Distribution group IDs" + required: true + app_distribution_service_account: + required: true + description: "JSON key of service account with permissions to upload build to Firebase App Distribution" + + ## Optional Inputs + version_name: + description: "Version name. Example: '1.X.X-snapshot'" + required: false + build_number_offset: + description: "Build number offset. This number will be added to GITHUB_RUN_NUMBER and can be used to make corrections to build numbers." + required: false + default: 0 + release_notes: + description: "Release notes for this build" + required: false + default: ${{ github.event.head_commit.message }} + kmp_flavor: + description: "KMP Build flavor. This is optional and only required by KMP projects and can be ignored on pure Android projects" + required: false + default: 'test' + secret_properties_file: + description: "A path to file that will be populated with contents of 'SECRET_PROPERTIES' secret. This file can be picked up by Secrets Gradle plugin to embed secrets into BuildConfig." + required: false + default: 'secrets.properties' + secret_properties: + required: false + description: "Custom string that contains key-value properties as secrets. Contents of this secret will be placed into file specified by 'SECRET_PROPERTIES_FILE' input." + +runs: + using: "composite" + steps: + - name: Prepare Environment + shell: bash + run: | + { + echo "ANDROID_BUILD_NUMBER=$((GITHUB_RUN_NUMBER + ${{ inputs.build_number_offset}} ))"; + echo "KMP_FLAVOR=${{ inputs.kmp_flavor }}" + } >> "$GITHUB_ENV" + + # Set ANDROID_VERSION_NAME only if VERSION_NAME is provided + if [[ -n "${{ inputs.version_name }}" ]]; then + echo "ANDROID_VERSION_NAME=${{ inputs.version_name }}" >> "$GITHUB_ENV" + fi + + echo '${{ inputs.secret_properties }}' > ${{ inputs.secret_properties_file }} + - name: Run Unit tests + shell: bash + run: ./gradlew --continue ${{ inputs.test_gradle_task }} + - name: Build universal APK + id: build_apk + shell: bash + run: | + ./gradlew ${{ inputs.package_gradle_task }} -P buildkonfig.flavor="$KMP_FLAVOR" + APK_FILE=$(find . -name '*.apk' | grep -v -e '.*intermediate' -e '.*baseline') + echo "universal_apk_file=$APK_FILE" >> "$GITHUB_OUTPUT" + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: universal_apk + path: ${{ steps.build_apk.outputs.universal_apk_file }} + - name: Upload APK to Firebase App Distribution + shell: bash + run: | + echo '${{ inputs.app_distribution_service_account }}' > "firebase_credentials.json" + + ./gradlew ${{ inputs.upload_gradle_task }} \ + --serviceCredentialsFile="firebase_credentials.json" \ + --groups="${{ inputs.app_distribution_groups }}" \ + --artifactType="APK" \ + --artifactPath="${{ steps.build_apk.outputs.universal_apk_file }}" \ + --releaseNotes='${{ inputs.release_notes }}' + + rm firebase_credentials.json diff --git a/.github/actions/android-build-googlePlay/action.yml b/.github/actions/android-build-googlePlay/action.yml new file mode 100644 index 0000000..4063c53 --- /dev/null +++ b/.github/actions/android-build-googlePlay/action.yml @@ -0,0 +1,99 @@ +name: Release build +description: Builds and uploads app to Google Play. + +inputs: + ## Required Inputs + bundle_gradle_task: + description: "A Gradle task for assembling app bundle, for example `bundleRelease`" + required: true + version_name: + description: "Version name. Example: '1.0.0'" + required: true + signing_keystore_password: + description: "Password to provided keystore" + required: true + signing_key_alias: + description: "Alias of the signing key in the provided keystore" + required: true + signing_key_password: + description: "Password to the key in the provided keystore" + required: true + google_play_application_id: + description: "Google Play applicationId" + required: true + google_play_whatsnew_dir: + description: "Path to directory with changelog files according to documentation in https://github.com/r0adkll/upload-google-play" + required: true + google_play_publish_service_account: + required: true + description: "JSON key of service account with permissions to upload build to Google Play" + + ## Optional Inputs + changes_not_sent_for_review: + description: 'A changesNotSentForReview Google Play flag. Enable when last google review failed, disable when last review was successful.' + required: false + default: false + build_number_offset: + description: "Build number offset. This number will be added to GITHUB_RUN_NUMBER and can be used to make corrections to build numbers." + required: false + default: 0 + kmp_flavor: + description: "KMP Build flavor. This is optional and only required by KMP projects and can be ignored on pure Android projects" + required: false + default: 'prod' + secret_properties_file: + description: "A path to file that will be populated with contents of 'SECRET_PROPERTIES' secret. This file can be picked up by Secrets Gradle plugin to embed secrets into BuildConfig." + required: false + default: 'secrets.properties' + secret_properties: + required: false + description: "Custom string that contains key-value properties as secrets. Contents of this secret will be placed into file specified by 'SECRET_PROPERTIES_FILE' input." + +runs: + using: "composite" + steps: + - name: Prepare Environment + shell: bash + run: | + { + echo "ANDROID_BUILD_NUMBER=$((GITHUB_RUN_NUMBER + ${{ inputs.build_number_offset}} ))"; + echo "ANDROID_VERSION_NAME=${{ inputs.version_name }}"; + echo "KMP_FLAVOR=${{ inputs.kmp_flavor }}" + } >> "$GITHUB_ENV" + + echo '${{ inputs.secret_properties }}' > ${{ inputs.secret_properties_file }} + - name: Generate Artifacts (AAB) + id: build_aab + shell: bash + env: + ANDROID_KEYSTORE_PASSWORD: ${{ inputs.signing_keystore_password }} + ANDROID_KEY_ALIAS: ${{ inputs.signing_key_alias }} + ANDROID_KEY_PASSWORD: ${{ inputs.signing_key_password }} + run: | + ./gradlew ${{ inputs.bundle_gradle_task }} -P buildkonfig.flavor="$KMP_FLAVOR" + BUNDLE_FILE=$(find . -name '*.aab' | grep -v -e '.*intermediate' -e '.*baseline') + MAPPING_FILE=$(find . -name mapping.txt) + + echo "bundle_file=BUNDLE_FILE" >> "$GITHUB_OUTPUT" + echo "mapping_file=$MAPPING_FILE" >> "$GITHUB_OUTPUT" + - name: Upload AAB artifact + uses: actions/upload-artifact@v4 + with: + name: release_bundle + path: ${{ steps.build_aab.outputs.bundle_file }} + - name: Upload Mapping file artifact + uses: actions/upload-artifact@v4 + with: + name: mapping_file + path: ${{ steps.build_aab.outputs.mapping_file }} + - name: Upload to Google Play + uses: r0adkll/upload-google-play@v1.1.1 + with: + serviceAccountJsonPlainText: ${{ inputs.google_play_publish_service_account }} + packageName: ${{ inputs.google_play_application_id }} + releaseFiles: ${{ steps.build_aab.outputs.bundle_file }} + track: internal + status: draft + whatsNewDirectory: ${{ inputs.google_play_whatsnew_dir }} + mappingFile: ${{ steps.build_aab.outputs.mapping_file }} + changesNotSentForReview: ${{ toJSON(inputs.changes_not_sent_for_review) }} diff --git a/.github/actions/android-check/action.yml b/.github/actions/android-check/action.yml new file mode 100644 index 0000000..01b332c --- /dev/null +++ b/.github/actions/android-check/action.yml @@ -0,0 +1,31 @@ +name: Android Check +description: Runs lint checks and unit tests. + +inputs: + # Required inputs + lint_gradle_task: + description: "A Gradle task(s) for executing lint check, for example `lintCheck lintRelease`" + required: true + test_gradle_task: + description: "A Gradle task(s) for executing unit tests, for example `testReleaseUnitTest` or `testDevEnterpriseUnitTest`" + required: true + +runs: + using: "composite" + steps: + - name: Run Lint Check + shell: bash + run: ./gradlew --continue ${{ inputs.lint_gradle_task }} + - name: Run Unit Tests + shell: bash + run: ./gradlew --continue ${{ inputs.test_gradle_task }} + - name: Danger action + uses: MeilCli/danger-action@v2 + continue-on-error: true + with: + plugins_file: 'Gemfile' + danger_file: 'Dangerfile' + danger_id: 'danger-pr' + env: + # The secrets.GITHUB_TOKEN is implicitly provided by trigger workflow + DANGER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/actions/android-setup-environment/action.yml b/.github/actions/android-setup-environment/action.yml new file mode 100644 index 0000000..8cdbc8a --- /dev/null +++ b/.github/actions/android-setup-environment/action.yml @@ -0,0 +1,39 @@ +name: Set up Android environment +description: Sets up Java, Gradle and Ruby and other preconditions for CI runs at Futured Android workflows. + +inputs: + # Required inputs + java_version: + description: "Java version to use, eg. '17'." + required: true + default: '17' + java_distribution: + description: "Java distribution to use, eg 'zulu'." + required: true + default: 'zulu' + + # Optional inputs + gradle_cache_encryption_key: + description: "Configuration cache encryption key. Leave empty if you don't need cache." + required: false + ruby_version: + description: "Ruby version." + required: false + default: '3.4' + +runs: + using: "composite" + steps: + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: ${{ inputs.ruby_version }} + - name: Setup Java + uses: actions/setup-java@v4 + with: + java-version: ${{ inputs.java_version }} + distribution: ${{ inputs.java_distribution }} + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + cache-encryption-key: ${{ inputs.gradle_cache_encryption_key }} From 45d716e7eaabcc0f2d81e7e14f031df74c03f5c3 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 29 Aug 2025 16:20:38 +0200 Subject: [PATCH 04/34] fix: Correctly set `bundle_file` output in Android build action The `bundle_file` output was incorrectly set to the literal string "BUNDLE_FILE" instead of the variable's value due to a missing dollar sign for variable expansion. This commit fixes the issue. --- .github/actions/android-build-googlePlay/action.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/actions/android-build-googlePlay/action.yml b/.github/actions/android-build-googlePlay/action.yml index 4063c53..dfed8da 100644 --- a/.github/actions/android-build-googlePlay/action.yml +++ b/.github/actions/android-build-googlePlay/action.yml @@ -74,7 +74,7 @@ runs: BUNDLE_FILE=$(find . -name '*.aab' | grep -v -e '.*intermediate' -e '.*baseline') MAPPING_FILE=$(find . -name mapping.txt) - echo "bundle_file=BUNDLE_FILE" >> "$GITHUB_OUTPUT" + echo "bundle_file=$BUNDLE_FILE" >> "$GITHUB_OUTPUT" echo "mapping_file=$MAPPING_FILE" >> "$GITHUB_OUTPUT" - name: Upload AAB artifact uses: actions/upload-artifact@v4 From ac059eaeae24c05f49a1b34572ac78f4ce5a7d37 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 29 Aug 2025 16:26:25 +0200 Subject: [PATCH 05/34] refactor(android): Use composite actions for setup and checks Encapsulate environment setup and check execution into reusable GitHub Actions. --- .github/workflows/android-cloud-check.yml | 36 ++++++----------------- 1 file changed, 9 insertions(+), 27 deletions(-) diff --git a/.github/workflows/android-cloud-check.yml b/.github/workflows/android-cloud-check.yml index 519bf97..f64fd43 100644 --- a/.github/workflows/android-cloud-check.yml +++ b/.github/workflows/android-cloud-check.yml @@ -57,32 +57,14 @@ jobs: uses: actions/checkout@v4 with: lfs: ${{ inputs.USE_GIT_LFS }} - - name: Setup Ruby - uses: ruby/setup-ruby@v1 + - name: Set up environment + uses: .github/actions/android-setup-environment with: - ruby-version: '3.4' - - name: Setup Java - uses: actions/setup-java@v4 + java_version: ${{ inputs.JAVA_VERSION }} + java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} + gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} + - name: Run checks + uses: .github/actions/android-check with: - java-version: ${{ inputs.JAVA_VERSION }} - distribution: ${{ inputs.JAVA_DISTRIBUTION }} - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - with: - cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - - name: Run Lint Check - shell: bash - run: ./gradlew --continue ${{ inputs.LINT_GRADLE_TASKS }} - - name: Run Unit Tests - shell: bash - run: ./gradlew --continue ${{ inputs.TEST_GRADLE_TASKS }} - - name: Danger action - uses: MeilCli/danger-action@v2 - continue-on-error: true - with: - plugins_file: 'Gemfile' - danger_file: 'Dangerfile' - danger_id: 'danger-pr' - env: - # The secrets.GITHUB_TOKEN is implicitly provided by trigger workflow - DANGER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + lint_gradle_task: ${{ inputs.LINT_GRADLE_TASKS }} + test_gradle_task: ${{ inputs.TEST_GRADLE_TASKS }} From c39680ae4d1fedabaf3e2a0e3529ba7837991e19 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 29 Aug 2025 16:28:34 +0200 Subject: [PATCH 06/34] fix: Correct relative paths for GitHub Actions Ensure local GitHub Actions are referenced with explicit relative paths to prevent resolution issues. --- .github/workflows/android-cloud-check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android-cloud-check.yml b/.github/workflows/android-cloud-check.yml index f64fd43..59a7910 100644 --- a/.github/workflows/android-cloud-check.yml +++ b/.github/workflows/android-cloud-check.yml @@ -58,13 +58,13 @@ jobs: with: lfs: ${{ inputs.USE_GIT_LFS }} - name: Set up environment - uses: .github/actions/android-setup-environment + uses: ./.github/actions/android-setup-environment with: java_version: ${{ inputs.JAVA_VERSION }} java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - name: Run checks - uses: .github/actions/android-check + uses: ./.github/actions/android-check with: lint_gradle_task: ${{ inputs.LINT_GRADLE_TASKS }} test_gradle_task: ${{ inputs.TEST_GRADLE_TASKS }} From b4fbbe1adec97b0f41197aa254e3922e8fb73241 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 29 Aug 2025 16:39:08 +0200 Subject: [PATCH 07/34] chore: Update Android cloud check workflow to use remote actions Reference `android-setup-environment` and `android-check` from `futuredapp/.github`'s `feature/matsem/changelog-android` branch. --- .github/workflows/android-cloud-check.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android-cloud-check.yml b/.github/workflows/android-cloud-check.yml index 59a7910..d857baa 100644 --- a/.github/workflows/android-cloud-check.yml +++ b/.github/workflows/android-cloud-check.yml @@ -58,13 +58,13 @@ jobs: with: lfs: ${{ inputs.USE_GIT_LFS }} - name: Set up environment - uses: ./.github/actions/android-setup-environment + uses: futuredapp/.github/.github/actions/android-setup-environment@feature/matsem/changelog-android with: java_version: ${{ inputs.JAVA_VERSION }} java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - name: Run checks - uses: ./.github/actions/android-check + uses: futuredapp/.github/.github/actions/android-check@feature/matsem/changelog-android with: lint_gradle_task: ${{ inputs.LINT_GRADLE_TASKS }} test_gradle_task: ${{ inputs.TEST_GRADLE_TASKS }} From 1a51dcd8ee85db00655041fe4a878f6910f200d2 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 29 Aug 2025 16:49:30 +0200 Subject: [PATCH 08/34] fix(github-actions): Update DANGER_GITHUB_API_TOKEN to use `github.token` Replace `secrets.GITHUB_TOKEN` with the recommended `github.token` for better readability and consistency. --- .github/actions/android-check/action.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/actions/android-check/action.yml b/.github/actions/android-check/action.yml index 01b332c..1cc5c02 100644 --- a/.github/actions/android-check/action.yml +++ b/.github/actions/android-check/action.yml @@ -27,5 +27,4 @@ runs: danger_file: 'Dangerfile' danger_id: 'danger-pr' env: - # The secrets.GITHUB_TOKEN is implicitly provided by trigger workflow - DANGER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DANGER_GITHUB_API_TOKEN: ${{ github.token }} From 46e07d92b8f792df5c641a8deb095788c0836cc4 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 29 Aug 2025 16:51:52 +0200 Subject: [PATCH 09/34] chore: Add TODO comments to Android cloud check workflow for branch ref updates --- .github/workflows/android-cloud-check.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/android-cloud-check.yml b/.github/workflows/android-cloud-check.yml index d857baa..50e5141 100644 --- a/.github/workflows/android-cloud-check.yml +++ b/.github/workflows/android-cloud-check.yml @@ -58,12 +58,14 @@ jobs: with: lfs: ${{ inputs.USE_GIT_LFS }} - name: Set up environment + # TODO update branch ref to main, reject pull request if you see this uses: futuredapp/.github/.github/actions/android-setup-environment@feature/matsem/changelog-android with: java_version: ${{ inputs.JAVA_VERSION }} java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - name: Run checks + # TODO update branch ref to main, reject pull request if you see this uses: futuredapp/.github/.github/actions/android-check@feature/matsem/changelog-android with: lint_gradle_task: ${{ inputs.LINT_GRADLE_TASKS }} From d4c2c92e6bcb8bd8ce4c30d9db9456e6d03bb50a Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 29 Aug 2025 16:58:50 +0200 Subject: [PATCH 10/34] chore(github-actions): Update Android release workflow to use composite actions Replace inline steps with reusable `android-setup-environment` and `android-build-googlePlay` composite actions from `futuredapp/.github`. Add TODOs to update branch references to `main`. --- .../android-cloud-release-googlePlay.yml | 63 +++++++------------ 1 file changed, 21 insertions(+), 42 deletions(-) diff --git a/.github/workflows/android-cloud-release-googlePlay.yml b/.github/workflows/android-cloud-release-googlePlay.yml index eb30bf4..c85d3eb 100644 --- a/.github/workflows/android-cloud-release-googlePlay.yml +++ b/.github/workflows/android-cloud-release-googlePlay.yml @@ -96,52 +96,31 @@ jobs: timeout-minutes: ${{ inputs.TIMEOUT_MINUTES }} env: GRADLE_OPTS: ${{ inputs.GRADLE_OPTS }} - EXCLUDE_AAB_FILTER: .*intermediate steps: - name: Checkout uses: actions/checkout@v4 with: lfs: ${{ inputs.USE_GIT_LFS }} - - name: Setup Java - uses: actions/setup-java@v4 + - name: Set up environment + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/android-setup-environment@feature/matsem/changelog-android with: - java-version: ${{ inputs.JAVA_VERSION }} - distribution: ${{ inputs.JAVA_DISTRIBUTION }} - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + java_version: ${{ inputs.JAVA_VERSION }} + java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} + - name: Build and release + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/android-build-googlePlay@feature/matsem/changelog-android with: - cache-disabled: true - - name: Prepare Environment - run: | - { - echo "ANDROID_BUILD_NUMBER=$((GITHUB_RUN_NUMBER + ${{ inputs.BUILD_NUMBER_OFFSET}} ))"; - echo "ANDROID_VERSION_NAME=${{ inputs.VERSION_NAME }}"; - echo "KMP_FLAVOR=${{ inputs.KMP_FLAVOR }}" - } >> "$GITHUB_ENV" - - echo '${{ secrets.SECRET_PROPERTIES }}' > ${{ inputs.SECRET_PROPERTIES_FILE }} - - name: Generate Artifacts (AAB) - id: artifacts - env: - ANDROID_KEYSTORE_PASSWORD: ${{ secrets.SIGNING_KEYSTORE_PASSWORD }} - ANDROID_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }} - ANDROID_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }} - shell: bash - run: | - ./gradlew ${{ inputs.BUNDLE_GRADLE_TASK }} -P buildkonfig.flavor="$KMP_FLAVOR" - BUNDLE_FILE=$(find . -name '*.aab' | grep -v '.*intermediate') - MAPPING_FILE=$(find . -name mapping.txt) - - echo "bundle_file=$BUNDLE_FILE" >> "$GITHUB_OUTPUT" - echo "mapping_file=$MAPPING_FILE" >> "$GITHUB_OUTPUT" - - name: Upload to Google Play - uses: r0adkll/upload-google-play@v1.1.1 - with: - serviceAccountJsonPlainText: ${{ secrets.GOOGLE_PLAY_PUBLISH_SERVICE_ACCOUNT }} - packageName: ${{ inputs.GOOGLE_PLAY_APPLICATION_ID }} - releaseFiles: ${{ steps.artifacts.outputs.bundle_file }} - track: internal - status: draft - whatsNewDirectory: ${{ inputs.GOOGLE_PLAY_WHATSNEW_DIRECTORY }} - mappingFile: ${{ steps.artifacts.outputs.mapping_file }} - changesNotSentForReview: ${{ toJSON(inputs.CHANGES_NOT_SENT_FOR_REVIEW) }} + bundle_gradle_task: ${{ inputs.BUNDLE_GRADLE_TASK }} + version_name: ${{ inputs.VERSION_NAME }} + signing_keystore_password: ${{ secrets.SIGNING_KEYSTORE_PASSWORD }} + signing_key_alias: ${{ secrets.SIGNING_KEY_ALIAS }} + signing_key_password: ${{ secrets.SIGNING_KEY_PASSWORD }} + google_play_application_id: ${{ inputs.GOOGLE_PLAY_APPLICATION_ID }} + google_play_whatsnew_dir: ${{ inputs.GOOGLE_PLAY_WHATSNEW_DIRECTORY }} + google_play_publish_service_account: ${{ secrets.GOOGLE_PLAY_PUBLISH_SERVICE_ACCOUNT }} + changes_not_sent_for_review: ${{ inputs.CHANGES_NOT_SENT_FOR_REVIEW }} + build_number_offset: ${{ inputs.BUILD_NUMBER_OFFSET }} + kmp_flavor: ${{ inputs.KMP_FLAVOR }} + secret_properties_file: ${{ inputs.SECRET_PROPERTIES_FILE }} + secret_properties: ${{ secrets.SECRET_PROPERTIES }} From 40d10b0ffd178c42464b5ee7f5762025bd4d4733 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 29 Aug 2025 18:13:22 +0200 Subject: [PATCH 11/34] feat(android-ci): Add Android nightly build workflow This workflow automates nightly builds for Android projects, including changelog generation and Firebase App Distribution. The `package_gradle_task` in `android-build-firebase` action is updated to require explicit definition. --- .../actions/android-build-firebase/action.yml | 3 +- .../workflows/android-cloud-nightly-build.yml | 145 ++++++++++++++++++ 2 files changed, 146 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/android-cloud-nightly-build.yml diff --git a/.github/actions/android-build-firebase/action.yml b/.github/actions/android-build-firebase/action.yml index 026322d..0e4e2c0 100644 --- a/.github/actions/android-build-firebase/action.yml +++ b/.github/actions/android-build-firebase/action.yml @@ -7,9 +7,8 @@ inputs: description: "A Gradle task(s) for executing unit tests, for example `testReleaseUnitTest` or `testDevEnterpriseUnitTest`" required: true package_gradle_task: - description: "A Gradle task for packaging universal APK" + description: "A Gradle task for packaging universal APK, eg. 'packageEnterpriseUniversalApk'" required: true - default: packageEnterpriseUniversalApk upload_gradle_task: description: "A Gradle task for uploading APK, for example `appDistributionUploadEnterprise`" required: true diff --git a/.github/workflows/android-cloud-nightly-build.yml b/.github/workflows/android-cloud-nightly-build.yml new file mode 100644 index 0000000..22d63cb --- /dev/null +++ b/.github/workflows/android-cloud-nightly-build.yml @@ -0,0 +1,145 @@ +name: Android nightly build + +on: + workflow_call: + inputs: + ## Required Inputs + TEST_GRADLE_TASKS: + description: "A Gradle task(s) for executing unit tests, for example `testReleaseUnitTest` or `testDevEnterpriseUnitTest`" + required: true + type: string + PACKAGE_GRADLE_TASK: + description: "A Gradle task for packaging universal APK, eg. 'packageEnterpriseUniversalApk'" + required: true + type: string + UPLOAD_GRADLE_TASK: + description: "A Gradle task for uploading APK, for example `appDistributionUploadEnterprise`" + required: true + type: string + APP_DISTRIBUTION_GROUPS: + description: "Comma-separated list of app distribution group IDs" + required: true + type: string + + ## Optional Inputs + USE_GIT_LFS: + description: "Whether to download Git-LFS files" + type: boolean + required: false + default: false + VERSION_NAME: + description: "Version name. Example: '1.X.X-snapshot'" + required: false + type: string + BUILD_NUMBER_OFFSET: + description: "Build number offset. This number will be added to GITHUB_RUN_NUMBER and can be used to make corrections to build numbers." + required: false + type: number + default: 0 + KMP_FLAVOR: + description: "KMP Build flavor. This is optional and only required by KMP projects and can be ignored on pure Android projects" + required: false + type: string + default: 'test' + SECRET_PROPERTIES_FILE: + description: "A path to file that will be populated with contents of 'SECRET_PROPERTIES' secret. This file can be picked up by Secrets Gradle plugin to embed secrets into BuildConfig." + required: false + type: string + default: secrets.properties + JAVA_VERSION: + description: "Java version to use" + required: false + type: string + default: '17' + JAVA_DISTRIBUTION: + description: "Java distribution to use" + required: false + type: string + default: 'zulu' + GRADLE_OPTS: + description: "Gradle options" + required: false + type: string + default: "" + CHANGELOG_DEBUG: + description: "Enable debug mode for changelog generation. Default is false." + type: boolean + required: false + default: false + CHANGELOG_CHECKOUT_DEPTH: + description: "The depth of the git history to fetch for changelog generation. Default is 100." + type: number + required: false + default: 100 + CHANGELOG_FALLBACK_LOOKBACK: + description: "The amount of time to look back for merge commits when no previous build commit is found. Default is 24 hours." + type: string + required: false + default: "24 hours" + TIMEOUT_MINUTES: + description: "Job timeout in minutes" + required: false + type: number + default: 30 + + secrets: + APP_DISTRIBUTION_SERVICE_ACCOUNT: + required: true + description: "JSON key of service account with permissions to upload build to Firebase App Distribution" + GRADLE_CACHE_ENCRYPTION_KEY: + required: false + description: "Configuration cache encryption key" + SECRET_PROPERTIES: + required: false + description: "Custom string that contains key-value properties as secrets. Contents of this secret will be placed into file specified by 'SECRET_PROPERTIES_FILE' input." + +jobs: + changelog: + outputs: + skip_build: ${{ steps.detect_changes.outputs.skip_build }} + changelog: ${{ steps.detect_changes.outputs.changelog }} + name: Detect changes and generate changelog + runs-on: ubuntu-latest + steps: + - name: Detect changes and generate changelog + id: detect_changes + uses: futuredapp/.github/.github/actions/universal-detect-changes-and-generate-changelog@main + with: + checkout_depth: ${{ inputs.CHANGELOG_CHECKOUT_DEPTH }} + debug: ${{ inputs.CHANGELOG_DEBUG }} + fallback_lookback: ${{ inputs.CHANGELOG_FALLBACK_LOOKBACK }} + build: + name: Enterprise build + runs-on: ubuntu-latest + needs: changelog + if: ${{ needs.changelog.outputs.skip_build != 'true' }} + timeout-minutes: ${{ inputs.TIMEOUT_MINUTES }} + env: + GRADLE_OPTS: ${{ inputs.GRADLE_OPTS }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + lfs: ${{ inputs.USE_GIT_LFS }} + - name: Set up environment + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/android-setup-environment@feature/matsem/changelog-android + with: + java_version: ${{ inputs.JAVA_VERSION }} + java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} + gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} + - name: Build and upload to App Distribution + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/android-build-firebase@feature/matsem/changelog-android + with: + test_gradle_task: ${{ inputs.TEST_GRADLE_TASKS }} + package_gradle_task: ${{ inputs.PACKAGE_GRADLE_TASK }} + upload_gradle_task: ${{ inputs.UPLOAD_GRADLE_TASK }} + app_distribution_groups: ${{ inputs.APP_DISTRIBUTION_GROUPS }} + app_distribution_service_account: ${{ secrets.APP_DISTRIBUTION_SERVICE_ACCOUNT }} + version_name: ${{ inputs.VERSION_NAME }} + build_number_offset: ${{ inputs.BUILD_NUMBER_OFFSET }} + release_notes: ${{ needs.changelog.outputs.changelog }} + kmp_flavor: ${{ inputs.KMP_FLAVOR }} + secret_properties_file: ${{ inputs.SECRET_PROPERTIES_FILE }} + secret_properties: ${{ secrets.SECRET_PROPERTIES }} From eef69ce729863b5c59eb50d26e6d07bc1cdbe0b0 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 29 Aug 2025 18:50:49 +0200 Subject: [PATCH 12/34] ci: Cache latest build commit SHA in nightly workflow Introduces caching of the last successfully built commit's SHA to optimize subsequent nightly builds. --- .github/workflows/android-cloud-nightly-build.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android-cloud-nightly-build.yml b/.github/workflows/android-cloud-nightly-build.yml index 22d63cb..15bffaf 100644 --- a/.github/workflows/android-cloud-nightly-build.yml +++ b/.github/workflows/android-cloud-nightly-build.yml @@ -98,12 +98,14 @@ jobs: outputs: skip_build: ${{ steps.detect_changes.outputs.skip_build }} changelog: ${{ steps.detect_changes.outputs.changelog }} + cache_key: ${{ steps.detect_changes.outputs.cache_key }} name: Detect changes and generate changelog runs-on: ubuntu-latest steps: - name: Detect changes and generate changelog id: detect_changes - uses: futuredapp/.github/.github/actions/universal-detect-changes-and-generate-changelog@main + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/universal-detect-changes-and-generate-changelog@feature/matsem/changelog-android with: checkout_depth: ${{ inputs.CHANGELOG_CHECKOUT_DEPTH }} debug: ${{ inputs.CHANGELOG_DEBUG }} @@ -143,3 +145,9 @@ jobs: kmp_flavor: ${{ inputs.KMP_FLAVOR }} secret_properties_file: ${{ inputs.SECRET_PROPERTIES_FILE }} secret_properties: ${{ secrets.SECRET_PROPERTIES }} + - name: Store latest build commit SHA in cache + if: success() && needs.changelog.outputs.skip_build != 'true' + uses: actions/cache/save@v4 + with: + path: latest_builded_commit.txt + key: ${{ needs.changelog.outputs.cache_key }} From 744db856d3410282ecba2b57010a22e809a50ba0 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 29 Aug 2025 19:18:47 +0200 Subject: [PATCH 13/34] ci: Save latest build commit SHA to file Ensure the commit SHA of the latest nightly build is explicitly saved to a file for tracking and caching. --- .github/workflows/android-cloud-nightly-build.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/android-cloud-nightly-build.yml b/.github/workflows/android-cloud-nightly-build.yml index 15bffaf..70844b9 100644 --- a/.github/workflows/android-cloud-nightly-build.yml +++ b/.github/workflows/android-cloud-nightly-build.yml @@ -145,6 +145,14 @@ jobs: kmp_flavor: ${{ inputs.KMP_FLAVOR }} secret_properties_file: ${{ inputs.SECRET_PROPERTIES_FILE }} secret_properties: ${{ secrets.SECRET_PROPERTIES }} + - name: Save latest build commit SHA to file + if: success() && needs.changelog.outputs.skip_build != 'true' + shell: bash + run: | + echo "${{ github.sha }}" > latest_builded_commit.txt + if [ "${{ inputs.CHANGELOG_DEBUG }}" == 'true' ]; then + echo "[DEBUG] Saved commit SHA ${{ github.sha }} to latest_builded_commit.txt" + fi - name: Store latest build commit SHA in cache if: success() && needs.changelog.outputs.skip_build != 'true' uses: actions/cache/save@v4 From 5abbf1bbaf6f9c7ff369b45702339c6c88a62586 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Tue, 23 Sep 2025 11:30:31 +0200 Subject: [PATCH 14/34] refactor(ci): Streamline Android Firebase App Distribution workflow Encapsulate build and upload logic into reusable GitHub Actions for better maintainability and reusability. --- ...-cloud-release-firebaseAppDistribution.yml | 109 +++++------------- 1 file changed, 28 insertions(+), 81 deletions(-) diff --git a/.github/workflows/android-cloud-release-firebaseAppDistribution.yml b/.github/workflows/android-cloud-release-firebaseAppDistribution.yml index 9f96423..452a1f9 100644 --- a/.github/workflows/android-cloud-release-firebaseAppDistribution.yml +++ b/.github/workflows/android-cloud-release-firebaseAppDistribution.yml @@ -8,18 +8,14 @@ on: description: "A Gradle task(s) for executing unit tests, for example `testReleaseUnitTest` or `testDevEnterpriseUnitTest`" required: true type: string - BUNDLE_GRADLE_TASK: - description: "A Gradle task for assembling app bundle, for example `bundleEnterprise`" + PACKAGE_GRADLE_TASK: + description: "A Gradle task for packaging universal APK, eg. 'packageEnterpriseUniversalApk'" required: true type: string UPLOAD_GRADLE_TASK: description: "A Gradle task for uploading APK, for example `appDistributionUploadEnterprise`" required: true type: string - SIGNING_KEYSTORE_PATH: - description: "Path to keystore for signing of universal APK. Example: `keystore/debug.jks' or 'androidApp/signing/debug.keystore'." - required: true - type: string APP_DISTRIBUTION_GROUPS: description: "Comma-separated list of app distribution group IDs" required: true @@ -55,11 +51,6 @@ on: required: false type: string default: secrets.properties - TIMEOUT_MINUTES: - description: "Job timeout in minutes" - required: false - type: number - default: 30 JAVA_VERSION: description: "Java version to use" required: false @@ -75,17 +66,13 @@ on: required: false type: string default: "" + TIMEOUT_MINUTES: + description: "Job timeout in minutes" + required: false + type: number + default: 30 secrets: - SIGNING_KEYSTORE_PASSWORD: - description: "Password to provided keystore" - required: true - SIGNING_KEY_ALIAS: - description: "Alias of the signing key in the provided keystore" - required: true - SIGNING_KEY_PASSWORD: - description: "Password to the key in the provided keystore" - required: true APP_DISTRIBUTION_SERVICE_ACCOUNT: required: true description: "JSON key of service account with permissions to upload build to Firebase App Distribution" @@ -99,74 +86,34 @@ on: jobs: build: name: Enterprise Build - runs-on: [ ubuntu-latest ] + runs-on: ubuntu-latest timeout-minutes: ${{ inputs.TIMEOUT_MINUTES }} env: GRADLE_OPTS: ${{ inputs.GRADLE_OPTS }} - FIREBASE_CREDENTIALS_FILE: firebase_credentials.json - BUNDLETOOL_URL: https://github.com/google/bundletool/releases/download/1.17.2/bundletool-all-1.17.2.jar - EXCLUDE_AAB_FILTER: .*intermediate - ANDROID_KEYSTORE_PASSWORD: ${{ secrets.SIGNING_KEYSTORE_PASSWORD }} - ANDROID_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }} - ANDROID_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }} steps: - name: Checkout uses: actions/checkout@v4 with: lfs: ${{ inputs.USE_GIT_LFS }} - - name: Setup Java - uses: actions/setup-java@v4 + - name: Set up environment + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/android-setup-environment@feature/matsem/changelog-android with: - java-version: ${{ inputs.JAVA_VERSION }} - distribution: ${{ inputs.JAVA_DISTRIBUTION }} - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 + java_version: ${{ inputs.JAVA_VERSION }} + java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} + gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} + - name: Build and upload to App Distribution + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/android-build-firebase@feature/matsem/changelog-android with: - cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - - name: Prepare Environment - run: | - { - echo "ANDROID_BUILD_NUMBER=$((GITHUB_RUN_NUMBER + ${{ inputs.BUILD_NUMBER_OFFSET}} ))"; - echo "KMP_FLAVOR=${{ inputs.KMP_FLAVOR }}" - } >> "$GITHUB_ENV" - - # Set ANDROID_VERSION_NAME only if VERSION_NAME is provided - if [[ -n "${{ inputs.VERSION_NAME }}" ]]; then - echo "ANDROID_VERSION_NAME=${{ inputs.VERSION_NAME }}" >> "$GITHUB_ENV" - fi - - echo '${{ secrets.SECRET_PROPERTIES }}' > ${{ inputs.SECRET_PROPERTIES_FILE }} - echo '${{ secrets.APP_DISTRIBUTION_SERVICE_ACCOUNT }}' > "$FIREBASE_CREDENTIALS_FILE" - - name: Run Unit tests - shell: bash - run: ./gradlew --continue ${{ inputs.TEST_GRADLE_TASKS }} - - name: Generate Artifacts (AAB and APK) - id: artifacts - shell: bash - run: | - ./gradlew ${{ inputs.BUNDLE_GRADLE_TASK }} -P buildkonfig.flavor="$KMP_FLAVOR" - BUNDLE_FILE=$(find . -name '*.aab' | grep -v '.*intermediate') - - wget -O bundletool.jar ${{ env.BUNDLETOOL_URL }} - java -jar bundletool.jar build-apks \ - --bundle "$BUNDLE_FILE" \ - --output universal.apks \ - --mode universal \ - --ks ${{ inputs.SIGNING_KEYSTORE_PATH }} \ - --ks-pass pass:${{ secrets.SIGNING_KEYSTORE_PASSWORD }} \ - --ks-key-alias ${{ secrets.SIGNING_KEY_ALIAS }} \ - --key-pass pass:${{ secrets.SIGNING_KEY_PASSWORD }} - unzip universal.apks -d universal_apk - UNIVERSAL_APK_FILE=$(find universal_apk/ -name '*.apk') - - echo "bundle_file=$BUNDLE_FILE" >> "$GITHUB_OUTPUT" - echo "universal_apk_file=$UNIVERSAL_APK_FILE" >> "$GITHUB_OUTPUT" - - name: Upload to Firebase App Distribution - shell: bash - run: | - ./gradlew ${{ inputs.UPLOAD_GRADLE_TASK }} \ - --serviceCredentialsFile="$FIREBASE_CREDENTIALS_FILE" \ - --groups="${{ inputs.APP_DISTRIBUTION_GROUPS }}" \ - --artifactType="APK" \ - --artifactPath="${{ steps.artifacts.outputs.universal_apk_file }}" \ - --releaseNotes='${{ inputs.RELEASE_NOTES }}' + test_gradle_task: ${{ inputs.TEST_GRADLE_TASKS }} + package_gradle_task: ${{ inputs.PACKAGE_GRADLE_TASK }} + upload_gradle_task: ${{ inputs.UPLOAD_GRADLE_TASK }} + app_distribution_groups: ${{ inputs.APP_DISTRIBUTION_GROUPS }} + app_distribution_service_account: ${{ secrets.APP_DISTRIBUTION_SERVICE_ACCOUNT }} + version_name: ${{ inputs.VERSION_NAME }} + build_number_offset: ${{ inputs.BUILD_NUMBER_OFFSET }} + release_notes: ${{ inputs.RELEASE_NOTES }} + kmp_flavor: ${{ inputs.KMP_FLAVOR }} + secret_properties_file: ${{ inputs.SECRET_PROPERTIES_FILE }} + secret_properties: ${{ secrets.SECRET_PROPERTIES }} From b9fe6ac7c73e601f503572cbad6d547726b0d7e7 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Tue, 23 Sep 2025 14:41:15 +0200 Subject: [PATCH 15/34] refactor(ci): Extract baseline profile generation into reusable action The existing workflow for generating Android baseline profiles was refactored to extract the core logic into a dedicated, reusable GitHub Action. This improves modularity and simplifies the workflow definition. The workflow file was also renamed to reflect its cloud context. --- .../action.yml | 53 +++++++++++++++++++ ...roid-cloud-generate-baseline-profiles.yml} | 50 ++++++----------- 2 files changed, 68 insertions(+), 35 deletions(-) create mode 100644 .github/actions/android-generate-baseline-profiles/action.yml rename .github/workflows/{android-generate-baseline-profiles.yml => android-cloud-generate-baseline-profiles.yml} (60%) diff --git a/.github/actions/android-generate-baseline-profiles/action.yml b/.github/actions/android-generate-baseline-profiles/action.yml new file mode 100644 index 0000000..1b0cfda --- /dev/null +++ b/.github/actions/android-generate-baseline-profiles/action.yml @@ -0,0 +1,53 @@ +name: Generate Baseline Profiles +description: Generates baseline profiles and creates a PR with the changes + +inputs: + # Required inputs + generate_gradle_task: + description: "A Gradle task for generating baseline profiles, for example `generateBaselineProfile`" + required: true + signing_keystore_password: + description: "Password to provided keystore" + required: true + signing_key_alias: + description: "Alias of the signing key in the provided keystore" + required: true + signing_key_password: + description: "Password to the key in the provided keystore" + required: true + secret_properties_file: + description: "A path to file that will be populated with contents of 'SECRET_PROPERTIES' secret. This file can be picked up by Secrets Gradle plugin to embed secrets into BuildConfig." + required: false + default: 'secrets.properties' + secret_properties: + required: false + description: "Custom string that contains key-value properties as secrets. Contents of this secret will be placed into file specified by 'SECRET_PROPERTIES_FILE' input." + +runs: + using: "composite" + steps: + - name: Enable KVM group perms + run: | + echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules + sudo udevadm control --reload-rules + sudo udevadm trigger --name-match=kvm + ls /dev/kvm + - name: Prepare Environment + run: | + echo '${{ inputs.secret_properties }}' > ${{ inputs.secret_properties_file }} + - name: Generate profiles + env: + ANDROID_KEYSTORE_PASSWORD: ${{ inputs.signing_keystore_password }} + ANDROID_KEY_ALIAS: ${{ inputs.signing_key_alias }} + ANDROID_KEY_PASSWORD: ${{ inputs.signing_key_password }} + run: ./gradlew ${{ inputs.generate_gradle_task }} + -Pandroid.experimental.testOptions.managedDevices.emulator.showKernelLogging=true + -Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect" + - name: Create Pull Request + uses: peter-evans/create-pull-request@v7 + with: + commit-message: 'Generate baseline profiles' + branch: 'feature/generate-baseline-profiles' + title: 'Generate baseline profiles' + body: '' + diff --git a/.github/workflows/android-generate-baseline-profiles.yml b/.github/workflows/android-cloud-generate-baseline-profiles.yml similarity index 60% rename from .github/workflows/android-generate-baseline-profiles.yml rename to .github/workflows/android-cloud-generate-baseline-profiles.yml index 1428004..4ee78b3 100644 --- a/.github/workflows/android-generate-baseline-profiles.yml +++ b/.github/workflows/android-cloud-generate-baseline-profiles.yml @@ -74,40 +74,20 @@ jobs: uses: actions/checkout@v4 with: lfs: ${{ inputs.USE_GIT_LFS }} - - name: Enable KVM group perms - run: | - echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules - sudo udevadm control --reload-rules - sudo udevadm trigger --name-match=kvm - ls /dev/kvm - - name: Setup Ruby - uses: ruby/setup-ruby@v1 + - name: Set up environment + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/android-setup-environment@feature/matsem/changelog-android with: - ruby-version: '3.0' - - name: Setup Java - uses: actions/setup-java@v4 + java_version: ${{ inputs.JAVA_VERSION }} + java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} + gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} + - name: Generate baseline profiles + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/android-generate-baseline-profiles@feature/matsem/changelog-android with: - java-version: ${{ inputs.JAVA_VERSION }} - distribution: ${{ inputs.JAVA_DISTRIBUTION }} - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - with: - cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - - name: Prepare Environment - run: | - echo '${{ secrets.SECRET_PROPERTIES }}' > ${{ inputs.SECRET_PROPERTIES_FILE }} - - name: Setup GMD - run: ./gradlew ${{ inputs.TASK_NAME }} - -Pandroid.experimental.testOptions.managedDevices.emulator.showKernelLogging=true - -Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect" - env: - ANDROID_KEYSTORE_PASSWORD: ${{ secrets.SIGNING_KEYSTORE_PASSWORD }} - ANDROID_KEY_ALIAS: ${{ secrets.SIGNING_KEY_ALIAS }} - ANDROID_KEY_PASSWORD: ${{ secrets.SIGNING_KEY_PASSWORD }} - - name: Create Pull Request - uses: peter-evans/create-pull-request@v7 - with: - commit-message: 'Generate baseline profiles' - branch: 'feature/generate-baseline-profiles' - title: 'Generate baseline profiles' - body: '' + generate_gradle_task: ${{ inputs.TASK_NAME }} + signing_keystore_password: ${{ secrets.SIGNING_KEYSTORE_PASSWORD }} + signing_key_alias: ${{ secrets.SIGNING_KEY_ALIAS }} + signing_key_password: ${{ secrets.SIGNING_KEY_PASSWORD }} + secret_properties_file: ${{ inputs.SECRET_PROPERTIES_FILE }} + secret_properties: ${{ secrets.SECRET_PROPERTIES }} From 2799ad8b3b875178c3190f6a7c82a09fea7da59f Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Tue, 23 Sep 2025 14:45:19 +0200 Subject: [PATCH 16/34] docs(README): add new Android workflows Added entries for nightly build and baseline profile generation workflows. --- README.md | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 1eb3ae4..ad8498e 100644 --- a/README.md +++ b/README.md @@ -23,23 +23,25 @@ All the available reusable workflows are listed in the following table. ### Available workflows -| Platform | Runner | Action | File | Description | -|:---------------|:------------|:--------------------------|:-----------------------------------------------------------------------------------------------------------------------|:-------------------------------------------------------------------------------------| -| Universal | Cloud | Backup | [`universal-cloud-backup`](.github/workflows/universal-cloud-backup.yml) | Backups currently checked out ref to a remote repository. | -| Universal | Self-hosted | Backup | [`universal-selfhosted-backup`](.github/workflows/universal-selfhosted-backup.yml) | Backups currently checked out ref to a remote repository. | -| iOS | Self-hosted | Test | [`ios-selfhosted-test`](.github/workflows/ios-selfhosted-test.yml) | Lints and tests the PR. | -| iOS | Self-hosted | Build | [`ios-selfhosted-build`](.github/workflows/ios-selfhosted-build.yml) | Creates enterprise release build and submits the build to Futured App Store Connect. | -| iOS | Self-hosted | Release | [`ios-selfhosted-release`](.github/workflows/ios-selfhosted-release.yml) | Creates release build and submits it to App Store Connect. | -| iOS | Cloud | Test | [`ios-cloud-test`](.github/workflows/ios-cloud-test.yml) | Lints and tests the PR. | -| iOS | Cloud | Build | [`ios-cloud-build`](.github/workflows/ios-cloud-build.yml) | Creates enterprise release build and submits the build to App Center. | -| iOS | Cloud | Release | [`ios-cloud-release`](.github/workflows/ios-cloud-release.yml) | Creates release build and submits it to App Store Connect. | -| iOS (KMP) | Self-hosted | Test | [`ios-kmp-selfhosted-test`](.github/workflows/ios-kmp-selfhosted-test.yml) | Lints and tests the PR. | -| iOS (KMP) | Self-hosted | Build | [`ios-kmp-selfhosted-build`](.github/workflows/ios-kmp-selfhosted-build.yml) | Creates enterprise release build and submits the build to Futured App Store Connect. | -| iOS (KMP) | Self-hosted | Release | [`ios-kmp-selfhosted-release`](.github/workflows/ios-kmp-selfhosted-release.yml) | Creates release build and submits it to App Store Connect. | -| Android (+KMP) | Cloud | Tests & Lint checks | [`android-cloud-check`](.github/workflows/android-cloud-check.yml) | Runs unit tests and lint checks on pull request. | -| Android (+KMP) | Cloud | Firebase Snapshot Release | [`android-cloud-release-firebaseAppDistribution`](.github/workflows/android-cloud-release-firebaseAppDistribution.yml) | Publishes QA Snapshot build to Firebase App Distribution. | -| Android (+KMP) | Cloud | Google Play Release | [`android-cloud-release-googlePlay`](.github/workflows/android-cloud-release-googlePlay.yml) | Publishes release build to Google Play. | -| KMP | Cloud | Detect Changes | [`kmp-cloud-detect-changes`](.github/workflows/kmp-cloud-detect-changes.yml) | Detects changed sources in KMP projects for conditional job execution. | +| Platform | Runner | Action | File | Description | +|:---------------|:------------|:----------------------------|:-----------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------| +| Universal | Cloud | Backup | [`universal-cloud-backup`](.github/workflows/universal-cloud-backup.yml) | Backups currently checked out ref to a remote repository. | +| Universal | Self-hosted | Backup | [`universal-selfhosted-backup`](.github/workflows/universal-selfhosted-backup.yml) | Backups currently checked out ref to a remote repository. | +| iOS | Self-hosted | Test | [`ios-selfhosted-test`](.github/workflows/ios-selfhosted-test.yml) | Lints and tests the PR. | +| iOS | Self-hosted | Build | [`ios-selfhosted-build`](.github/workflows/ios-selfhosted-build.yml) | Creates enterprise release build and submits the build to Futured App Store Connect. | +| iOS | Self-hosted | Release | [`ios-selfhosted-release`](.github/workflows/ios-selfhosted-release.yml) | Creates release build and submits it to App Store Connect. | +| iOS | Cloud | Test | [`ios-cloud-test`](.github/workflows/ios-cloud-test.yml) | Lints and tests the PR. | +| iOS | Cloud | Build | [`ios-cloud-build`](.github/workflows/ios-cloud-build.yml) | Creates enterprise release build and submits the build to App Center. | +| iOS | Cloud | Release | [`ios-cloud-release`](.github/workflows/ios-cloud-release.yml) | Creates release build and submits it to App Store Connect. | +| iOS (KMP) | Self-hosted | Test | [`ios-kmp-selfhosted-test`](.github/workflows/ios-kmp-selfhosted-test.yml) | Lints and tests the PR. | +| iOS (KMP) | Self-hosted | Build | [`ios-kmp-selfhosted-build`](.github/workflows/ios-kmp-selfhosted-build.yml) | Creates enterprise release build and submits the build to Futured App Store Connect. | +| iOS (KMP) | Self-hosted | Release | [`ios-kmp-selfhosted-release`](.github/workflows/ios-kmp-selfhosted-release.yml) | Creates release build and submits it to App Store Connect. | +| Android (+KMP) | Cloud | Tests & Lint checks | [`android-cloud-check`](.github/workflows/android-cloud-check.yml) | Runs unit tests and lint checks on pull request. | +| Android (+KMP) | Cloud | Firebase Snapshot Release | [`android-cloud-release-firebaseAppDistribution`](.github/workflows/android-cloud-release-firebaseAppDistribution.yml) | Publishes QA Snapshot build to Firebase App Distribution. | +| Android (+KMP) | Cloud | Google Play Release | [`android-cloud-release-googlePlay`](.github/workflows/android-cloud-release-googlePlay.yml) | Publishes release build to Google Play. | +| Android | Cloud | Nightly Build | [`android-cloud-nightly-build`](.github/workflows/android-cloud-nightly-build.yml) | Automated nightly builds with Firebase App Distribution deployment. | +| Android (+KMP) | Cloud | Generate Baseline Profiles | [`android-cloud-generate-baseline-profiles`](.github/workflows/android-cloud-generate-baseline-profiles.yml) | Generates baseline profiles and creates PR with changes. | +| KMP | Cloud | Detect Changes | [`kmp-cloud-detect-changes`](.github/workflows/kmp-cloud-detect-changes.yml) | Detects changed sources in KMP projects for conditional job execution. | ## Contributors From eae0553770bf92858a2f58eb9f94dc712a7ef7a5 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Wed, 24 Sep 2025 11:45:26 +0200 Subject: [PATCH 17/34] refactor(ci): Pass build number, version name and signing secrets as Gradle properties Updated Firebase and Google Play build workflows to pass build variables as Gradle properties. This resolves an issue with sticky build variables when using configuration cache. --- .github/actions/android-build-firebase/action.yml | 12 ++++++++---- .github/actions/android-build-googlePlay/action.yml | 13 ++++++++----- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/.github/actions/android-build-firebase/action.yml b/.github/actions/android-build-firebase/action.yml index 0e4e2c0..c86d2e7 100644 --- a/.github/actions/android-build-firebase/action.yml +++ b/.github/actions/android-build-firebase/action.yml @@ -52,12 +52,12 @@ runs: { echo "ANDROID_BUILD_NUMBER=$((GITHUB_RUN_NUMBER + ${{ inputs.build_number_offset}} ))"; echo "KMP_FLAVOR=${{ inputs.kmp_flavor }}" - } >> "$GITHUB_ENV" - + # Set ANDROID_VERSION_NAME only if VERSION_NAME is provided if [[ -n "${{ inputs.version_name }}" ]]; then - echo "ANDROID_VERSION_NAME=${{ inputs.version_name }}" >> "$GITHUB_ENV" + echo "ANDROID_VERSION_NAME=${{ inputs.version_name }}" fi + } >> "$GITHUB_ENV" echo '${{ inputs.secret_properties }}' > ${{ inputs.secret_properties_file }} - name: Run Unit tests @@ -67,7 +67,11 @@ runs: id: build_apk shell: bash run: | - ./gradlew ${{ inputs.package_gradle_task }} -P buildkonfig.flavor="$KMP_FLAVOR" + ./gradlew ${{ inputs.package_gradle_task }} \ + -P android.build_number="$ANDROID_BUILD_NUMBER" \ + -P android.version_name="$ANDROID_VERSION_NAME" \ + -P buildkonfig.flavor="$KMP_FLAVOR" + APK_FILE=$(find . -name '*.apk' | grep -v -e '.*intermediate' -e '.*baseline') echo "universal_apk_file=$APK_FILE" >> "$GITHUB_OUTPUT" - name: Upload artifact diff --git a/.github/actions/android-build-googlePlay/action.yml b/.github/actions/android-build-googlePlay/action.yml index dfed8da..39cbdb9 100644 --- a/.github/actions/android-build-googlePlay/action.yml +++ b/.github/actions/android-build-googlePlay/action.yml @@ -65,12 +65,15 @@ runs: - name: Generate Artifacts (AAB) id: build_aab shell: bash - env: - ANDROID_KEYSTORE_PASSWORD: ${{ inputs.signing_keystore_password }} - ANDROID_KEY_ALIAS: ${{ inputs.signing_key_alias }} - ANDROID_KEY_PASSWORD: ${{ inputs.signing_key_password }} run: | - ./gradlew ${{ inputs.bundle_gradle_task }} -P buildkonfig.flavor="$KMP_FLAVOR" + ./gradlew ${{ inputs.bundle_gradle_task }} \ + -P android.build_number="$ANDROID_BUILD_NUMBER" \ + -P android.version_name="$ANDROID_VERSION_NAME" \ + -P buildkonfig.flavor="$KMP_FLAVOR" \ + -P android.signing.keystore.password="${{ inputs.signing_keystore_password }}" \ + -P android.signing.key.alias="${{ inputs.signing_key_alias }}" \ + -P android.signing.key.password="${{ inputs.signing_key_password }}" + BUNDLE_FILE=$(find . -name '*.aab' | grep -v -e '.*intermediate' -e '.*baseline') MAPPING_FILE=$(find . -name mapping.txt) From cd6d43a72537d4d5f73bac975360b50969979377 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Wed, 24 Sep 2025 12:54:28 +0200 Subject: [PATCH 18/34] refactor(ci): Update Android workflows to use `feature/android-refactor` actions Replaced references to `feature/matsem/changelog-android` with `feature/android-refactor` across workflows for consistency and improved maintainability. --- .github/workflows/android-cloud-check.yml | 4 ++-- .../workflows/android-cloud-generate-baseline-profiles.yml | 4 ++-- .github/workflows/android-cloud-nightly-build.yml | 6 +++--- .../android-cloud-release-firebaseAppDistribution.yml | 4 ++-- .github/workflows/android-cloud-release-googlePlay.yml | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/android-cloud-check.yml b/.github/workflows/android-cloud-check.yml index 50e5141..719c8f5 100644 --- a/.github/workflows/android-cloud-check.yml +++ b/.github/workflows/android-cloud-check.yml @@ -59,14 +59,14 @@ jobs: lfs: ${{ inputs.USE_GIT_LFS }} - name: Set up environment # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-setup-environment@feature/matsem/changelog-android + uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor with: java_version: ${{ inputs.JAVA_VERSION }} java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - name: Run checks # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-check@feature/matsem/changelog-android + uses: futuredapp/.github/.github/actions/android-check@feature/android-refactor with: lint_gradle_task: ${{ inputs.LINT_GRADLE_TASKS }} test_gradle_task: ${{ inputs.TEST_GRADLE_TASKS }} diff --git a/.github/workflows/android-cloud-generate-baseline-profiles.yml b/.github/workflows/android-cloud-generate-baseline-profiles.yml index 4ee78b3..8cedd47 100644 --- a/.github/workflows/android-cloud-generate-baseline-profiles.yml +++ b/.github/workflows/android-cloud-generate-baseline-profiles.yml @@ -76,14 +76,14 @@ jobs: lfs: ${{ inputs.USE_GIT_LFS }} - name: Set up environment # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-setup-environment@feature/matsem/changelog-android + uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor with: java_version: ${{ inputs.JAVA_VERSION }} java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - name: Generate baseline profiles # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-generate-baseline-profiles@feature/matsem/changelog-android + uses: futuredapp/.github/.github/actions/android-generate-baseline-profiles@feature/android-refactor with: generate_gradle_task: ${{ inputs.TASK_NAME }} signing_keystore_password: ${{ secrets.SIGNING_KEYSTORE_PASSWORD }} diff --git a/.github/workflows/android-cloud-nightly-build.yml b/.github/workflows/android-cloud-nightly-build.yml index 70844b9..249ccab 100644 --- a/.github/workflows/android-cloud-nightly-build.yml +++ b/.github/workflows/android-cloud-nightly-build.yml @@ -105,7 +105,7 @@ jobs: - name: Detect changes and generate changelog id: detect_changes # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/universal-detect-changes-and-generate-changelog@feature/matsem/changelog-android + uses: futuredapp/.github/.github/actions/universal-detect-changes-and-generate-changelog@feature/android-refactor with: checkout_depth: ${{ inputs.CHANGELOG_CHECKOUT_DEPTH }} debug: ${{ inputs.CHANGELOG_DEBUG }} @@ -125,14 +125,14 @@ jobs: lfs: ${{ inputs.USE_GIT_LFS }} - name: Set up environment # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-setup-environment@feature/matsem/changelog-android + uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor with: java_version: ${{ inputs.JAVA_VERSION }} java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - name: Build and upload to App Distribution # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-build-firebase@feature/matsem/changelog-android + uses: futuredapp/.github/.github/actions/android-build-firebase@feature/android-refactor with: test_gradle_task: ${{ inputs.TEST_GRADLE_TASKS }} package_gradle_task: ${{ inputs.PACKAGE_GRADLE_TASK }} diff --git a/.github/workflows/android-cloud-release-firebaseAppDistribution.yml b/.github/workflows/android-cloud-release-firebaseAppDistribution.yml index 452a1f9..09fbac3 100644 --- a/.github/workflows/android-cloud-release-firebaseAppDistribution.yml +++ b/.github/workflows/android-cloud-release-firebaseAppDistribution.yml @@ -97,14 +97,14 @@ jobs: lfs: ${{ inputs.USE_GIT_LFS }} - name: Set up environment # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-setup-environment@feature/matsem/changelog-android + uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor with: java_version: ${{ inputs.JAVA_VERSION }} java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - name: Build and upload to App Distribution # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-build-firebase@feature/matsem/changelog-android + uses: futuredapp/.github/.github/actions/android-build-firebase@feature/android-refactor with: test_gradle_task: ${{ inputs.TEST_GRADLE_TASKS }} package_gradle_task: ${{ inputs.PACKAGE_GRADLE_TASK }} diff --git a/.github/workflows/android-cloud-release-googlePlay.yml b/.github/workflows/android-cloud-release-googlePlay.yml index c85d3eb..194261a 100644 --- a/.github/workflows/android-cloud-release-googlePlay.yml +++ b/.github/workflows/android-cloud-release-googlePlay.yml @@ -103,13 +103,13 @@ jobs: lfs: ${{ inputs.USE_GIT_LFS }} - name: Set up environment # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-setup-environment@feature/matsem/changelog-android + uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor with: java_version: ${{ inputs.JAVA_VERSION }} java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} - name: Build and release # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-build-googlePlay@feature/matsem/changelog-android + uses: futuredapp/.github/.github/actions/android-build-googlePlay@feature/android-refactor with: bundle_gradle_task: ${{ inputs.BUNDLE_GRADLE_TASK }} version_name: ${{ inputs.VERSION_NAME }} From 500471e9046f5159f9049f4906629b8c2ca16081 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Wed, 24 Sep 2025 15:35:08 +0200 Subject: [PATCH 19/34] Revert "refactor(ci): Pass build number, version name and signing secrets as Gradle properties" This reverts commit eae0553770bf92858a2f58eb9f94dc712a7ef7a5. --- .github/actions/android-build-firebase/action.yml | 12 ++++-------- .github/actions/android-build-googlePlay/action.yml | 13 +++++-------- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/.github/actions/android-build-firebase/action.yml b/.github/actions/android-build-firebase/action.yml index c86d2e7..0e4e2c0 100644 --- a/.github/actions/android-build-firebase/action.yml +++ b/.github/actions/android-build-firebase/action.yml @@ -52,12 +52,12 @@ runs: { echo "ANDROID_BUILD_NUMBER=$((GITHUB_RUN_NUMBER + ${{ inputs.build_number_offset}} ))"; echo "KMP_FLAVOR=${{ inputs.kmp_flavor }}" - + } >> "$GITHUB_ENV" + # Set ANDROID_VERSION_NAME only if VERSION_NAME is provided if [[ -n "${{ inputs.version_name }}" ]]; then - echo "ANDROID_VERSION_NAME=${{ inputs.version_name }}" + echo "ANDROID_VERSION_NAME=${{ inputs.version_name }}" >> "$GITHUB_ENV" fi - } >> "$GITHUB_ENV" echo '${{ inputs.secret_properties }}' > ${{ inputs.secret_properties_file }} - name: Run Unit tests @@ -67,11 +67,7 @@ runs: id: build_apk shell: bash run: | - ./gradlew ${{ inputs.package_gradle_task }} \ - -P android.build_number="$ANDROID_BUILD_NUMBER" \ - -P android.version_name="$ANDROID_VERSION_NAME" \ - -P buildkonfig.flavor="$KMP_FLAVOR" - + ./gradlew ${{ inputs.package_gradle_task }} -P buildkonfig.flavor="$KMP_FLAVOR" APK_FILE=$(find . -name '*.apk' | grep -v -e '.*intermediate' -e '.*baseline') echo "universal_apk_file=$APK_FILE" >> "$GITHUB_OUTPUT" - name: Upload artifact diff --git a/.github/actions/android-build-googlePlay/action.yml b/.github/actions/android-build-googlePlay/action.yml index 39cbdb9..dfed8da 100644 --- a/.github/actions/android-build-googlePlay/action.yml +++ b/.github/actions/android-build-googlePlay/action.yml @@ -65,15 +65,12 @@ runs: - name: Generate Artifacts (AAB) id: build_aab shell: bash + env: + ANDROID_KEYSTORE_PASSWORD: ${{ inputs.signing_keystore_password }} + ANDROID_KEY_ALIAS: ${{ inputs.signing_key_alias }} + ANDROID_KEY_PASSWORD: ${{ inputs.signing_key_password }} run: | - ./gradlew ${{ inputs.bundle_gradle_task }} \ - -P android.build_number="$ANDROID_BUILD_NUMBER" \ - -P android.version_name="$ANDROID_VERSION_NAME" \ - -P buildkonfig.flavor="$KMP_FLAVOR" \ - -P android.signing.keystore.password="${{ inputs.signing_keystore_password }}" \ - -P android.signing.key.alias="${{ inputs.signing_key_alias }}" \ - -P android.signing.key.password="${{ inputs.signing_key_password }}" - + ./gradlew ${{ inputs.bundle_gradle_task }} -P buildkonfig.flavor="$KMP_FLAVOR" BUNDLE_FILE=$(find . -name '*.aab' | grep -v -e '.*intermediate' -e '.*baseline') MAPPING_FILE=$(find . -name mapping.txt) From 44166514a97bd1079b9c9a5e331fa65c7924ea5c Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Thu, 25 Sep 2025 13:56:40 +0200 Subject: [PATCH 20/34] refactor(ci): Add reusable iOS KMP build action and update TestFlight workflow Introduced a new `ios-build` reusable action to streamline iOS builds and uploads to TestFlight. Updated `ios-kmp-selfhosted-build.yml` to integrate the new action and added a nightly build workflow for improved automation. --- .github/actions/ios-build/action.yml | 85 +++++++++++++++++++ .../workflows/ios-kmp-selfhosted-build.yml | 71 ++++++---------- .github/workflows/kmp-nightly-build.yml | 0 3 files changed, 111 insertions(+), 45 deletions(-) create mode 100644 .github/actions/ios-build/action.yml create mode 100644 .github/workflows/kmp-nightly-build.yml diff --git a/.github/actions/ios-build/action.yml b/.github/actions/ios-build/action.yml new file mode 100644 index 0000000..f08f941 --- /dev/null +++ b/.github/actions/ios-build/action.yml @@ -0,0 +1,85 @@ +name: iOS KMP Build +description: Builds iOS app (optionally with KMP framework) and uploads to TestFlight + +inputs: + # Required + match_password: + description: "Password for decrypting of certificates and provisioning profiles." + required: true + app_store_connect_api_key_key: + description: "Private App Store Connect API key for submitting build to App Store." + required: true + app_store_connect_api_key_key_id: + required: true + description: "Private App Store Connect API key for submitting build to App Store." + app_store_connect_api_key_issuer_id: + required: true + description: "Private App Store Connect API issuer key for submitting build to App Store." + testflight_changelog: + required: true + description: "Will be used as TestFlight changelog" + # Optional + secret_xcconfig_path: + description: "Path to the .xcconfig file. Selected secret properties will be appended to the end of this file." + required: false + secret_properties: + required: false + description: "Secrets in the format KEY = VALUE (one per line)." + secret_required_keys: + description: "Comma-separated list of required secret keys." + required: false + kmp_swift_package_integration: + description: "Whether KMP is integrated in Xcode project as a Swift Package" + required: false + kmp_swift_package_path: + description: "If `kmp_swift_package_integration` is 'true', then specifies a location of local Swift Package with Makefile. Example: 'iosApp/shared/KMP`" + required: false + kmp_swift_package_flavor: + description: "If `kmp_swift_package_integration`, specifies build flavor of KMP Package" + required: false + custom_values: + description: "Custom string that can contains values specified in your workflow file. Those values will be placed into environment variable. Example: \"CUSTOM-1: 1; CUSTOM-2: 2\"" + required: false +runs: + using: "composite" + steps: + - name: Export secrets to .xcconfig file + if: ${{ inputs.secret_xcconfig_path != '' }} + uses: futuredapp/.github/.github/actions/ios-export-secrets@main + with: + XCCONFIG_PATH: ${{ inputs.secret_xcconfig_path }} + SECRET_PROPERTIES: ${{ inputs.secret_properties }} + REQUIRED_KEYS: ${{ inputs.secret_required_keys }} + - name: Build KMP Package + if: ${{ inputs.kmp_swift_package_integration }} + env: + KMP_BUILD_FLAVOR: ${{ inputs.kmp_swift_package_flavor }} + KMP_FRAMEWORK_BUILD_TYPE: release + shell: bash + run: | + cd ${{ inputs.kmp_swift_package_path }} + make build + - name: Fastlane Beta + working-directory: iosApp + shell: bash + run: | + gem install bundler + bundle install --jobs 4 --retry 3 + bundle exec fastlane beta + env: + MATCH_PASSWORD: ${{ inputs.match_password }} + PR_TITLE: ${{ inputs.testflight_changelog }} + APP_STORE_CONNECT_API_KEY_KEY: ${{ inputs.app_store_connect_api_key_key }} + APP_STORE_CONNECT_API_KEY_KEY_ID: ${{ inputs.app_store_connect_api_key_key_id }} + APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ inputs.app_store_connect_api_key_issuer_id }} + CUSTOM_VALUES: ${{ inputs.custom_values }} + - name: Upload IPA + uses: actions/upload-artifact@v4 + with: + name: Build.ipa + path: build_output/*.ipa + - name: Upload dSYM + uses: actions/upload-artifact@v4 + with: + name: Build.app.dSYM.zip + path: build_output/*.app.dSYM.zip diff --git a/.github/workflows/ios-kmp-selfhosted-build.yml b/.github/workflows/ios-kmp-selfhosted-build.yml index d501e28..75a24b9 100644 --- a/.github/workflows/ios-kmp-selfhosted-build.yml +++ b/.github/workflows/ios-kmp-selfhosted-build.yml @@ -52,6 +52,11 @@ on: type: string required: false default: "" + changelog: + description: "Will be used as TestFlight changelog" + type: string + required: false + default: ${{ github.event.pull_request.title }} secrets: MATCH_PASSWORD: @@ -87,50 +92,26 @@ jobs: uses: actions/checkout@v4 with: lfs: ${{ inputs.use_git_lfs }} - - name: Export secrets to .xcconfig file - if: ${{ inputs.xcconfig_path != '' }} - uses: futuredapp/.github/.github/actions/ios-export-secrets@main - with: - XCCONFIG_PATH: ${{ inputs.xcconfig_path }} - SECRET_PROPERTIES: ${{ secrets.SECRET_PROPERTIES }} - REQUIRED_KEYS: ${{ inputs.required_keys }} - - name: Setup Java - uses: actions/setup-java@v4 - with: - java-version: ${{ inputs.java_version }} - distribution: ${{ inputs.java_distribution }} - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - with: - cache-encryption-key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - - name: Build KMP Package - if: ${{ inputs.kmp_swift_package_integration }} - env: - KMP_BUILD_FLAVOR: ${{ inputs.kmp_swift_package_flavor }} - KMP_FRAMEWORK_BUILD_TYPE: release - run: | - cd ${{ inputs.kmp_swift_package_path }} - make build - - name: Fastlane Beta - working-directory: iosApp - run: | - gem install bundler - bundle install --jobs 4 --retry 3 - bundle exec fastlane beta - env: - MATCH_PASSWORD: ${{ secrets.MATCH_PASSWORD }} - PR_TITLE: ${{ github.event.pull_request.title }} - APP_STORE_CONNECT_API_KEY_KEY: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY }} - APP_STORE_CONNECT_API_KEY_KEY_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }} - APP_STORE_CONNECT_API_KEY_ISSUER_ID: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }} - CUSTOM_VALUES: ${{ inputs.custom_values }} - - name: Upload IPA - uses: actions/upload-artifact@v4 + - name: Set up environment + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor with: - name: Build.ipa - path: build_output/*.ipa - - name: Upload dSYM - uses: actions/upload-artifact@v4 + java_version: ${{ inputs.java_version }} + java_distribution: ${{ inputs.java_distribution }} + gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} + - name: Build and upload to TestFlight + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/ios-build@feature/android-refactor with: - name: Build.app.dSYM.zip - path: build_output/*.app.dSYM.zip + match_password: ${{ secrets.MATCH_PASSWORD }} + app_store_connect_api_key_key: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY }} + app_store_connect_api_key_key_id: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY_ID }} + app_store_connect_api_key_issuer_id: ${{ secrets.APP_STORE_CONNECT_API_KEY_ISSUER_ID }} + testflight_changelog: ${{ inputs.changelog }} + secret_xcconfig_path: ${{ inputs.xcconfig_path }} + secret_properties: ${{ secrets.SECRET_PROPERTIES }} + secret_required_keys: ${{ inputs.required_keys }} + kmp_swift_package_integration: ${{ inputs.kmp_swift_package_integration }} + kmp_swift_package_path: ${{ inputs.kmp_swift_package_path }} + kmp_swift_package_flavor: ${{ inputs.kmp_swift_package_flavor }} + custom_values: ${{ inputs.custom_values }} diff --git a/.github/workflows/kmp-nightly-build.yml b/.github/workflows/kmp-nightly-build.yml new file mode 100644 index 0000000..e69de29 From 9a14525a5fe855378a01f37bcf5f31bc96169817 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Thu, 25 Sep 2025 14:46:25 +0200 Subject: [PATCH 21/34] refactor(ci): Add optional setup toggles for Java, Ruby, and Gradle in Android CI action Introduced inputs to enable or disable the setup of Java, Ruby, and Gradle independently in `.github/actions/android-setup-environment`. Updated steps to conditionally execute based on these inputs for enhanced flexibility. --- .../android-setup-environment/action.yml | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/.github/actions/android-setup-environment/action.yml b/.github/actions/android-setup-environment/action.yml index 8cdbc8a..ae04a82 100644 --- a/.github/actions/android-setup-environment/action.yml +++ b/.github/actions/android-setup-environment/action.yml @@ -2,38 +2,53 @@ name: Set up Android environment description: Sets up Java, Gradle and Ruby and other preconditions for CI runs at Futured Android workflows. inputs: - # Required inputs + # Java + java: + description: "Whether to set up Java" + required: false + default: 'true' java_version: description: "Java version to use, eg. '17'." - required: true + required: false default: '17' java_distribution: description: "Java distribution to use, eg 'zulu'." - required: true + required: false default: 'zulu' - - # Optional inputs - gradle_cache_encryption_key: - description: "Configuration cache encryption key. Leave empty if you don't need cache." + # Ruby + ruby: + description: "Whether to set up Ruby" required: false + default: 'true' ruby_version: description: "Ruby version." required: false default: '3.4' + # Gradle + gradle: + description: "Whether to set up Gradle" + required: false + default: 'true' + gradle_cache_encryption_key: + description: "Configuration cache encryption key. Leave empty if you don't need cache." + required: false runs: using: "composite" steps: - name: Setup Ruby + if: ${{ inputs.ruby == 'true' }} uses: ruby/setup-ruby@v1 with: ruby-version: ${{ inputs.ruby_version }} - name: Setup Java + if: ${{ inputs.java == 'true' }} uses: actions/setup-java@v4 with: java-version: ${{ inputs.java_version }} distribution: ${{ inputs.java_distribution }} - name: Setup Gradle + if: ${{ inputs.gradle == 'true' }} uses: gradle/actions/setup-gradle@v4 with: cache-encryption-key: ${{ inputs.gradle_cache_encryption_key }} From accc38dfd67b0fa3266d69507eb038f5ae6d6eb1 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Thu, 25 Sep 2025 14:48:00 +0200 Subject: [PATCH 22/34] Disable Ruby setup for ios-kmp-selfhosted-build.yml Ruby is already installed on runner --- .github/workflows/ios-kmp-selfhosted-build.yml | 1 + .github/workflows/kmp-nightly-build.yml | 0 2 files changed, 1 insertion(+) delete mode 100644 .github/workflows/kmp-nightly-build.yml diff --git a/.github/workflows/ios-kmp-selfhosted-build.yml b/.github/workflows/ios-kmp-selfhosted-build.yml index 75a24b9..aff5c67 100644 --- a/.github/workflows/ios-kmp-selfhosted-build.yml +++ b/.github/workflows/ios-kmp-selfhosted-build.yml @@ -99,6 +99,7 @@ jobs: java_version: ${{ inputs.java_version }} java_distribution: ${{ inputs.java_distribution }} gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} + ruby: 'false' - name: Build and upload to TestFlight # TODO update branch ref to main, reject pull request if you see this uses: futuredapp/.github/.github/actions/ios-build@feature/android-refactor diff --git a/.github/workflows/kmp-nightly-build.yml b/.github/workflows/kmp-nightly-build.yml deleted file mode 100644 index e69de29..0000000 From b58ec4b681938093f19268179b4966858914a6d3 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Thu, 25 Sep 2025 16:07:55 +0200 Subject: [PATCH 23/34] feat(ci): Add KMP combined nightly build workflow This workflow automates nightly builds for KMP projects, including Android and iOS, changelog generation, and build caching. --- .github/actions/ios-build/action.yml | 7 +- .../workflows/kmp-combined-nightly-build.yml | 248 ++++++++++++++++++ 2 files changed, 252 insertions(+), 3 deletions(-) create mode 100644 .github/workflows/kmp-combined-nightly-build.yml diff --git a/.github/actions/ios-build/action.yml b/.github/actions/ios-build/action.yml index f08f941..d556454 100644 --- a/.github/actions/ios-build/action.yml +++ b/.github/actions/ios-build/action.yml @@ -15,9 +15,6 @@ inputs: app_store_connect_api_key_issuer_id: required: true description: "Private App Store Connect API issuer key for submitting build to App Store." - testflight_changelog: - required: true - description: "Will be used as TestFlight changelog" # Optional secret_xcconfig_path: description: "Path to the .xcconfig file. Selected secret properties will be appended to the end of this file." @@ -40,6 +37,10 @@ inputs: custom_values: description: "Custom string that can contains values specified in your workflow file. Those values will be placed into environment variable. Example: \"CUSTOM-1: 1; CUSTOM-2: 2\"" required: false + testflight_changelog: + required: false + description: "Will be used as TestFlight changelog" + runs: using: "composite" steps: diff --git a/.github/workflows/kmp-combined-nightly-build.yml b/.github/workflows/kmp-combined-nightly-build.yml new file mode 100644 index 0000000..1f340a6 --- /dev/null +++ b/.github/workflows/kmp-combined-nightly-build.yml @@ -0,0 +1,248 @@ +name: KMP nightly build + +on: + workflow_call: + inputs: + ## Required Inputs + android_test_gradle_task: + description: "A Gradle task(s) for executing unit tests, for example `testReleaseUnitTest` or `testDevEnterpriseUnitTest`" + required: true + type: string + android_package_gradle_task: + description: "A Gradle task for packaging universal APK, eg. 'packageEnterpriseUniversalApk'" + required: true + type: string + android_upload_gradle_task: + description: "A Gradle task for uploading APK, for example `appDistributionUploadEnterprise`" + required: true + type: string + kmp_flavor: + description: "KMP Build flavor. This is optional and only required by KMP projects and can be ignored on pure Android projects" + required: true + type: string + default: 'test' + firebase_app_distribution_groups: + description: "Comma-separated list of app distribution group IDs" + required: true + type: string + + ## Optional Inputs + timeout_minutes: + description: "Job timeout in minutes" + required: false + type: number + default: 30 + use_git_lfs: + description: "Whether to download Git-LFS files" + type: boolean + required: false + default: false + gradle_opts: + description: "Gradle options" + required: false + type: string + default: "" + java_version: + description: "Java version to use" + required: false + type: string + default: '17' + java_distribution: + description: "Java distribution to use" + required: false + type: string + default: 'zulu' + android_version_name: + description: "Version name. Example: '1.X.X-snapshot'" + required: false + type: string + android_build_number_offset: + description: "Build number offset. This number will be added to GITHUB_RUN_NUMBER and can be used to make corrections to build numbers." + required: false + type: number + default: 0 + kmp_swift_package_integration: + description: "Whether KMP is integrated in Xcode project as a Swift Package" + required: false + type: boolean + default: false + kmp_swift_package_path: + description: "If `kmp_swift_package_integration` is 'true', then specifies a location of local Swift Package with Makefile. Example: 'iosApp/shared/KMP`" + required: false + type: string + android_secret_properties_file: + description: "A path to file that will be populated with contents of 'android_secret_properties' secret. This file can be picked up by Secrets Gradle plugin to embed secrets into BuildConfig." + required: false + type: string + default: secrets.properties + changelog_debug: + description: "Enable debug mode for changelog generation. Default is false." + type: boolean + required: false + default: false + changelog_checkout_depth: + description: "The depth of the git history to fetch for changelog generation. Default is 100." + type: number + required: false + default: 100 + changelog_fallback_lookback: + description: "The amount of time to look back for merge commits when no previous build commit is found. Default is 24 hours." + type: string + required: false + default: "24 hours" + ios_secret_xcconfig_path: + description: "Path to the .xcconfig file. Selected secret properties will be appended to the end of this file." + type: string + required: false + ios_secret_properties: + required: false + type: string + description: "Secrets in the format KEY = VALUE (one per line)." + ios_secret_required_keys: + description: "Comma-separated list of required secret keys." + type: string + required: false + ios_custom_values: + description: "Custom string that can contains values specified in your workflow file. Those values will be placed into environment variable. Example: \"CUSTOM-1: 1; CUSTOM-2: 2\"" + required: false + type: string + + secrets: + firebase_app_distribution_service_account: + required: true + description: "JSON key of service account with permissions to upload build to Firebase App Distribution" + gradle_cache_encryption_key: + required: false + description: "Configuration cache encryption key" + android_secret_properties: + required: false + description: "Custom string that contains key-value properties as secrets. Contents of this secret will be placed into file specified by 'android_secret_properties_file' input." + ios_match_password: + description: "Password for decrypting of certificates and provisioning profiles." + required: true + ios_app_store_connect_api_key_key: + description: "Private App Store Connect API key for submitting build to App Store." + required: true + ios_app_store_connect_api_key_key_id: + required: true + description: "Private App Store Connect API key for submitting build to App Store." + ios_app_store_connect_api_key_issuer_id: + required: true + description: "Private App Store Connect API issuer key for submitting build to App Store." + +jobs: + + changelog: + outputs: + skip_build: ${{ steps.detect_changes.outputs.skip_build }} + changelog: ${{ steps.detect_changes.outputs.changelog }} + cache_key: ${{ steps.detect_changes.outputs.cache_key }} + name: Detect changes and generate changelog + runs-on: ubuntu-latest + steps: + - name: Detect changes and generate changelog + id: detect_changes + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/universal-detect-changes-and-generate-changelog@feature/android-refactor + with: + checkout_depth: ${{ inputs.changelog_checkout_depth }} + debug: ${{ inputs.changelog_debug }} + fallback_lookback: ${{ inputs.changelog_fallback_lookback }} + + ios_build: + name: iOS Build + runs-on: self-hosted + needs: changelog + if: ${{ needs.changelog.outputs.skip_build != 'true' }} + timeout-minutes: ${{ inputs.timeout_minutes }} + env: + GRADLE_OPTS: ${{ inputs.gradle_opts }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + lfs: ${{ inputs.use_git_lfs }} + - name: Set up environment + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor + with: + java_version: ${{ inputs.java_version }} + java_distribution: ${{ inputs.java_distribution }} + gradle_cache_encryption_key: ${{ secrets.gradle_cache_encryption_key }} + ruby: 'false' + - name: Build and upload to TestFlight + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/ios-build@feature/android-refactor + with: + match_password: ${{ secrets.ios_match_password }} + app_store_connect_api_key_key: ${{ secrets.ios_app_store_connect_api_key_key }} + app_store_connect_api_key_key_id: ${{ secrets.ios_app_store_connect_api_key_key_id }} + app_store_connect_api_key_issuer_id: ${{ secrets.ios_app_store_connect_api_key_issuer_id }} + secret_xcconfig_path: ${{ inputs.ios_secret_xcconfig_path }} + secret_properties: ${{ inputs.ios_secret_properties }} + secret_required_keys: ${{ inputs.ios_secret_required_keys }} + kmp_swift_package_integration: ${{ inputs.kmp_swift_package_integration }} + kmp_swift_package_path: ${{ inputs.kmp_swift_package_path }} + kmp_swift_package_flavor: ${{ inputs.kmp_flavor }} + custom_values: ${{ inputs.ios_custom_values }} + testflight_changelog: ${{ needs.changelog.outputs.changelog }} + + android_build: + name: Android Build + runs-on: ubuntu-latest + needs: changelog + if: ${{ needs.changelog.outputs.skip_build != 'true' }} + timeout-minutes: ${{ inputs.timeout_minutes }} + env: + GRADLE_OPTS: ${{ inputs.gradle_opts }} + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + lfs: ${{ inputs.use_git_lfs }} + - name: Set up environment + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor + with: + java_version: ${{ inputs.java_version }} + java_distribution: ${{ inputs.java_distribution }} + gradle_cache_encryption_key: ${{ secrets.gradle_cache_encryption_key }} + - name: Build and upload to App Distribution + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/android-build-firebase@feature/android-refactor + with: + test_gradle_task: ${{ inputs.android_test_gradle_task }} + package_gradle_task: ${{ inputs.android_package_gradle_task }} + upload_gradle_task: ${{ inputs.android_upload_gradle_task }} + app_distribution_groups: ${{ inputs.firebase_app_distribution_groups }} + app_distribution_service_account: ${{ secrets.firebase_app_distribution_service_account }} + version_name: ${{ inputs.android_version_name }} + build_number_offset: ${{ inputs.android_build_number_offset }} + release_notes: ${{ needs.changelog.outputs.changelog }} + kmp_flavor: ${{ inputs.kmp_flavor }} + secret_properties_file: ${{ inputs.android_secret_properties_file }} + secret_properties: ${{ secrets.android_secret_properties }} + + save_cache: + name: Cache last build commit SHA + runs-on: ubuntu-latest + needs: + - ios_build + - android_build + - changelog + steps: + - name: Save latest build commit SHA to file + if: success() && needs.changelog.outputs.skip_build != 'true' + shell: bash + run: | + echo "${{ github.sha }}" > latest_builded_commit.txt + if [ "${{ inputs.changelog_debug }}" == 'true' ]; then + echo "[DEBUG] Saved commit SHA ${{ github.sha }} to latest_builded_commit.txt" + fi + - name: Store latest build commit SHA in cache + if: success() && needs.changelog.outputs.skip_build != 'true' + uses: actions/cache/save@v4 + with: + path: latest_builded_commit.txt + key: ${{ needs.changelog.outputs.cache_key }} + From be8c542b38b591e56a91bd1f3b7de62635aafdc3 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Thu, 25 Sep 2025 16:08:18 +0200 Subject: [PATCH 24/34] docs: Enhance workflow documentation with dependency diagram Adds a new workflow to the table and introduces a Mermaid diagram to visualize workflow and action dependencies for better understanding. --- README.md | 111 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 110 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 195e66e..9b5a05f 100644 --- a/README.md +++ b/README.md @@ -25,12 +25,13 @@ All the available reusable workflows are listed in the following table. | Platform | Runner | Action | File | Description | |:---------------|:------------|:----------------------------|:-----------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------| +| Universal | Any | Workflows Lint | [`workflows-lint`](.github/workflows/workflows-lint.yml) | Lints GitHub workflow files for syntax and best practices. | | Universal | Cloud | Backup | [`universal-cloud-backup`](.github/workflows/universal-cloud-backup.yml) | Backups currently checked out ref to a remote repository. | | Universal | Self-hosted | Backup | [`universal-selfhosted-backup`](.github/workflows/universal-selfhosted-backup.yml) | Backups currently checked out ref to a remote repository. | | iOS | Self-hosted | Test | [`ios-selfhosted-test`](.github/workflows/ios-selfhosted-test.yml) | Lints and tests the PR. | | iOS | Self-hosted | Build | [`ios-selfhosted-build`](.github/workflows/ios-selfhosted-build.yml) | Creates enterprise release build and submits the build to Futured App Store Connect. | | iOS | Self-hosted | Release | [`ios-selfhosted-release`](.github/workflows/ios-selfhosted-release.yml) | Creates release build and submits it to App Store Connect. | -| iOS (KMP) | Self-hosted | Test | [`ios-kmp-selfhosted-test`](.github/workflows/ios-kmp-selfhosted-test.yml) | Lints and tests the PR. | +| iOS (KMP) | Self-hosted | Test | [`ios-kmp-selfhosted-test`](.github/workflows/ios-kmp-selfhosted-test.yml) | Lints and tests the PR. | | iOS (KMP) | Self-hosted | Build | [`ios-kmp-selfhosted-build`](.github/workflows/ios-kmp-selfhosted-build.yml) | Creates enterprise release build and submits the build to Futured App Store Connect. | | iOS (KMP) | Self-hosted | Release | [`ios-kmp-selfhosted-release`](.github/workflows/ios-kmp-selfhosted-release.yml) | Creates release build and submits it to App Store Connect. | | Android (+KMP) | Cloud | Tests & Lint checks | [`android-cloud-check`](.github/workflows/android-cloud-check.yml) | Runs unit tests and lint checks on pull request. | @@ -39,6 +40,114 @@ All the available reusable workflows are listed in the following table. | Android | Cloud | Nightly Build | [`android-cloud-nightly-build`](.github/workflows/android-cloud-nightly-build.yml) | Automated nightly builds with Firebase App Distribution deployment. | | Android (+KMP) | Cloud | Generate Baseline Profiles | [`android-cloud-generate-baseline-profiles`](.github/workflows/android-cloud-generate-baseline-profiles.yml) | Generates baseline profiles and creates PR with changes. | | KMP | Cloud | Detect Changes | [`kmp-cloud-detect-changes`](.github/workflows/kmp-cloud-detect-changes.yml) | Detects changed sources in KMP projects for conditional job execution. | +| KMP | Cloud | Combined Nightly Build | [`kmp-combined-nightly-build`](.github/workflows/kmp-combined-nightly-build.yml) | Automated nightly builds for both iOS and Android platforms in KMP projects. | + +## Workflow and Action Dependencies + +The following diagram shows the relationships between workflows and actions in this repository: + +```mermaid +graph TD + %% Workflow definitions + subgraph "Workflows" + WL[workflows-lint] + UCB[universal-cloud-backup] + USB[universal-selfhosted-backup] + IKST[ios-kmp-selfhosted-test] + IST[ios-selfhosted-test] + ACC[android-cloud-check] + ACGBP[android-cloud-generate-baseline-profiles] + ACNB[android-cloud-nightly-build] + ACRFAD[android-cloud-release-firebaseAppDistribution] + ACRGP[android-cloud-release-googlePlay] + KCDC[kmp-cloud-detect-changes] + IKSR[ios-kmp-selfhosted-release] + ISB[ios-selfhosted-build] + ISR[ios-selfhosted-release] + IKSB[ios-kmp-selfhosted-build] + KCNB[kmp-combined-nightly-build] + end + + %% Action definitions + subgraph "Actions" + ASE[android-setup-environment] + AC[android-check] + ABF[android-build-firebase] + ABGP[android-build-googlePlay] + AGBP[android-generate-baseline-profiles] + KDC[kmp-detect-changes] + UDCGC[universal-detect-changes-and-generate-changelog] + IES[ios-export-secrets] + IB[ios-build] + end + + %% Android workflow dependencies + ACC --> ASE + ACC --> AC + + ACGBP --> ASE + ACGBP --> AGBP + + ACNB --> UDCGC + ACNB --> ASE + ACNB --> ABF + + ACRFAD --> ASE + ACRFAD --> ABF + + ACRGP --> ASE + ACRGP --> ABGP + + %% iOS workflow dependencies + IKSB --> ASE + IKSB --> IB + + IKSR --> IES + + ISB --> UDCGC + ISB --> IES + + ISR --> IES + + %% KMP workflow dependencies + KCDC --> KDC + + KCNB --> UDCGC + KCNB --> ASE + KCNB --> IB + KCNB --> ABF + + %% Styling + classDef workflowAndroid fill:#4CAF50,stroke:#2E7D32,stroke-width:2px,color:#fff + classDef workflowIOS fill:#2196F3,stroke:#1565C0,stroke-width:2px,color:#fff + classDef workflowKMP fill:#FF9800,stroke:#E65100,stroke-width:2px,color:#fff + classDef workflowUniversal fill:#9C27B0,stroke:#4A148C,stroke-width:2px,color:#fff + classDef actionAndroid fill:#A5D6A7,stroke:#2E7D32,stroke-width:2px + classDef actionIOS fill:#90CAF9,stroke:#1565C0,stroke-width:2px + classDef actionUniversal fill:#CE93D8,stroke:#4A148C,stroke-width:2px + + %% Apply styling + class ACC,ACGBP,ACNB,ACRFAD,ACRGP workflowAndroid + class IST,ISB,ISR,IKST,IKSB,IKSR workflowIOS + class KCDC,KCNB workflowKMP + class WL,UCB,USB workflowUniversal + + class ASE,AC,ABF,ABGP,AGBP actionAndroid + class IES,IB actionIOS + class KDC,UDCGC actionUniversal +``` + +### Legend +- **Green**: Android workflows and actions +- **Blue**: iOS workflows and actions +- **Orange**: KMP (Kotlin Multiplatform) workflows +- **Purple**: Universal workflows and actions + +### Key Dependencies +- **android-setup-environment**: Core action used by most Android and KMP workflows for environment setup +- **universal-detect-changes-and-generate-changelog**: Used by build workflows to detect changes and generate changelogs +- **ios-export-secrets**: Used by iOS workflows to export secrets to .xcconfig files +- **ios-build**: Handles iOS building and TestFlight uploads for KMP projects ## Contributors From 8c3eb7054dfd5a8136ec0e6a35e5f327047bce44 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Thu, 25 Sep 2025 16:10:15 +0200 Subject: [PATCH 25/34] Revert "docs: Enhance workflow documentation with dependency diagram" This reverts commit be8c542b38b591e56a91bd1f3b7de62635aafdc3. --- README.md | 111 +----------------------------------------------------- 1 file changed, 1 insertion(+), 110 deletions(-) diff --git a/README.md b/README.md index 9b5a05f..195e66e 100644 --- a/README.md +++ b/README.md @@ -25,13 +25,12 @@ All the available reusable workflows are listed in the following table. | Platform | Runner | Action | File | Description | |:---------------|:------------|:----------------------------|:-----------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------| -| Universal | Any | Workflows Lint | [`workflows-lint`](.github/workflows/workflows-lint.yml) | Lints GitHub workflow files for syntax and best practices. | | Universal | Cloud | Backup | [`universal-cloud-backup`](.github/workflows/universal-cloud-backup.yml) | Backups currently checked out ref to a remote repository. | | Universal | Self-hosted | Backup | [`universal-selfhosted-backup`](.github/workflows/universal-selfhosted-backup.yml) | Backups currently checked out ref to a remote repository. | | iOS | Self-hosted | Test | [`ios-selfhosted-test`](.github/workflows/ios-selfhosted-test.yml) | Lints and tests the PR. | | iOS | Self-hosted | Build | [`ios-selfhosted-build`](.github/workflows/ios-selfhosted-build.yml) | Creates enterprise release build and submits the build to Futured App Store Connect. | | iOS | Self-hosted | Release | [`ios-selfhosted-release`](.github/workflows/ios-selfhosted-release.yml) | Creates release build and submits it to App Store Connect. | -| iOS (KMP) | Self-hosted | Test | [`ios-kmp-selfhosted-test`](.github/workflows/ios-kmp-selfhosted-test.yml) | Lints and tests the PR. | +| iOS (KMP) | Self-hosted | Test | [`ios-kmp-selfhosted-test`](.github/workflows/ios-kmp-selfhosted-test.yml) | Lints and tests the PR. | | iOS (KMP) | Self-hosted | Build | [`ios-kmp-selfhosted-build`](.github/workflows/ios-kmp-selfhosted-build.yml) | Creates enterprise release build and submits the build to Futured App Store Connect. | | iOS (KMP) | Self-hosted | Release | [`ios-kmp-selfhosted-release`](.github/workflows/ios-kmp-selfhosted-release.yml) | Creates release build and submits it to App Store Connect. | | Android (+KMP) | Cloud | Tests & Lint checks | [`android-cloud-check`](.github/workflows/android-cloud-check.yml) | Runs unit tests and lint checks on pull request. | @@ -40,114 +39,6 @@ All the available reusable workflows are listed in the following table. | Android | Cloud | Nightly Build | [`android-cloud-nightly-build`](.github/workflows/android-cloud-nightly-build.yml) | Automated nightly builds with Firebase App Distribution deployment. | | Android (+KMP) | Cloud | Generate Baseline Profiles | [`android-cloud-generate-baseline-profiles`](.github/workflows/android-cloud-generate-baseline-profiles.yml) | Generates baseline profiles and creates PR with changes. | | KMP | Cloud | Detect Changes | [`kmp-cloud-detect-changes`](.github/workflows/kmp-cloud-detect-changes.yml) | Detects changed sources in KMP projects for conditional job execution. | -| KMP | Cloud | Combined Nightly Build | [`kmp-combined-nightly-build`](.github/workflows/kmp-combined-nightly-build.yml) | Automated nightly builds for both iOS and Android platforms in KMP projects. | - -## Workflow and Action Dependencies - -The following diagram shows the relationships between workflows and actions in this repository: - -```mermaid -graph TD - %% Workflow definitions - subgraph "Workflows" - WL[workflows-lint] - UCB[universal-cloud-backup] - USB[universal-selfhosted-backup] - IKST[ios-kmp-selfhosted-test] - IST[ios-selfhosted-test] - ACC[android-cloud-check] - ACGBP[android-cloud-generate-baseline-profiles] - ACNB[android-cloud-nightly-build] - ACRFAD[android-cloud-release-firebaseAppDistribution] - ACRGP[android-cloud-release-googlePlay] - KCDC[kmp-cloud-detect-changes] - IKSR[ios-kmp-selfhosted-release] - ISB[ios-selfhosted-build] - ISR[ios-selfhosted-release] - IKSB[ios-kmp-selfhosted-build] - KCNB[kmp-combined-nightly-build] - end - - %% Action definitions - subgraph "Actions" - ASE[android-setup-environment] - AC[android-check] - ABF[android-build-firebase] - ABGP[android-build-googlePlay] - AGBP[android-generate-baseline-profiles] - KDC[kmp-detect-changes] - UDCGC[universal-detect-changes-and-generate-changelog] - IES[ios-export-secrets] - IB[ios-build] - end - - %% Android workflow dependencies - ACC --> ASE - ACC --> AC - - ACGBP --> ASE - ACGBP --> AGBP - - ACNB --> UDCGC - ACNB --> ASE - ACNB --> ABF - - ACRFAD --> ASE - ACRFAD --> ABF - - ACRGP --> ASE - ACRGP --> ABGP - - %% iOS workflow dependencies - IKSB --> ASE - IKSB --> IB - - IKSR --> IES - - ISB --> UDCGC - ISB --> IES - - ISR --> IES - - %% KMP workflow dependencies - KCDC --> KDC - - KCNB --> UDCGC - KCNB --> ASE - KCNB --> IB - KCNB --> ABF - - %% Styling - classDef workflowAndroid fill:#4CAF50,stroke:#2E7D32,stroke-width:2px,color:#fff - classDef workflowIOS fill:#2196F3,stroke:#1565C0,stroke-width:2px,color:#fff - classDef workflowKMP fill:#FF9800,stroke:#E65100,stroke-width:2px,color:#fff - classDef workflowUniversal fill:#9C27B0,stroke:#4A148C,stroke-width:2px,color:#fff - classDef actionAndroid fill:#A5D6A7,stroke:#2E7D32,stroke-width:2px - classDef actionIOS fill:#90CAF9,stroke:#1565C0,stroke-width:2px - classDef actionUniversal fill:#CE93D8,stroke:#4A148C,stroke-width:2px - - %% Apply styling - class ACC,ACGBP,ACNB,ACRFAD,ACRGP workflowAndroid - class IST,ISB,ISR,IKST,IKSB,IKSR workflowIOS - class KCDC,KCNB workflowKMP - class WL,UCB,USB workflowUniversal - - class ASE,AC,ABF,ABGP,AGBP actionAndroid - class IES,IB actionIOS - class KDC,UDCGC actionUniversal -``` - -### Legend -- **Green**: Android workflows and actions -- **Blue**: iOS workflows and actions -- **Orange**: KMP (Kotlin Multiplatform) workflows -- **Purple**: Universal workflows and actions - -### Key Dependencies -- **android-setup-environment**: Core action used by most Android and KMP workflows for environment setup -- **universal-detect-changes-and-generate-changelog**: Used by build workflows to detect changes and generate changelogs -- **ios-export-secrets**: Used by iOS workflows to export secrets to .xcconfig files -- **ios-build**: Handles iOS building and TestFlight uploads for KMP projects ## Contributors From 2bfabf3deaa0d30ab1ee5dfca44e323bcf8c52ca Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Thu, 25 Sep 2025 16:12:41 +0200 Subject: [PATCH 26/34] docs: Update README with new workflows and fixes - Added `workflows-lint` and `kmp-combined-nightly-build` workflows to the table. - Fixed formatting inconsistency for `iOS (KMP)` workflow entry. --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 195e66e..0b03544 100644 --- a/README.md +++ b/README.md @@ -25,12 +25,13 @@ All the available reusable workflows are listed in the following table. | Platform | Runner | Action | File | Description | |:---------------|:------------|:----------------------------|:-----------------------------------------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------------| +| Universal | Any | Workflows Lint | [`workflows-lint`](.github/workflows/workflows-lint.yml) | Lints GitHub workflow files for syntax and best practices. | | Universal | Cloud | Backup | [`universal-cloud-backup`](.github/workflows/universal-cloud-backup.yml) | Backups currently checked out ref to a remote repository. | | Universal | Self-hosted | Backup | [`universal-selfhosted-backup`](.github/workflows/universal-selfhosted-backup.yml) | Backups currently checked out ref to a remote repository. | | iOS | Self-hosted | Test | [`ios-selfhosted-test`](.github/workflows/ios-selfhosted-test.yml) | Lints and tests the PR. | | iOS | Self-hosted | Build | [`ios-selfhosted-build`](.github/workflows/ios-selfhosted-build.yml) | Creates enterprise release build and submits the build to Futured App Store Connect. | | iOS | Self-hosted | Release | [`ios-selfhosted-release`](.github/workflows/ios-selfhosted-release.yml) | Creates release build and submits it to App Store Connect. | -| iOS (KMP) | Self-hosted | Test | [`ios-kmp-selfhosted-test`](.github/workflows/ios-kmp-selfhosted-test.yml) | Lints and tests the PR. | +| iOS (KMP) | Self-hosted | Test | [`ios-kmp-selfhosted-test`](.github/workflows/ios-kmp-selfhosted-test.yml) | Lints and tests the PR. | | iOS (KMP) | Self-hosted | Build | [`ios-kmp-selfhosted-build`](.github/workflows/ios-kmp-selfhosted-build.yml) | Creates enterprise release build and submits the build to Futured App Store Connect. | | iOS (KMP) | Self-hosted | Release | [`ios-kmp-selfhosted-release`](.github/workflows/ios-kmp-selfhosted-release.yml) | Creates release build and submits it to App Store Connect. | | Android (+KMP) | Cloud | Tests & Lint checks | [`android-cloud-check`](.github/workflows/android-cloud-check.yml) | Runs unit tests and lint checks on pull request. | @@ -39,6 +40,7 @@ All the available reusable workflows are listed in the following table. | Android | Cloud | Nightly Build | [`android-cloud-nightly-build`](.github/workflows/android-cloud-nightly-build.yml) | Automated nightly builds with Firebase App Distribution deployment. | | Android (+KMP) | Cloud | Generate Baseline Profiles | [`android-cloud-generate-baseline-profiles`](.github/workflows/android-cloud-generate-baseline-profiles.yml) | Generates baseline profiles and creates PR with changes. | | KMP | Cloud | Detect Changes | [`kmp-cloud-detect-changes`](.github/workflows/kmp-cloud-detect-changes.yml) | Detects changed sources in KMP projects for conditional job execution. | +| KMP | Cloud | Combined Nightly Build | [`kmp-combined-nightly-build`](.github/workflows/kmp-combined-nightly-build.yml) | Automated nightly builds for both iOS and Android platforms in KMP projects. | ## Contributors From be120f153aad722c502004c2b89e3dbfe53171a4 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Thu, 25 Sep 2025 16:24:19 +0200 Subject: [PATCH 27/34] refactor(ci): Simplify and streamline inputs in KMP nightly build workflow - Removed redundant input definitions for `ios_secret_properties` and modified references to use `secrets`. - Adjusted formatting and cleaned up unnecessary lines for better readability. --- .../workflows/kmp-combined-nightly-build.yml | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/.github/workflows/kmp-combined-nightly-build.yml b/.github/workflows/kmp-combined-nightly-build.yml index 1f340a6..2176393 100644 --- a/.github/workflows/kmp-combined-nightly-build.yml +++ b/.github/workflows/kmp-combined-nightly-build.yml @@ -75,6 +75,18 @@ on: required: false type: string default: secrets.properties + ios_secret_xcconfig_path: + description: "Path to the .xcconfig file. Selected secret properties will be appended to the end of this file." + type: string + required: false + ios_secret_required_keys: + description: "Comma-separated list of required secret keys." + type: string + required: false + ios_custom_values: + description: "Custom string that can contains values specified in your workflow file. Those values will be placed into environment variable. Example: \"CUSTOM-1: 1; CUSTOM-2: 2\"" + required: false + type: string changelog_debug: description: "Enable debug mode for changelog generation. Default is false." type: boolean @@ -90,22 +102,6 @@ on: type: string required: false default: "24 hours" - ios_secret_xcconfig_path: - description: "Path to the .xcconfig file. Selected secret properties will be appended to the end of this file." - type: string - required: false - ios_secret_properties: - required: false - type: string - description: "Secrets in the format KEY = VALUE (one per line)." - ios_secret_required_keys: - description: "Comma-separated list of required secret keys." - type: string - required: false - ios_custom_values: - description: "Custom string that can contains values specified in your workflow file. Those values will be placed into environment variable. Example: \"CUSTOM-1: 1; CUSTOM-2: 2\"" - required: false - type: string secrets: firebase_app_distribution_service_account: @@ -117,6 +113,9 @@ on: android_secret_properties: required: false description: "Custom string that contains key-value properties as secrets. Contents of this secret will be placed into file specified by 'android_secret_properties_file' input." + ios_secret_properties: + required: false + description: "Secrets in the format KEY = VALUE (one per line)." ios_match_password: description: "Password for decrypting of certificates and provisioning profiles." required: true @@ -131,7 +130,6 @@ on: description: "Private App Store Connect API issuer key for submitting build to App Store." jobs: - changelog: outputs: skip_build: ${{ steps.detect_changes.outputs.skip_build }} @@ -148,7 +146,6 @@ jobs: checkout_depth: ${{ inputs.changelog_checkout_depth }} debug: ${{ inputs.changelog_debug }} fallback_lookback: ${{ inputs.changelog_fallback_lookback }} - ios_build: name: iOS Build runs-on: self-hosted @@ -179,14 +176,13 @@ jobs: app_store_connect_api_key_key_id: ${{ secrets.ios_app_store_connect_api_key_key_id }} app_store_connect_api_key_issuer_id: ${{ secrets.ios_app_store_connect_api_key_issuer_id }} secret_xcconfig_path: ${{ inputs.ios_secret_xcconfig_path }} - secret_properties: ${{ inputs.ios_secret_properties }} + secret_properties: ${{ secrets.ios_secret_properties }} secret_required_keys: ${{ inputs.ios_secret_required_keys }} kmp_swift_package_integration: ${{ inputs.kmp_swift_package_integration }} kmp_swift_package_path: ${{ inputs.kmp_swift_package_path }} kmp_swift_package_flavor: ${{ inputs.kmp_flavor }} custom_values: ${{ inputs.ios_custom_values }} testflight_changelog: ${{ needs.changelog.outputs.changelog }} - android_build: name: Android Build runs-on: ubuntu-latest @@ -222,7 +218,6 @@ jobs: kmp_flavor: ${{ inputs.kmp_flavor }} secret_properties_file: ${{ inputs.android_secret_properties_file }} secret_properties: ${{ secrets.android_secret_properties }} - save_cache: name: Cache last build commit SHA runs-on: ubuntu-latest From 3fc2a7a6390e15af639ac7a58926ee3554e1262c Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 26 Sep 2025 11:33:24 +0200 Subject: [PATCH 28/34] refactor(ci): Remove default value for `build_flavor` in KMP nightly build workflow --- .github/workflows/kmp-combined-nightly-build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/kmp-combined-nightly-build.yml b/.github/workflows/kmp-combined-nightly-build.yml index 2176393..79c34c8 100644 --- a/.github/workflows/kmp-combined-nightly-build.yml +++ b/.github/workflows/kmp-combined-nightly-build.yml @@ -20,7 +20,6 @@ on: description: "KMP Build flavor. This is optional and only required by KMP projects and can be ignored on pure Android projects" required: true type: string - default: 'test' firebase_app_distribution_groups: description: "Comma-separated list of app distribution group IDs" required: true From 0445f18abcc924a4d5e7fbf5dec4360904eb090e Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 26 Sep 2025 11:42:10 +0200 Subject: [PATCH 29/34] refactor(ci): Specify `bash` shell for all action steps in `android-generate-baseline-profiles` - Ensures consistency and avoids potential shell mismatches across defined steps. --- .github/actions/android-generate-baseline-profiles/action.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/actions/android-generate-baseline-profiles/action.yml b/.github/actions/android-generate-baseline-profiles/action.yml index 1b0cfda..aa916db 100644 --- a/.github/actions/android-generate-baseline-profiles/action.yml +++ b/.github/actions/android-generate-baseline-profiles/action.yml @@ -27,12 +27,14 @@ runs: using: "composite" steps: - name: Enable KVM group perms + shell: bash run: | echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules sudo udevadm control --reload-rules sudo udevadm trigger --name-match=kvm ls /dev/kvm - name: Prepare Environment + shell: bash run: | echo '${{ inputs.secret_properties }}' > ${{ inputs.secret_properties_file }} - name: Generate profiles @@ -40,6 +42,7 @@ runs: ANDROID_KEYSTORE_PASSWORD: ${{ inputs.signing_keystore_password }} ANDROID_KEY_ALIAS: ${{ inputs.signing_key_alias }} ANDROID_KEY_PASSWORD: ${{ inputs.signing_key_password }} + shell: bash run: ./gradlew ${{ inputs.generate_gradle_task }} -Pandroid.experimental.testOptions.managedDevices.emulator.showKernelLogging=true -Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect" From 5fe051f0dfc68deb1c530990b825910db99a378d Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 26 Sep 2025 11:48:30 +0200 Subject: [PATCH 30/34] fix(ci): Update action reference in `kmp-cloud-detect-changes.yml` - Temporarily point to `feature/android-refactor` branch with a TODO note to update to `main`. --- .github/workflows/kmp-cloud-detect-changes.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/kmp-cloud-detect-changes.yml b/.github/workflows/kmp-cloud-detect-changes.yml index 3cc3602..9be8ed4 100644 --- a/.github/workflows/kmp-cloud-detect-changes.yml +++ b/.github/workflows/kmp-cloud-detect-changes.yml @@ -58,6 +58,7 @@ jobs: steps: - name: Detect Changes id: detect - uses: ./.github/actions/kmp-detect-changes + # TODO update branch ref to main, reject pull request if you see this + uses: futuredapp/.github/.github/actions/kmp-detect-changes@feature/android-refactor with: USE_GIT_LFS: ${{ inputs.USE_GIT_LFS }} From 86634e03c12cdf7415551a7d4d46562d44283900 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 26 Sep 2025 12:04:39 +0200 Subject: [PATCH 31/34] refactor(ci): Update action references to `main` across workflows - Replaced `feature/android-refactor` branch references with `main`. - Removed outdated TODO comments regarding branch updates. --- .github/workflows/android-cloud-check.yml | 6 ++---- .../android-cloud-generate-baseline-profiles.yml | 6 ++---- .github/workflows/android-cloud-nightly-build.yml | 9 +++------ ...roid-cloud-release-firebaseAppDistribution.yml | 6 ++---- .../android-cloud-release-googlePlay.yml | 6 ++---- .github/workflows/ios-kmp-selfhosted-build.yml | 6 ++---- .github/workflows/kmp-cloud-detect-changes.yml | 3 +-- .github/workflows/kmp-combined-nightly-build.yml | 15 +++++---------- 8 files changed, 19 insertions(+), 38 deletions(-) diff --git a/.github/workflows/android-cloud-check.yml b/.github/workflows/android-cloud-check.yml index 719c8f5..cefc60c 100644 --- a/.github/workflows/android-cloud-check.yml +++ b/.github/workflows/android-cloud-check.yml @@ -58,15 +58,13 @@ jobs: with: lfs: ${{ inputs.USE_GIT_LFS }} - name: Set up environment - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor + uses: futuredapp/.github/.github/actions/android-setup-environment@main with: java_version: ${{ inputs.JAVA_VERSION }} java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - name: Run checks - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-check@feature/android-refactor + uses: futuredapp/.github/.github/actions/android-check@main with: lint_gradle_task: ${{ inputs.LINT_GRADLE_TASKS }} test_gradle_task: ${{ inputs.TEST_GRADLE_TASKS }} diff --git a/.github/workflows/android-cloud-generate-baseline-profiles.yml b/.github/workflows/android-cloud-generate-baseline-profiles.yml index 8cedd47..90a19b4 100644 --- a/.github/workflows/android-cloud-generate-baseline-profiles.yml +++ b/.github/workflows/android-cloud-generate-baseline-profiles.yml @@ -75,15 +75,13 @@ jobs: with: lfs: ${{ inputs.USE_GIT_LFS }} - name: Set up environment - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor + uses: futuredapp/.github/.github/actions/android-setup-environment@main with: java_version: ${{ inputs.JAVA_VERSION }} java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - name: Generate baseline profiles - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-generate-baseline-profiles@feature/android-refactor + uses: futuredapp/.github/.github/actions/android-generate-baseline-profiles@main with: generate_gradle_task: ${{ inputs.TASK_NAME }} signing_keystore_password: ${{ secrets.SIGNING_KEYSTORE_PASSWORD }} diff --git a/.github/workflows/android-cloud-nightly-build.yml b/.github/workflows/android-cloud-nightly-build.yml index 249ccab..edcb878 100644 --- a/.github/workflows/android-cloud-nightly-build.yml +++ b/.github/workflows/android-cloud-nightly-build.yml @@ -104,8 +104,7 @@ jobs: steps: - name: Detect changes and generate changelog id: detect_changes - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/universal-detect-changes-and-generate-changelog@feature/android-refactor + uses: futuredapp/.github/.github/actions/universal-detect-changes-and-generate-changelog@main with: checkout_depth: ${{ inputs.CHANGELOG_CHECKOUT_DEPTH }} debug: ${{ inputs.CHANGELOG_DEBUG }} @@ -124,15 +123,13 @@ jobs: with: lfs: ${{ inputs.USE_GIT_LFS }} - name: Set up environment - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor + uses: futuredapp/.github/.github/actions/android-setup-environment@main with: java_version: ${{ inputs.JAVA_VERSION }} java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - name: Build and upload to App Distribution - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-build-firebase@feature/android-refactor + uses: futuredapp/.github/.github/actions/android-build-firebase@main with: test_gradle_task: ${{ inputs.TEST_GRADLE_TASKS }} package_gradle_task: ${{ inputs.PACKAGE_GRADLE_TASK }} diff --git a/.github/workflows/android-cloud-release-firebaseAppDistribution.yml b/.github/workflows/android-cloud-release-firebaseAppDistribution.yml index 09fbac3..9724d3e 100644 --- a/.github/workflows/android-cloud-release-firebaseAppDistribution.yml +++ b/.github/workflows/android-cloud-release-firebaseAppDistribution.yml @@ -96,15 +96,13 @@ jobs: with: lfs: ${{ inputs.USE_GIT_LFS }} - name: Set up environment - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor + uses: futuredapp/.github/.github/actions/android-setup-environment@main with: java_version: ${{ inputs.JAVA_VERSION }} java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - name: Build and upload to App Distribution - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-build-firebase@feature/android-refactor + uses: futuredapp/.github/.github/actions/android-build-firebase@main with: test_gradle_task: ${{ inputs.TEST_GRADLE_TASKS }} package_gradle_task: ${{ inputs.PACKAGE_GRADLE_TASK }} diff --git a/.github/workflows/android-cloud-release-googlePlay.yml b/.github/workflows/android-cloud-release-googlePlay.yml index 194261a..13a9465 100644 --- a/.github/workflows/android-cloud-release-googlePlay.yml +++ b/.github/workflows/android-cloud-release-googlePlay.yml @@ -102,14 +102,12 @@ jobs: with: lfs: ${{ inputs.USE_GIT_LFS }} - name: Set up environment - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor + uses: futuredapp/.github/.github/actions/android-setup-environment@main with: java_version: ${{ inputs.JAVA_VERSION }} java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} - name: Build and release - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-build-googlePlay@feature/android-refactor + uses: futuredapp/.github/.github/actions/android-build-googlePlay@main with: bundle_gradle_task: ${{ inputs.BUNDLE_GRADLE_TASK }} version_name: ${{ inputs.VERSION_NAME }} diff --git a/.github/workflows/ios-kmp-selfhosted-build.yml b/.github/workflows/ios-kmp-selfhosted-build.yml index aff5c67..6641204 100644 --- a/.github/workflows/ios-kmp-selfhosted-build.yml +++ b/.github/workflows/ios-kmp-selfhosted-build.yml @@ -93,16 +93,14 @@ jobs: with: lfs: ${{ inputs.use_git_lfs }} - name: Set up environment - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor + uses: futuredapp/.github/.github/actions/android-setup-environment@main with: java_version: ${{ inputs.java_version }} java_distribution: ${{ inputs.java_distribution }} gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} ruby: 'false' - name: Build and upload to TestFlight - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/ios-build@feature/android-refactor + uses: futuredapp/.github/.github/actions/ios-build@main with: match_password: ${{ secrets.MATCH_PASSWORD }} app_store_connect_api_key_key: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY }} diff --git a/.github/workflows/kmp-cloud-detect-changes.yml b/.github/workflows/kmp-cloud-detect-changes.yml index 9be8ed4..50caa63 100644 --- a/.github/workflows/kmp-cloud-detect-changes.yml +++ b/.github/workflows/kmp-cloud-detect-changes.yml @@ -58,7 +58,6 @@ jobs: steps: - name: Detect Changes id: detect - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/kmp-detect-changes@feature/android-refactor + uses: futuredapp/.github/.github/actions/kmp-detect-changes@main with: USE_GIT_LFS: ${{ inputs.USE_GIT_LFS }} diff --git a/.github/workflows/kmp-combined-nightly-build.yml b/.github/workflows/kmp-combined-nightly-build.yml index 79c34c8..a7e3a3a 100644 --- a/.github/workflows/kmp-combined-nightly-build.yml +++ b/.github/workflows/kmp-combined-nightly-build.yml @@ -139,8 +139,7 @@ jobs: steps: - name: Detect changes and generate changelog id: detect_changes - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/universal-detect-changes-and-generate-changelog@feature/android-refactor + uses: futuredapp/.github/.github/actions/universal-detect-changes-and-generate-changelog@main with: checkout_depth: ${{ inputs.changelog_checkout_depth }} debug: ${{ inputs.changelog_debug }} @@ -159,16 +158,14 @@ jobs: with: lfs: ${{ inputs.use_git_lfs }} - name: Set up environment - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor + uses: futuredapp/.github/.github/actions/android-setup-environment@main with: java_version: ${{ inputs.java_version }} java_distribution: ${{ inputs.java_distribution }} gradle_cache_encryption_key: ${{ secrets.gradle_cache_encryption_key }} ruby: 'false' - name: Build and upload to TestFlight - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/ios-build@feature/android-refactor + uses: futuredapp/.github/.github/actions/ios-build@main with: match_password: ${{ secrets.ios_match_password }} app_store_connect_api_key_key: ${{ secrets.ios_app_store_connect_api_key_key }} @@ -196,15 +193,13 @@ jobs: with: lfs: ${{ inputs.use_git_lfs }} - name: Set up environment - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-setup-environment@feature/android-refactor + uses: futuredapp/.github/.github/actions/android-setup-environment@main with: java_version: ${{ inputs.java_version }} java_distribution: ${{ inputs.java_distribution }} gradle_cache_encryption_key: ${{ secrets.gradle_cache_encryption_key }} - name: Build and upload to App Distribution - # TODO update branch ref to main, reject pull request if you see this - uses: futuredapp/.github/.github/actions/android-build-firebase@feature/android-refactor + uses: futuredapp/.github/.github/actions/android-build-firebase@main with: test_gradle_task: ${{ inputs.android_test_gradle_task }} package_gradle_task: ${{ inputs.android_package_gradle_task }} From e4927f826e67d9e5a2f690eec80569891c8bc098 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 26 Sep 2025 12:08:34 +0200 Subject: [PATCH 32/34] refactor(ci): Update iOS build action references to `ios-kmp-build` - Replaced `ios-build` action with `ios-kmp-build` in KMP workflows for consistency. --- .github/actions/{ios-build => ios-kmp-build}/action.yml | 0 .github/workflows/ios-kmp-selfhosted-build.yml | 2 +- .github/workflows/kmp-combined-nightly-build.yml | 2 +- 3 files changed, 2 insertions(+), 2 deletions(-) rename .github/actions/{ios-build => ios-kmp-build}/action.yml (100%) diff --git a/.github/actions/ios-build/action.yml b/.github/actions/ios-kmp-build/action.yml similarity index 100% rename from .github/actions/ios-build/action.yml rename to .github/actions/ios-kmp-build/action.yml diff --git a/.github/workflows/ios-kmp-selfhosted-build.yml b/.github/workflows/ios-kmp-selfhosted-build.yml index 6641204..4c8caf8 100644 --- a/.github/workflows/ios-kmp-selfhosted-build.yml +++ b/.github/workflows/ios-kmp-selfhosted-build.yml @@ -100,7 +100,7 @@ jobs: gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} ruby: 'false' - name: Build and upload to TestFlight - uses: futuredapp/.github/.github/actions/ios-build@main + uses: futuredapp/.github/.github/actions/ios-kmp-build@main with: match_password: ${{ secrets.MATCH_PASSWORD }} app_store_connect_api_key_key: ${{ secrets.APP_STORE_CONNECT_API_KEY_KEY }} diff --git a/.github/workflows/kmp-combined-nightly-build.yml b/.github/workflows/kmp-combined-nightly-build.yml index a7e3a3a..130235b 100644 --- a/.github/workflows/kmp-combined-nightly-build.yml +++ b/.github/workflows/kmp-combined-nightly-build.yml @@ -165,7 +165,7 @@ jobs: gradle_cache_encryption_key: ${{ secrets.gradle_cache_encryption_key }} ruby: 'false' - name: Build and upload to TestFlight - uses: futuredapp/.github/.github/actions/ios-build@main + uses: futuredapp/.github/.github/actions/ios-kmp-build@main with: match_password: ${{ secrets.ios_match_password }} app_store_connect_api_key_key: ${{ secrets.ios_app_store_connect_api_key_key }} From e46f1737cbc5c535e5c2482858f2b8497bfdf4cb Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 26 Sep 2025 13:03:13 +0200 Subject: [PATCH 33/34] refactor(ci): Remove unused `SIGNING_KEYSTORE_PATH` input from Android release workflow --- .github/workflows/android-cloud-release-googlePlay.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.github/workflows/android-cloud-release-googlePlay.yml b/.github/workflows/android-cloud-release-googlePlay.yml index 13a9465..25c1325 100644 --- a/.github/workflows/android-cloud-release-googlePlay.yml +++ b/.github/workflows/android-cloud-release-googlePlay.yml @@ -12,10 +12,6 @@ on: description: "A Gradle task for assembling app bundle, for example `bundleRelease`" required: true type: string - SIGNING_KEYSTORE_PATH: - description: "Path to keystore for signing of universal APK. Example: `keystore/debug.jks' or 'androidApp/signing/debug.keystore'" - required: true - type: string GOOGLE_PLAY_APPLICATION_ID: description: "Google Play applicationId" required: true From 38c493a034de12a32795e1d6d35e0d56dd6b0bc5 Mon Sep 17 00:00:00 2001 From: matejsemancik Date: Fri, 26 Sep 2025 14:09:35 +0200 Subject: [PATCH 34/34] refactor(ci): Standardize input variable casing in `kmp-combined-nightly-build.yml` - Updated all input and secret variable names to use uppercase casing for consistency. - Adjusted workflow references to align with new variable names. --- .../workflows/kmp-combined-nightly-build.yml | 136 +++++++++--------- 1 file changed, 68 insertions(+), 68 deletions(-) diff --git a/.github/workflows/kmp-combined-nightly-build.yml b/.github/workflows/kmp-combined-nightly-build.yml index 130235b..c28716a 100644 --- a/.github/workflows/kmp-combined-nightly-build.yml +++ b/.github/workflows/kmp-combined-nightly-build.yml @@ -4,127 +4,127 @@ on: workflow_call: inputs: ## Required Inputs - android_test_gradle_task: + ANDROID_TEST_GRADLE_TASK: description: "A Gradle task(s) for executing unit tests, for example `testReleaseUnitTest` or `testDevEnterpriseUnitTest`" required: true type: string - android_package_gradle_task: + ANDROID_PACKAGE_GRADLE_TASK: description: "A Gradle task for packaging universal APK, eg. 'packageEnterpriseUniversalApk'" required: true type: string - android_upload_gradle_task: + ANDROID_UPLOAD_GRADLE_TASK: description: "A Gradle task for uploading APK, for example `appDistributionUploadEnterprise`" required: true type: string - kmp_flavor: + KMP_FLAVOR: description: "KMP Build flavor. This is optional and only required by KMP projects and can be ignored on pure Android projects" required: true type: string - firebase_app_distribution_groups: + FIREBASE_APP_DISTRIBUTION_GROUPS: description: "Comma-separated list of app distribution group IDs" required: true type: string ## Optional Inputs - timeout_minutes: + TIMEOUT_MINUTES: description: "Job timeout in minutes" required: false type: number default: 30 - use_git_lfs: + USE_GIT_LFS: description: "Whether to download Git-LFS files" type: boolean required: false default: false - gradle_opts: + GRADLE_OPTS: description: "Gradle options" required: false type: string default: "" - java_version: + JAVA_VERSION: description: "Java version to use" required: false type: string default: '17' - java_distribution: + JAVA_DISTRIBUTION: description: "Java distribution to use" required: false type: string default: 'zulu' - android_version_name: + ANDROID_VERSION_NAME: description: "Version name. Example: '1.X.X-snapshot'" required: false type: string - android_build_number_offset: + ANDROID_BUILD_NUMBER_OFFSET: description: "Build number offset. This number will be added to GITHUB_RUN_NUMBER and can be used to make corrections to build numbers." required: false type: number default: 0 - kmp_swift_package_integration: + KMP_SWIFT_PACKAGE_INTEGRATION: description: "Whether KMP is integrated in Xcode project as a Swift Package" required: false type: boolean default: false - kmp_swift_package_path: - description: "If `kmp_swift_package_integration` is 'true', then specifies a location of local Swift Package with Makefile. Example: 'iosApp/shared/KMP`" + KMP_SWIFT_PACKAGE_PATH: + description: "If `KMP_SWIFT_PACKAGE_INTEGRATION` is 'true', then specifies a location of local Swift Package with Makefile. Example: 'iosApp/shared/KMP`" required: false type: string - android_secret_properties_file: + ANDROID_SECRET_PROPERTIES_FILE: description: "A path to file that will be populated with contents of 'android_secret_properties' secret. This file can be picked up by Secrets Gradle plugin to embed secrets into BuildConfig." required: false type: string default: secrets.properties - ios_secret_xcconfig_path: + IOS_SECRET_XCCONFIG_PATH: description: "Path to the .xcconfig file. Selected secret properties will be appended to the end of this file." type: string required: false - ios_secret_required_keys: + IOS_SECRET_REQUIRED_KEYS: description: "Comma-separated list of required secret keys." type: string required: false - ios_custom_values: + IOS_CUSTOM_VALUES: description: "Custom string that can contains values specified in your workflow file. Those values will be placed into environment variable. Example: \"CUSTOM-1: 1; CUSTOM-2: 2\"" required: false type: string - changelog_debug: + CHANGELOG_DEBUG: description: "Enable debug mode for changelog generation. Default is false." type: boolean required: false default: false - changelog_checkout_depth: + CHANGELOG_CHECKOUT_DEPTH: description: "The depth of the git history to fetch for changelog generation. Default is 100." type: number required: false default: 100 - changelog_fallback_lookback: + CHANGELOG_FALLBACK_LOOKBACK: description: "The amount of time to look back for merge commits when no previous build commit is found. Default is 24 hours." type: string required: false default: "24 hours" secrets: - firebase_app_distribution_service_account: + FIREBASE_APP_DISTRIBUTION_SERVICE_ACCOUNT: required: true description: "JSON key of service account with permissions to upload build to Firebase App Distribution" - gradle_cache_encryption_key: + GRADLE_CACHE_ENCRYPTION_KEY: required: false description: "Configuration cache encryption key" - android_secret_properties: + ANDROID_SECRET_PROPERTIES: required: false - description: "Custom string that contains key-value properties as secrets. Contents of this secret will be placed into file specified by 'android_secret_properties_file' input." - ios_secret_properties: + description: "Custom string that contains key-value properties as secrets. Contents of this secret will be placed into file specified by 'ANDROID_SECRET_PROPERTIES_FILE' input." + IOS_SECRET_PROPERTIES: required: false description: "Secrets in the format KEY = VALUE (one per line)." - ios_match_password: + IOS_MATCH_PASSWORD: description: "Password for decrypting of certificates and provisioning profiles." required: true - ios_app_store_connect_api_key_key: + IOS_APP_STORE_CONNECT_API_KEY_KEY: description: "Private App Store Connect API key for submitting build to App Store." required: true - ios_app_store_connect_api_key_key_id: + IOS_APP_STORE_CONNECT_API_KEY_KEY_ID: required: true description: "Private App Store Connect API key for submitting build to App Store." - ios_app_store_connect_api_key_issuer_id: + IOS_APP_STORE_CONNECT_API_KEY_ISSUER_ID: required: true description: "Private App Store Connect API issuer key for submitting build to App Store." @@ -141,77 +141,77 @@ jobs: id: detect_changes uses: futuredapp/.github/.github/actions/universal-detect-changes-and-generate-changelog@main with: - checkout_depth: ${{ inputs.changelog_checkout_depth }} - debug: ${{ inputs.changelog_debug }} - fallback_lookback: ${{ inputs.changelog_fallback_lookback }} + checkout_depth: ${{ inputs.CHANGELOG_CHECKOUT_DEPTH }} + debug: ${{ inputs.CHANGELOG_DEBUG }} + fallback_lookback: ${{ inputs.CHANGELOG_FALLBACK_LOOKBACK }} ios_build: name: iOS Build runs-on: self-hosted needs: changelog if: ${{ needs.changelog.outputs.skip_build != 'true' }} - timeout-minutes: ${{ inputs.timeout_minutes }} + timeout-minutes: ${{ inputs.TIMEOUT_MINUTES }} env: - GRADLE_OPTS: ${{ inputs.gradle_opts }} + GRADLE_OPTS: ${{ inputs.GRADLE_OPTS }} steps: - name: Checkout uses: actions/checkout@v4 with: - lfs: ${{ inputs.use_git_lfs }} + lfs: ${{ inputs.USE_GIT_LFS }} - name: Set up environment uses: futuredapp/.github/.github/actions/android-setup-environment@main with: - java_version: ${{ inputs.java_version }} - java_distribution: ${{ inputs.java_distribution }} - gradle_cache_encryption_key: ${{ secrets.gradle_cache_encryption_key }} + java_version: ${{ inputs.JAVA_VERSION }} + java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} + gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} ruby: 'false' - name: Build and upload to TestFlight uses: futuredapp/.github/.github/actions/ios-kmp-build@main with: - match_password: ${{ secrets.ios_match_password }} - app_store_connect_api_key_key: ${{ secrets.ios_app_store_connect_api_key_key }} - app_store_connect_api_key_key_id: ${{ secrets.ios_app_store_connect_api_key_key_id }} - app_store_connect_api_key_issuer_id: ${{ secrets.ios_app_store_connect_api_key_issuer_id }} - secret_xcconfig_path: ${{ inputs.ios_secret_xcconfig_path }} - secret_properties: ${{ secrets.ios_secret_properties }} - secret_required_keys: ${{ inputs.ios_secret_required_keys }} - kmp_swift_package_integration: ${{ inputs.kmp_swift_package_integration }} - kmp_swift_package_path: ${{ inputs.kmp_swift_package_path }} - kmp_swift_package_flavor: ${{ inputs.kmp_flavor }} - custom_values: ${{ inputs.ios_custom_values }} + match_password: ${{ secrets.IOS_MATCH_PASSWORD }} + app_store_connect_api_key_key: ${{ secrets.IOS_APP_STORE_CONNECT_API_KEY_KEY }} + app_store_connect_api_key_key_id: ${{ secrets.IOS_APP_STORE_CONNECT_API_KEY_KEY_ID }} + app_store_connect_api_key_issuer_id: ${{ secrets.IOS_APP_STORE_CONNECT_API_KEY_ISSUER_ID }} + secret_xcconfig_path: ${{ inputs.IOS_SECRET_XCCONFIG_PATH }} + secret_properties: ${{ secrets.IOS_SECRET_PROPERTIES }} + secret_required_keys: ${{ inputs.IOS_SECRET_REQUIRED_KEYS }} + kmp_swift_package_integration: ${{ inputs.KMP_SWIFT_PACKAGE_INTEGRATION }} + kmp_swift_package_path: ${{ inputs.KMP_SWIFT_PACKAGE_PATH }} + kmp_swift_package_flavor: ${{ inputs.KMP_FLAVOR }} + custom_values: ${{ inputs.IOS_CUSTOM_VALUES }} testflight_changelog: ${{ needs.changelog.outputs.changelog }} android_build: name: Android Build runs-on: ubuntu-latest needs: changelog if: ${{ needs.changelog.outputs.skip_build != 'true' }} - timeout-minutes: ${{ inputs.timeout_minutes }} + timeout-minutes: ${{ inputs.TIMEOUT_MINUTES }} env: - GRADLE_OPTS: ${{ inputs.gradle_opts }} + GRADLE_OPTS: ${{ inputs.GRADLE_OPTS }} steps: - name: Checkout uses: actions/checkout@v4 with: - lfs: ${{ inputs.use_git_lfs }} + lfs: ${{ inputs.USE_GIT_LFS }} - name: Set up environment uses: futuredapp/.github/.github/actions/android-setup-environment@main with: - java_version: ${{ inputs.java_version }} - java_distribution: ${{ inputs.java_distribution }} - gradle_cache_encryption_key: ${{ secrets.gradle_cache_encryption_key }} + java_version: ${{ inputs.JAVA_VERSION }} + java_distribution: ${{ inputs.JAVA_DISTRIBUTION }} + gradle_cache_encryption_key: ${{ secrets.GRADLE_CACHE_ENCRYPTION_KEY }} - name: Build and upload to App Distribution uses: futuredapp/.github/.github/actions/android-build-firebase@main with: - test_gradle_task: ${{ inputs.android_test_gradle_task }} - package_gradle_task: ${{ inputs.android_package_gradle_task }} - upload_gradle_task: ${{ inputs.android_upload_gradle_task }} - app_distribution_groups: ${{ inputs.firebase_app_distribution_groups }} - app_distribution_service_account: ${{ secrets.firebase_app_distribution_service_account }} - version_name: ${{ inputs.android_version_name }} - build_number_offset: ${{ inputs.android_build_number_offset }} + test_gradle_task: ${{ inputs.ANDROID_TEST_GRADLE_TASK }} + package_gradle_task: ${{ inputs.ANDROID_PACKAGE_GRADLE_TASK }} + upload_gradle_task: ${{ inputs.ANDROID_UPLOAD_GRADLE_TASK }} + app_distribution_groups: ${{ inputs.FIREBASE_APP_DISTRIBUTION_GROUPS }} + app_distribution_service_account: ${{ secrets.FIREBASE_APP_DISTRIBUTION_SERVICE_ACCOUNT }} + version_name: ${{ inputs.ANDROID_VERSION_NAME }} + build_number_offset: ${{ inputs.ANDROID_BUILD_NUMBER_OFFSET }} release_notes: ${{ needs.changelog.outputs.changelog }} - kmp_flavor: ${{ inputs.kmp_flavor }} - secret_properties_file: ${{ inputs.android_secret_properties_file }} - secret_properties: ${{ secrets.android_secret_properties }} + kmp_flavor: ${{ inputs.KMP_FLAVOR }} + secret_properties_file: ${{ inputs.ANDROID_SECRET_PROPERTIES_FILE }} + secret_properties: ${{ secrets.ANDROID_SECRET_PROPERTIES }} save_cache: name: Cache last build commit SHA runs-on: ubuntu-latest @@ -225,7 +225,7 @@ jobs: shell: bash run: | echo "${{ github.sha }}" > latest_builded_commit.txt - if [ "${{ inputs.changelog_debug }}" == 'true' ]; then + if [ "${{ inputs.CHANGELOG_DEBUG }}" == 'true' ]; then echo "[DEBUG] Saved commit SHA ${{ github.sha }} to latest_builded_commit.txt" fi - name: Store latest build commit SHA in cache