diff --git a/.github/workflows/android.yml b/.github/workflows/merge-queue.yml similarity index 55% rename from .github/workflows/android.yml rename to .github/workflows/merge-queue.yml index b792fc7be..4311fe9df 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/merge-queue.yml @@ -1,98 +1,46 @@ -name: Android CI +name: Android CI (Merge Queue) on: - push: - branches: [ main ] - paths-ignore: - - "**.md" - - ".idea/**" - - ".gitignore" - - ".gitmodules" - - pull_request: - branches: [ main ] merge_group: types: [checks_requested] - workflow_dispatch: - concurrency: - group: build-${{ github.ref }} + group: build-mq-${{ github.ref }} cancel-in-progress: true jobs: - build: runs-on: ubuntu-latest if: github.repository == 'meshtastic/Meshtastic-Android' timeout-minutes: 30 - steps: - - - name: Checkout code - uses: actions/checkout@v4 - with: - submodules: 'recursive' - - - name: Validate Gradle wrapper - uses: gradle/actions/wrapper-validation@v4 - - - name: Set up JDK 21 - uses: actions/setup-java@v4 - with: - java-version: '21' - distribution: 'jetbrains' - - - name: Setup Gradle - uses: gradle/actions/setup-gradle@v4 - with: - cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} - build-scan-publish: true - build-scan-terms-of-use-url: 'https://gradle.com/terms-of-service' - build-scan-terms-of-use-agree: 'yes' - add-job-summary: always - - - name: Check lint - run: ./gradlew lintFdroidDebug lintGoogleDebug --configuration-cache --scan - - - name: Build debug artifacts - run: ./gradlew assembleDebug --configuration-cache --scan - - - name: Run local tests - run: ./gradlew testFdroidDebug testGoogleDebug --configuration-cache --scan - - - name: Upload debug artifact - uses: actions/upload-artifact@v4 - with: - name: fdroidDebug - path: app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk - retention-days: 30 - - - name: Upload build reports - if: ${{ !cancelled() }} - uses: actions/upload-artifact@v4 - with: - name: build-reports - path: app/build/reports - retention-days: 30 - - detekt: - runs-on: ubuntu-latest - timeout-minutes: 10 - - steps: - - name: Checkout code uses: actions/checkout@v4 with: submodules: 'recursive' - + - name: Validate Gradle wrapper + uses: gradle/actions/wrapper-validation@v4 - name: Set up JDK 21 uses: actions/setup-java@v4 with: java-version: '21' distribution: 'jetbrains' - + - name: Cache Gradle User Home + uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle.properties', 'settings.gradle*') }} + restore-keys: | + gradle-${{ runner.os }}- + - name: Cache Android build cache + uses: actions/cache@v4 + with: + path: ~/.android/build-cache + key: android-build-cache-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle.properties', 'settings.gradle*') }} + restore-keys: | + android-build-cache-${{ runner.os }}- - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 with: @@ -101,41 +49,72 @@ jobs: build-scan-terms-of-use-url: 'https://gradle.com/terms-of-service' build-scan-terms-of-use-agree: 'yes' add-job-summary: always + - name: Check lint + run: ./gradlew lintFdroidDebug lintGoogleDebug --configuration-cache --scan + - name: Build debug artifacts + run: ./gradlew assembleDebug --configuration-cache --scan + - name: Run local tests + run: ./gradlew testFdroidDebug testGoogleDebug --configuration-cache --scan + detekt: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: 'recursive' + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'jetbrains' + - name: Cache Gradle User Home + uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle.properties', 'settings.gradle*') }} + restore-keys: | + gradle-${{ runner.os }}- + - name: Cache Android build cache + uses: actions/cache@v4 + with: + path: ~/.android/build-cache + key: android-build-cache-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle.properties', 'settings.gradle*') }} + restore-keys: | + android-build-cache-${{ runner.os }}- + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} + build-scan-publish: true + build-scan-terms-of-use-url: 'https://gradle.com/terms-of-service' + build-scan-terms-of-use-agree: 'yes' + add-job-summary: always - name: Check detekt run: ./gradlew detekt --configuration-cache --scan - - name: Upload build reports - if: ${{ !cancelled() }} - uses: actions/upload-artifact@v4 - with: - name: detekt-reports - path: app/build/reports - retention-days: 30 - androidTest: runs-on: ubuntu-latest timeout-minutes: 15 strategy: matrix: api-level: [26, 35] - steps: - uses: actions/checkout@v4 with: submodules: 'recursive' - - 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 - - uses: actions/setup-java@v4 with: java-version: '21' distribution: 'jetbrains' - - uses: gradle/actions/setup-gradle@v4 with: cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} @@ -143,7 +122,6 @@ jobs: build-scan-terms-of-use-url: 'https://gradle.com/terms-of-service' build-scan-terms-of-use-agree: 'yes' add-job-summary: always - - uses: actions/cache@v4 id: avd-cache with: @@ -151,13 +129,6 @@ jobs: ~/.android/avd/* ~/.android/adb* key: avd-${{ matrix.api-level }} - - - 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 - - name: create AVD and generate snapshot for caching if: steps.avd-cache.outputs.cache-hit != 'true' uses: reactivecircus/android-emulator-runner@v2 @@ -168,7 +139,6 @@ jobs: emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none disable-animations: true script: echo "Generated AVD snapshot for caching." - - uses: reactivecircus/android-emulator-runner@v2 env: ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL: 60 @@ -179,11 +149,3 @@ jobs: emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -no-metrics -camera-back none disable-animations: true script: ./gradlew :app:connectedFdroidDebugAndroidTest --configuration-cache --scan && ( killall -INT crashpad_handler || true ) - - - name: Upload Test Results - if: ${{ !cancelled() }} - uses: actions/upload-artifact@v4 - with: - name: android-test-reports-api-${{ matrix.api-level }} - path: app/build/outputs/androidTest-results/ - retention-days: 30 diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml new file mode 100644 index 000000000..bdf41ef29 --- /dev/null +++ b/.github/workflows/pull-request.yml @@ -0,0 +1,175 @@ +name: Android CI (PR) + +on: + pull_request: + branches: [ main ] + +concurrency: + group: build-pr-${{ github.ref }} + cancel-in-progress: true + +jobs: + build: + runs-on: ubuntu-latest + if: github.repository == 'meshtastic/Meshtastic-Android' + timeout-minutes: 30 + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: 'recursive' + - name: Validate Gradle wrapper + uses: gradle/actions/wrapper-validation@v4 + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'jetbrains' + - name: Cache Gradle User Home + uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle.properties', 'settings.gradle*') }} + restore-keys: | + gradle-${{ runner.os }}- + - name: Cache Android build cache + uses: actions/cache@v4 + with: + path: ~/.android/build-cache + key: android-build-cache-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle.properties', 'settings.gradle*') }} + restore-keys: | + android-build-cache-${{ runner.os }}- + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} + build-scan-publish: true + build-scan-terms-of-use-url: 'https://gradle.com/terms-of-service' + build-scan-terms-of-use-agree: 'yes' + add-job-summary: always + - name: Check lint + run: ./gradlew lintFdroidDebug lintGoogleDebug --configuration-cache --scan + - name: Build debug artifacts + run: ./gradlew assembleDebug --configuration-cache --scan + - name: Run local tests + run: ./gradlew testFdroidDebug testGoogleDebug --configuration-cache --scan + - name: Upload debug artifact + uses: actions/upload-artifact@v4 + with: + name: fdroidDebug + path: app/build/outputs/apk/fdroid/debug/app-fdroid-debug.apk + retention-days: 14 + - name: Upload build reports + uses: actions/upload-artifact@v4 + with: + name: build-reports + path: app/build/reports + retention-days: 14 + + detekt: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + submodules: 'recursive' + - name: Set up JDK 21 + uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'jetbrains' + - name: Cache Gradle User Home + uses: actions/cache@v4 + with: + path: | + ~/.gradle/caches + ~/.gradle/wrapper + key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle.properties', 'settings.gradle*') }} + restore-keys: | + gradle-${{ runner.os }}- + - name: Cache Android build cache + uses: actions/cache@v4 + with: + path: ~/.android/build-cache + key: android-build-cache-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'gradle.properties', 'settings.gradle*') }} + restore-keys: | + android-build-cache-${{ runner.os }}- + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v4 + with: + cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} + build-scan-publish: true + build-scan-terms-of-use-url: 'https://gradle.com/terms-of-service' + build-scan-terms-of-use-agree: 'yes' + add-job-summary: always + - name: Check detekt + run: ./gradlew detekt --configuration-cache --scan + - name: Upload build reports + uses: actions/upload-artifact@v4 + with: + name: detekt-reports + path: app/build/reports + retention-days: 14 + + androidTest: + runs-on: ubuntu-latest + timeout-minutes: 15 + strategy: + matrix: + api-level: [26, 35] + steps: + - uses: actions/checkout@v4 + with: + submodules: 'recursive' + - 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 + - uses: actions/setup-java@v4 + with: + java-version: '21' + distribution: 'jetbrains' + - uses: gradle/actions/setup-gradle@v4 + with: + cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }} + build-scan-publish: true + build-scan-terms-of-use-url: 'https://gradle.com/terms-of-service' + build-scan-terms-of-use-agree: 'yes' + add-job-summary: always + - uses: actions/cache@v4 + id: avd-cache + with: + path: | + ~/.android/avd/* + ~/.android/adb* + key: avd-${{ matrix.api-level }} + - name: create AVD and generate snapshot for caching + if: steps.avd-cache.outputs.cache-hit != 'true' + uses: reactivecircus/android-emulator-runner@v2 + with: + api-level: ${{ matrix.api-level }} + arch: x86_64 + force-avd-creation: false + emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none + disable-animations: true + script: echo "Generated AVD snapshot for caching." + - uses: reactivecircus/android-emulator-runner@v2 + env: + ANDROID_EMULATOR_WAIT_TIME_BEFORE_KILL: 60 + with: + api-level: ${{ matrix.api-level }} + arch: x86_64 + force-avd-creation: false + emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -no-metrics -camera-back none + disable-animations: true + script: ./gradlew :app:connectedFdroidDebugAndroidTest --configuration-cache --scan && ( killall -INT crashpad_handler || true ) + - name: Upload Test Results + uses: actions/upload-artifact@v4 + with: + name: android-test-reports-api-${{ matrix.api-level }} + path: app/build/outputs/androidTest-results/ + retention-days: 14