diff --git a/.github/workflows/android-cloud-check.yml b/.github/workflows/android-cloud-check.yml new file mode 100644 index 0000000..4c03885 --- /dev/null +++ b/.github/workflows/android-cloud-check.yml @@ -0,0 +1,67 @@ +name: Android Pull Request Check + +on: + workflow_call: + inputs: + ## Required Inputs + LINT_GRADLE_TASKS: + description: "A Gradle task(s) for executing lint check, for example `lintCheck lintRelease`" + required: true + type: string + TEST_GRADLE_TASKS: + description: "A Gradle task(s) for executing unit tests, for example `testReleaseUnitTest` or `testDevEnterpriseUnitTest`" + required: true + type: string + + ## Optional Inputs + TIMEOUT_MINUTES: + description: "Job timeout in minutes" + required: false + type: number + default: 30 + 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' + +jobs: + test: + name: Lint & Tests + runs-on: ubuntu-latest + timeout-minutes: ${{ inputs.TIMEOUT_MINUTES }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.0' + - 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 + - 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 }} \ No newline at end of file diff --git a/.github/workflows/android-cloud-release-firebaseAppDistribution.yml b/.github/workflows/android-cloud-release-firebaseAppDistribution.yml new file mode 100644 index 0000000..811bdcc --- /dev/null +++ b/.github/workflows/android-cloud-release-firebaseAppDistribution.yml @@ -0,0 +1,146 @@ +name: Android Release to Firebase App Distribution + +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 + BUNDLE_GRADLE_TASK: + description: "A Gradle task for assembling app bundle, for example `bundleEnterprise`" + 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 + type: string + + ## Optional Inputs + VERSION_NAME: + description: "Version name. Example: '1.X.X-snapshot'" + required: false + type: string + default: '1.X.X-snapshot' + 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 fill 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 + TIMEOUT_MINUTES: + description: "Job timeout in minutes" + required: false + type: number + default: 30 + 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' + + 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" + 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: + build: + name: Enterprise Build + runs-on: [ ubuntu-latest ] + timeout-minutes: ${{ inputs.TIMEOUT_MINUTES }} + env: + 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 + steps: + - name: Checkout + uses: actions/checkout@v4 + - 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 + - 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 }} + 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 + 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') + + 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 }}" diff --git a/.github/workflows/android-cloud-release-googlePlay.yml b/.github/workflows/android-cloud-release-googlePlay.yml new file mode 100644 index 0000000..616a39e --- /dev/null +++ b/.github/workflows/android-cloud-release-googlePlay.yml @@ -0,0 +1,132 @@ +name: Android Release to Google Play + +on: + workflow_call: + inputs: + ## Required Inputs + VERSION_NAME: + description: "Build version name" + required: true + type: string + BUNDLE_GRADLE_TASK: + 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 + type: string + GOOGLE_PLAY_WHATSNEW_DIRECTORY: + description: "Path to directory with changelog files according to documentation in https://github.com/r0adkll/upload-google-play" + required: true + type: string + + ## Optional Inputs + 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: 'prod' + SECRET_PROPERTIES_FILE: + description: "A path to file that fill 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 + CHANGES_NOT_SENT_FOR_REVIEW: + description: 'A changesNotSentForReview Google Play flag. Enable when last google review failed, disable when last review was successful.' + type: boolean + required: false + default: false + TIMEOUT_MINUTES: + description: "Job timeout in minutes" + required: false + type: number + default: 30 + 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' + + 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 + GOOGLE_PLAY_PUBLISH_SERVICE_ACCOUNT: + required: true + description: "JSON key of service account with permissions to upload build to Google Play" + 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: + build: + name: Release Build + runs-on: [ ubuntu-latest ] + timeout-minutes: ${{ inputs.TIMEOUT_MINUTES }} + env: + EXCLUDE_AAB_FILTER: .*intermediate + steps: + - name: Checkout + uses: actions/checkout@v4 + - 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 + - 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) }} diff --git a/.github/workflows/ios-kmp-selfhosted-build.yml b/.github/workflows/ios-kmp-selfhosted-build.yml index a0298d2..b5d38bf 100644 --- a/.github/workflows/ios-kmp-selfhosted-build.yml +++ b/.github/workflows/ios-kmp-selfhosted-build.yml @@ -12,6 +12,12 @@ on: 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\"" type: string required: false + timeout_minutes: + description: "Job timeout in minutes" + type: number + required: false + default: 30 + secrets: MATCH_PASSWORD: required: true @@ -31,60 +37,36 @@ on: Private App Store Connect API issuer key for submitting build to App Store. jobs: - detect-changes: - name: Detect Changes - runs-on: ubuntu-latest - outputs: - # Matches all files which can affect iOS build, when changed - iosFiles: ${{ steps.file-changes.outputs.iosFiles }} - # Matches all files which can affect Android build, when changed - androidFiles: ${{ steps.file-changes.outputs.androidFiles }} + build: + runs-on: self-hosted + timeout-minutes: ${{ inputs.timeout_minutes }} steps: - name: Checkout uses: actions/checkout@v4 - - name: Detect Changes - uses: dorny/paths-filter@v2 - id: file-changes with: - base: ${{ github.ref }} - filters: | - iosFiles: - - "!(androidApp/**)" - androidFiles: - - "!(iosApp/**)" - build: - runs-on: self-hosted - timeout-minutes: 30 - needs: detect-changes - if: ${{ needs.detect-changes.outputs.iosFiles == 'true' }} - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - lfs: ${{ inputs.use_git_lfs }} - - name: Setup Gradle - uses: gradle/gradle-build-action@v2 - - 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 - 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 + lfs: ${{ inputs.use_git_lfs }} + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + - 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 + 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-test.yml b/.github/workflows/ios-kmp-selfhosted-test.yml index b4bc641..1b16c23 100644 --- a/.github/workflows/ios-kmp-selfhosted-test.yml +++ b/.github/workflows/ios-kmp-selfhosted-test.yml @@ -12,52 +12,31 @@ on: 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\"" type: string required: false - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref }} - cancel-in-progress: true + timeout_minutes: + description: "Job timeout in minutes" + type: number + required: false + default: 30 jobs: - detect-changes: - name: Detect Changes - runs-on: ubuntu-latest - outputs: - # Matches all files which can affect iOS build, when changed - iosFiles: ${{ steps.file-changes.outputs.iosFiles }} - # Matches all files which can affect Android build, when changed - androidFiles: ${{ steps.file-changes.outputs.androidFiles }} + test: + name: Test + runs-on: self-hosted + timeout-minutes: ${{ inputs.timeout_minutes }} steps: - name: Checkout uses: actions/checkout@v4 - - name: Detect Changes - uses: dorny/paths-filter@v3 - id: file-changes with: - filters: | - iosFiles: - - "!(androidApp/**)" - androidFiles: - - "!(iosApp/**)" - test: - runs-on: self-hosted - timeout-minutes: 30 - needs: detect-changes - if: ${{ needs.detect-changes.outputs.iosFiles == 'true' }} - - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - lfs: ${{ inputs.use_git_lfs }} - fetch-depth: 0 - - name: Setup Gradle - uses: gradle/gradle-build-action@v2 - - name: Fastlane Test - working-directory: iosApp - run: | - gem install bundler - bundle install --jobs 4 --retry 3 - bundle exec fastlane test - env: - DANGER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} - CUSTOM_VALUES: ${{ inputs.custom_values }} + lfs: ${{ inputs.use_git_lfs }} + fetch-depth: 0 + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + - name: Fastlane Test + working-directory: iosApp + run: | + gem install bundler + bundle install --jobs 4 --retry 3 + bundle exec fastlane test + env: + DANGER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CUSTOM_VALUES: ${{ inputs.custom_values }} diff --git a/.github/workflows/kmp-cloud-detect-changes.yml b/.github/workflows/kmp-cloud-detect-changes.yml new file mode 100644 index 0000000..5520ffc --- /dev/null +++ b/.github/workflows/kmp-cloud-detect-changes.yml @@ -0,0 +1,56 @@ +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. +# +# The following project structure is assumed: Android app in `androidApp/` path and iOS app in `iosApp/` path +# relative to the repository root. +# +# It produces two outputs: +# - `iosFiles`: Will be set to 'true' if any files affecting iOS build were changed +# - `androidFiles`: Will be set to `true` if any files affecting Android build were changed +# +# Usage: +# 1. Call this workflow first in your trigger workflows +# 2. Use the outputs to conditionally run platform-specific workflows +# +# Example: +# jobs: +# changes: +# uses: ./.github/workflows/util_detect_changes.yml +# ios-build: +# needs: changes +# if: ${{ needs.changes.outputs.iosFiles == 'true' }} +# uses: ./.github/workflows/build_ios.yml + +on: + workflow_call: + outputs: + iosFiles: + description: "Whether files affecting iOS build changed (all files except those in androidApp/)" + value: ${{ jobs.detect-changes.outputs.iosFiles }} + androidFiles: + description: "Whether files affecting Android build changed (all files except those in iosApp/)" + value: ${{ jobs.detect-changes.outputs.androidFiles }} + +jobs: + detect-changes: + name: Detect Changes + runs-on: ubuntu-latest + outputs: + # Matches all files which can affect iOS build if changed + iosFiles: ${{ steps.file-changes.outputs.iosFiles }} + # Matches all files which can affect Android build if changed + androidFiles: ${{ steps.file-changes.outputs.androidFiles }} + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Detect Changes + uses: dorny/paths-filter@v3 + id: file-changes + with: + filters: | + iosFiles: + - "!(androidApp/**)" + androidFiles: + - "!(iosApp/**)" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/README.md b/README.md index 674f02c..1eb3ae4 100644 --- a/README.md +++ b/README.md @@ -6,42 +6,46 @@ This repo contains reusable workflows. These workflows are automatically set up when creating projects using [iOS project template](https://github.com/futuredapp/iOS-project-template). -If you want to import them manually to your workflow configuration add a job like this: +If you want to import them manually, reference a reusable workflow in your trigger workflow: ```yml jobs: - {name}: - uses: futuredapp/.github/.github/workflows/{platform}-{runner}-{action}.yml@main + { name }: + uses: futuredapp/.github/.github/workflows/{platform}-{runner}-{action}.yml@1.0.0 secrets: # Secrets to be passed to called workflow key: ${{ secrets.key }} ``` Name the job first and choose its platform, runner and action. -Check the reusable workflow file and pass alll the required secrets to it. +Check the reusable workflow file and pass all the required secrets to it. 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. | +| 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. | ## Contributors All contributions are welcome! -Current maintainer is [Matěj Kašpar Jirásek](https://github.com/mkj-is), . +Current maintainer is [Jakub Marek](https://github.com/jmarek41), and [Matej Semančík](https://github.com/matejsemancik), . ## License