Add AGENTS.md #90
Workflow file for this run
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: CI | |
| on: | |
| pull_request: | |
| push: | |
| branches: | |
| - main | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ci-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| native-tests: | |
| name: Native Go tests | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 20 | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| - name: Set up Go | |
| uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: native/go.mod | |
| cache-dependency-path: native/go.sum | |
| - name: Set up Ruby and Fastlane | |
| uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: "3.4.10" | |
| bundler-cache: true | |
| - name: Run native tests with the race detector | |
| run: bundle exec fastlane android native_tests | |
| android-tests: | |
| name: Android tests and checks | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| - name: Set up JDK 21 | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: temurin | |
| java-version: "21" | |
| cache: gradle | |
| - name: Set up Go | |
| uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: native/go.mod | |
| cache-dependency-path: native/go.sum | |
| - name: Set up Ruby and Fastlane | |
| uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: "3.4.10" | |
| bundler-cache: true | |
| - name: Install Android SDK components | |
| run: | | |
| sdkmanager="$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" | |
| if [[ ! -x "$sdkmanager" ]]; then | |
| echo "sdkmanager is unavailable at $sdkmanager" >&2 | |
| exit 1 | |
| fi | |
| yes | "$sdkmanager" --licenses >/dev/null || true | |
| "$sdkmanager" \ | |
| "platforms;android-36" \ | |
| "build-tools;36.0.0" \ | |
| "ndk;29.0.14206865" | |
| echo "ANDROID_NDK_HOME=$ANDROID_HOME/ndk/29.0.14206865" >> "$GITHUB_ENV" | |
| - name: Run Android checks and verify the unsigned APK | |
| run: bundle exec fastlane android android_checks | |
| - name: Publish PR debug APK | |
| if: github.event_name == 'pull_request' | |
| id: debug_apk_upload | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: megaproxy-pr-${{ github.event.pull_request.number }}-debug-apk | |
| path: app/build/outputs/apk/debug/app-debug.apk | |
| if-no-files-found: error | |
| compression-level: 0 | |
| retention-days: 14 | |
| - name: Publish PR unsigned release APK | |
| if: github.event_name == 'pull_request' | |
| id: unsigned_release_apk_upload | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: megaproxy-pr-${{ github.event.pull_request.number }}-unsigned-release-apk | |
| path: app/build/outputs/apk/release/app-release-unsigned.apk | |
| if-no-files-found: error | |
| compression-level: 0 | |
| retention-days: 14 | |
| - name: Add APK download links to the job summary | |
| if: github.event_name == 'pull_request' | |
| env: | |
| DEBUG_APK_URL: ${{ steps.debug_apk_upload.outputs.artifact-url }} | |
| UNSIGNED_RELEASE_APK_URL: ${{ steps.unsigned_release_apk_upload.outputs.artifact-url }} | |
| run: | | |
| { | |
| echo "## APK artifacts" | |
| echo | |
| echo "- [Download debug APK]($DEBUG_APK_URL) — signed with the disposable Android debug key" | |
| echo "- [Download unsigned release APK]($UNSIGNED_RELEASE_APK_URL) — verified unsigned" | |
| echo | |
| echo "Artifacts expire after 14 days. Neither APK uses the MegaProxy release key." | |
| } >> "$GITHUB_STEP_SUMMARY" | |
| android-ui-tests: | |
| name: Android UI tests | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| steps: | |
| - name: Check out repository | |
| uses: actions/checkout@v6 | |
| - name: Enable KVM device access | |
| run: | | |
| if [[ ! -e /dev/kvm ]]; then | |
| echo "::error::KVM is unavailable on this runner" | |
| exit 1 | |
| fi | |
| 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 | |
| if [[ ! -r /dev/kvm || ! -w /dev/kvm ]]; then | |
| echo "::error::The runner cannot access /dev/kvm" | |
| ls -l /dev/kvm | |
| exit 1 | |
| fi | |
| echo "KVM is available; the emulator will use hardware acceleration" | |
| - name: Set up JDK 21 | |
| uses: actions/setup-java@v5 | |
| with: | |
| distribution: temurin | |
| java-version: "21" | |
| cache: gradle | |
| - name: Set up Go | |
| uses: actions/setup-go@v7 | |
| with: | |
| go-version-file: native/go.mod | |
| cache-dependency-path: native/go.sum | |
| - name: Set up Ruby and Fastlane | |
| uses: ruby/setup-ruby@v1 | |
| with: | |
| ruby-version: "3.4.10" | |
| bundler-cache: true | |
| - name: Install native build dependencies | |
| run: | | |
| sdkmanager="$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" | |
| yes | "$sdkmanager" --licenses >/dev/null || true | |
| "$sdkmanager" "ndk;29.0.14206865" | |
| echo "ANDROID_NDK_HOME=$ANDROID_HOME/ndk/29.0.14206865" >> "$GITHUB_ENV" | |
| - name: Run Compose UI tests on an emulator | |
| uses: reactivecircus/android-emulator-runner@v2.38.0 | |
| with: | |
| api-level: 30 | |
| target: aosp_atd | |
| arch: x86_64 | |
| disable-linux-hw-accel: false | |
| disable-animations: true | |
| emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none | |
| script: bundle exec fastlane android ui_tests | |
| - name: Verify UI tests actually ran | |
| run: | | |
| shopt -s nullglob | |
| reports=(app/build/outputs/androidTest-results/connected/debug/TEST-*.xml) | |
| if (( ${#reports[@]} == 0 )); then | |
| echo "No Android UI test XML reports were produced" >&2 | |
| exit 1 | |
| fi | |
| tests=0 | |
| failures=0 | |
| errors=0 | |
| skipped=0 | |
| for report in "${reports[@]}"; do | |
| suite="$(sed -nE 's/.*tests="([0-9]+)" failures="([0-9]+)" errors="([0-9]+)" skipped="([0-9]+)".*/\1 \2 \3 \4/p' "$report" | head -n 1)" | |
| if [[ -z "$suite" ]]; then | |
| echo "Cannot read test counters from $report" >&2 | |
| exit 1 | |
| fi | |
| read -r suite_tests suite_failures suite_errors suite_skipped <<< "$suite" | |
| (( tests += suite_tests )) || true | |
| (( failures += suite_failures )) || true | |
| (( errors += suite_errors )) || true | |
| (( skipped += suite_skipped )) || true | |
| done | |
| if (( tests < 4 )); then | |
| echo "Expected at least 4 Android UI tests, found $tests" >&2 | |
| exit 1 | |
| fi | |
| if (( failures != 0 || errors != 0 || skipped != 0 )); then | |
| echo "Android UI test results: tests=$tests failures=$failures errors=$errors skipped=$skipped" >&2 | |
| exit 1 | |
| fi | |
| expected_tests=( | |
| everySettingsDestinationOpensAndReturnsThroughTheNavHost | |
| russianLocaleIsAppliedAcrossNavigation | |
| settingsAndProfilesShareTheMainActivityBackStack | |
| trafficUnitsDefaultToIecAndPersistSiSelection | |
| ) | |
| for expected_test in "${expected_tests[@]}"; do | |
| if ! grep -Fq "name=\"$expected_test\"" "${reports[@]}"; then | |
| echo "Expected Android UI test did not run: $expected_test" >&2 | |
| exit 1 | |
| fi | |
| done | |
| echo "Verified Android UI test results: tests=$tests failures=0 errors=0 skipped=0" | |
| - name: Publish UI test report | |
| if: ${{ always() && hashFiles('app/build/outputs/androidTest-results/connected/debug/TEST-*.xml') != '' }} | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: android-ui-test-report | |
| path: | | |
| app/build/reports/androidTests/connected/debug | |
| app/build/outputs/androidTest-results/connected/debug | |
| if-no-files-found: error | |
| retention-days: 14 |