Merge pull request #3234 from vitorpamplona/l10n_crowdin_translations #8455
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Test/Build | |
| on: | |
| pull_request: | |
| branches: [main] | |
| push: | |
| branches: [main] | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| lint: | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 15 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up JDK 21 | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: 'temurin' | |
| java-version: 21 | |
| # Remote Gradle build cache: writes on push to main, reads on PRs and | |
| # other branches. Caches both `~/.gradle/caches/` and individual task | |
| # outputs, so dependency-only changes hit the cache and skip recompiling | |
| # downstream modules / re-merging native libs (~600MB of work on | |
| # :amethyst alone). Replaces the narrower `cache: gradle` previously on | |
| # actions/setup-java, which only cached `modules-2`. | |
| - name: Set up Gradle | |
| uses: gradle/actions/setup-gradle@v6 | |
| with: | |
| cache-read-only: ${{ github.ref != 'refs/heads/main' }} | |
| - name: Linter (gradle) | |
| run: ./gradlew spotlessCheck :quartz:verifyKmpPurity :commons:verifyKmpPurity | |
| build-desktop: | |
| needs: lint | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| desktop-task: packageDeb | |
| desktop-artifact-name: Desktop Linux DEB | |
| desktop-artifact-path: desktopApp/build/compose/binaries/main/deb/*.deb | |
| - os: macos-latest | |
| desktop-task: packageDmg | |
| desktop-artifact-name: Desktop macOS DMG | |
| desktop-artifact-path: desktopApp/build/compose/binaries/main/dmg/*.dmg | |
| - os: windows-latest | |
| desktop-task: packageMsi | |
| desktop-artifact-name: Desktop Windows MSI | |
| desktop-artifact-path: desktopApp/build/compose/binaries/main/msi/*.msi | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 60 | |
| defaults: | |
| run: | |
| shell: bash | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up JDK 21 | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: 'temurin' | |
| java-version: 21 | |
| - name: Set up Gradle | |
| uses: gradle/actions/setup-gradle@v6 | |
| with: | |
| cache-read-only: ${{ github.ref != 'refs/heads/main' }} | |
| # Compose UI smoke test (DesktopLaunchSmokeTest) uses Skiko which needs | |
| # a display server on Linux. xvfb provides a virtual framebuffer. | |
| - name: Install xvfb (Linux) | |
| if: runner.os == 'Linux' | |
| run: sudo apt-get update && sudo apt-get install -y xvfb | |
| - name: Test + Build Desktop (gradle) | |
| run: | | |
| CMD="./gradlew :quartz:jvmTest :commons:jvmTest :nestsClient:jvmTest :cli:test :desktopApp:test :desktopApp:${{ matrix.desktop-task }}" | |
| if [ "${{ runner.os }}" = "Linux" ]; then | |
| xvfb-run --auto-servernum $CMD | |
| else | |
| $CMD | |
| fi | |
| # jpackage pins libicu to the build host's version (libicu74 on | |
| # ubuntu-24.04). Rewrite the .deb so testers on other Debian/Ubuntu | |
| # releases can install the uploaded artifact. | |
| - name: Relax libicu dependency in .deb | |
| if: matrix.desktop-task == 'packageDeb' | |
| run: | | |
| set -euo pipefail | |
| chmod +x scripts/relax-deb-libicu.sh | |
| scripts/relax-deb-libicu.sh desktopApp/build/compose/binaries/main/deb/*.deb | |
| - name: Upload Desktop Distribution | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: ${{ matrix.desktop-artifact-name }} | |
| path: ${{ matrix.desktop-artifact-path }} | |
| test-quartz-ios: | |
| # Phase 1 of the iOS support plan | |
| # (amethyst/plans/2026-05-24-ios-support.md): keep :quartz green on iOS | |
| # so JVM-only imports can't sneak into commonMain unnoticed. The | |
| # `verifyKmpPurity` task in the lint job is the fast pre-check (Linux, | |
| # ~1s); this job is the real one — compiles for the device variant | |
| # and actually runs the simulator test suite. | |
| needs: lint | |
| runs-on: macos-latest | |
| timeout-minutes: 45 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up JDK 21 | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: 'temurin' | |
| java-version: 21 | |
| - name: Set up Gradle | |
| uses: gradle/actions/setup-gradle@v6 | |
| with: | |
| cache-read-only: ${{ github.ref != 'refs/heads/main' }} | |
| # Two tasks, two purposes: | |
| # - iosSimulatorArm64Test runs the existing iosTest suite on the | |
| # simulator (NIP-04 / NIP-17 / NIP-19 / NIP-49 / AES-GCM / | |
| # Chatroom keys), exercising secp256k1 and CryptoKit-backed | |
| # primitives on a real Apple toolchain. | |
| # - compileTestKotlinIosArm64 catches any device-only compile drift | |
| # (iosArm64 = aarch64-apple-ios) without needing a physical | |
| # device to run on. Compile-only is enough — running on-device | |
| # would require xcodebuild + a provisioning profile. | |
| - name: Test Quartz on iOS | |
| run: | | |
| ./gradlew \ | |
| :quartz:iosSimulatorArm64Test \ | |
| :quartz:compileTestKotlinIosArm64 | |
| # :commons gained iosArm64 + iosSimulatorArm64 targets in Phase 2 of the | |
| # iOS plan. Actual UI / lifecycle wiring will land with the iosApp module | |
| # in Phase 3, but the shared commonMain + commonTest sources are already | |
| # built here against an Apple Native frontend. Same two-task shape as | |
| # quartz above: | |
| # - iosSimulatorArm64Test compiles AND runs the shared commonTest suite | |
| # on the simulator. commonTest is built for every target, so a test | |
| # reaching for a JVM-only API (JUnit, javaClass, @JvmStatic, or a | |
| # jvmAndroid-only symbol) breaks the Apple build even though | |
| # :commons:jvmTest stays green — this is the job that catches it. | |
| # - compileTestKotlinIosArm64 catches device-only compile drift | |
| # (iosArm64 = aarch64-apple-ios) without needing a physical device. | |
| - name: Test Commons on iOS | |
| run: | | |
| ./gradlew \ | |
| :commons:iosSimulatorArm64Test \ | |
| :commons:compileTestKotlinIosArm64 | |
| - name: Upload iOS Test Reports | |
| uses: actions/upload-artifact@v7 | |
| if: failure() | |
| with: | |
| name: Quartz iOS Test Reports | |
| path: quartz/build/reports | |
| test-and-build-android: | |
| needs: lint | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v6 | |
| - name: Set up JDK 21 | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: 'temurin' | |
| java-version: 21 | |
| - name: Set up Gradle | |
| uses: gradle/actions/setup-gradle@v6 | |
| with: | |
| cache-read-only: ${{ github.ref != 'refs/heads/main' }} | |
| # Lint + focused unit tests + benchmark assembly in one Gradle invocation. | |
| # Previously: one invocation for lint, one for `test` (which compiled all | |
| # six amethyst variants × all flavors), one for `assembleBenchmark` | |
| # (re-walking the same task graph). Combining them keeps the daemon hot | |
| # across phases and lets task-level dedup (e.g. compileKotlin) only | |
| # happen once. | |
| # | |
| # `-PdisableAbiSplits=true` produces a single non-split APK per | |
| # (flavor, buildType) instead of 5 (4 ABIs + universal). The CI only | |
| # uploads the universal-equivalent benchmark APK; per-ABI splits were | |
| # being built and discarded, costing ~600MB of stripped_native_libs | |
| # intermediates and several minutes per run. | |
| # | |
| # Test scope: only Debug unit tests for amethyst. The release/benchmark | |
| # variants are compile-equivalent for unit-test purposes; running all six | |
| # adds ~5× the kotlinc work without catching new defects on PRs. Push to | |
| # main still gets the full test matrix via the production-build path. | |
| - name: Test + Build Android (gradle) | |
| run: | | |
| ./gradlew \ | |
| :amethyst:lintFdroidBenchmark \ | |
| :amethyst:lintPlayBenchmark \ | |
| :quartz:jvmTest \ | |
| :commons:jvmTest \ | |
| :nestsClient:jvmTest \ | |
| :amethyst:testFdroidDebugUnitTest \ | |
| :amethyst:testPlayDebugUnitTest \ | |
| :amethyst:assembleBenchmark \ | |
| -PdisableAbiSplits=true | |
| - name: Upload Android Lint Reports | |
| uses: actions/upload-artifact@v7 | |
| if: always() | |
| with: | |
| name: Android Lint Reports | |
| path: amethyst/build/reports/lint-results-*.html | |
| - name: Android Test Report | |
| uses: asadmansr/android-test-report-action@v1.2.0 | |
| if: always() | |
| - name: Upload Test Results | |
| uses: actions/upload-artifact@v7 | |
| if: failure() | |
| with: | |
| name: Test Reports | |
| path: amethyst/build/reports | |
| # With -PdisableAbiSplits=true the APK is named without the ABI/universal | |
| # suffix: amethyst-<flavor>-benchmark.apk. Glob both forms so this still | |
| # works if a contributor runs CI on a branch that doesn't pass the flag. | |
| - name: Upload Play APK Benchmark | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: Play Benchmark APK | |
| path: | | |
| amethyst/build/outputs/apk/play/benchmark/amethyst-play-benchmark.apk | |
| amethyst/build/outputs/apk/play/benchmark/amethyst-play-universal-benchmark.apk | |
| - name: Upload FDroid APK Benchmark | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: FDroid Benchmark APK | |
| path: | | |
| amethyst/build/outputs/apk/fdroid/benchmark/amethyst-fdroid-benchmark.apk | |
| amethyst/build/outputs/apk/fdroid/benchmark/amethyst-fdroid-universal-benchmark.apk | |
| - name: Upload Compose Reports | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: Compose Reports | |
| path: amethyst/build/compose_compiler |