Repository navigation
Native Tests #30
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: Native Tests | |
| # Native suites are slow (macOS runners, Gradle), so PRs only run the platform | |
| # whose code they touch; the daily run catches breakage coming from src/. | |
| on: | |
| push: | |
| branches: | |
| - main | |
| paths: | |
| - 'platforms/**' | |
| - 'dev/**' | |
| - 'tests/fixtures/ssh/**' | |
| - 'package.json' | |
| - 'package-lock.json' | |
| - '.github/workflows/native-tests.yml' | |
| pull_request: | |
| paths: | |
| - 'platforms/**' | |
| - 'dev/**' | |
| - 'tests/fixtures/ssh/**' | |
| - 'package.json' | |
| - 'package-lock.json' | |
| - '.github/workflows/native-tests.yml' | |
| schedule: | |
| - cron: "0 5 * * *" | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| changes: | |
| name: Detect changed platforms | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| outputs: | |
| android: ${{ steps.filter.outputs.android }} | |
| ios: ${{ steps.filter.outputs.ios }} | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| if: github.event_name == 'push' || github.event_name == 'pull_request' | |
| - name: Detect changed files | |
| id: filter | |
| if: github.event_name == 'push' || github.event_name == 'pull_request' | |
| uses: dorny/paths-filter@v4 | |
| with: | |
| filters: | | |
| shared: &shared | |
| - 'dev/config.js' | |
| - 'dev/sync.js' | |
| - 'dev/scripts/native.js' | |
| - 'dev/scripts/build.sh' | |
| - 'package.json' | |
| - 'package-lock.json' | |
| - '.github/workflows/native-tests.yml' | |
| android: | |
| - *shared | |
| - 'platforms/android/**' | |
| - 'dev/storage_manager.mjs' | |
| - 'dev/scripts/android.js' | |
| ios: | |
| - *shared | |
| - 'platforms/ios/**' | |
| - 'dev/ios/**' | |
| - 'dev/scripts/ios.js' | |
| - 'dev/scripts/iosAds.js' | |
| - 'tests/fixtures/ssh/**' | |
| android: | |
| name: Android (${{ matrix.variant }}, ${{ matrix.distribution }}) | |
| needs: changes | |
| if: needs.changes.outputs.android == 'true' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - variant: paid | |
| package: com.foxdebug.acode | |
| distribution: store | |
| - variant: free | |
| package: com.foxdebug.acodefree | |
| distribution: store | |
| - variant: paid | |
| package: com.foxdebug.acode | |
| distribution: fdroid | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| submodules: recursive | |
| - uses: actions/setup-java@v6 | |
| with: | |
| distribution: temurin | |
| java-version: '26' | |
| cache: gradle | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| - name: Install dependencies | |
| run: npm ci --no-audit --no-fund | |
| - name: Install Android SDK packages | |
| run: $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager 'platforms;android-37.0' 'build-tools;36.0.0' | |
| - name: Select package | |
| run: npm pkg set androidPackageId=${{ matrix.package }} | |
| - name: Native unit tests | |
| run: npm run test:android -- ${{ matrix.distribution }} | |
| ios: | |
| name: iOS | |
| needs: changes | |
| if: needs.changes.outputs.ios == 'true' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' | |
| runs-on: macos-26 | |
| timeout-minutes: 30 | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| submodules: recursive | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: '24' | |
| cache: npm | |
| - name: Install dependencies | |
| run: npm ci --no-audit --no-fund | |
| - name: Install Alpine runtime build tools | |
| run: brew install meson ninja llvm lld | |
| - name: Prepare local iOS configuration | |
| run: cp platforms/ios/Config.xcconfig.example platforms/ios/Config.xcconfig | |
| - name: Select iPhone and iPad simulators with working StoreKit testing | |
| id: simulator | |
| run: | | |
| node <<'JS' | |
| const { execFileSync } = require('node:child_process'); | |
| const { appendFileSync } = require('node:fs'); | |
| const { devices } = JSON.parse(execFileSync('xcrun', ['simctl', 'list', 'devices', 'available', '--json'])); | |
| // iOS 26.3–26.5 fails SKTestSession configuration in command-line runs: | |
| // https://developer.apple.com/forums/thread/826971 | |
| const supported = ['iOS-18-6', 'iOS-26-2'].flatMap(version => | |
| devices[`com.apple.CoreSimulator.SimRuntime.${version}`] || []); | |
| for (const [family, output] of [['iPhone', 'id'], ['iPad', 'ipad']]) { | |
| const device = supported.find(device => device.isAvailable && | |
| device.deviceTypeIdentifier?.startsWith(`com.apple.CoreSimulator.SimDeviceType.${family}-`)); | |
| if (!device) throw new Error(`Install an iOS 18.6 or 26.2 ${family} simulator for integration tests`); | |
| appendFileSync(process.env.GITHUB_OUTPUT, `${output}=${device.udid}\n`); | |
| } | |
| JS | |
| - name: Build and run simulator tests with SSH and FTP fixtures | |
| run: | | |
| python3 -m venv .ios-build/ssh-fixture-venv | |
| .ios-build/ssh-fixture-venv/bin/pip install -r tests/fixtures/ssh/requirements.txt | |
| .ios-build/ssh-fixture-venv/bin/python tests/fixtures/ssh/server.py -- npm run test:ios -- --target=${{ steps.simulator.outputs.id }} | |
| - name: Run iPad startup and native UI checks | |
| run: | | |
| checks=() | |
| for test in AppBridgeTests SystemUITests KeyboardLayoutTests PlatformUITests HapticControlsTests DocumentsPickerTests ShareTests PreviewBrowserTests FilesBrowserTests BrowserBridgeTests; do | |
| checks+=("-only-testing:runnerTests/$test") | |
| done | |
| checks+=("-only-testing:runnerUITests/AppIconUITests") | |
| xcodebuild -project platforms/ios/runner.xcodeproj -scheme runner \ | |
| -configuration Debug -sdk iphonesimulator \ | |
| -destination 'platform=iOS Simulator,id=${{ steps.simulator.outputs.ipad }}' \ | |
| -derivedDataPath .ios-build -clonedSourcePackagesDirPath .ios-build/SourcePackages \ | |
| -parallel-testing-enabled NO -collect-test-diagnostics never \ | |
| "${checks[@]}" CODE_SIGNING_ALLOWED=YES CODE_SIGN_IDENTITY=- test-without-building |