From 54e7f2461711f75fe666342d513ad41152bb945f Mon Sep 17 00:00:00 2001 From: Raunak Raj <71929976+bajrangCoder@users.noreply.github.com> Date: Sat, 10 Oct 2026 16:51:55 +0530 Subject: [PATCH 1/4] ci: move native builds out of per-PR CI Match upstream Acode: ci.yml keeps only fast checks (spelling, Biome, unit tests, typecheck, translations). Native tests move to a new native-tests.yml that runs only the platform a PR touches, plus a daily and manual full run. APKs are built only by nightly and on-demand preview releases. Also select the Android edition via androidPackageId (npm pkg set name was a no-op, so the free build was actually paid) and install the required Android SDK packages in the nightly build. --- .github/workflows/ci.yml | 99 ---------------- .github/workflows/native-tests.yml | 172 ++++++++++++++++++++++++++++ .github/workflows/nightly-build.yml | 5 +- 3 files changed, 176 insertions(+), 100 deletions(-) create mode 100644 .github/workflows/native-tests.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e26d82b..e8a9f06 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,102 +107,3 @@ jobs: npm ci --no-audit --no-fund npm run lang check - ios: - name: Acode iOS - runs-on: macos-26 - timeout-minutes: 30 - permissions: - contents: read - 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 - - android: - name: Acode Android (${{ matrix.variant }}, ${{ matrix.distribution }}) - runs-on: ubuntu-latest - timeout-minutes: 45 - 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' - - 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: sdkmanager 'platforms;android-37' 'build-tools;36.0.0' - - name: Select package - run: npm pkg set name=${{ matrix.package }} - - name: Build APK - run: npm run build -- dev apk ${{ matrix.distribution }} - - name: Native tests - run: npm run test:android -- ${{ matrix.distribution }} - - name: Validate minified release bundle - if: matrix.distribution == 'store' - run: npm run build -- prod bundle diff --git a/.github/workflows/native-tests.yml b/.github/workflows/native-tests.yml new file mode 100644 index 0000000..f25c056 --- /dev/null +++ b/.github/workflows/native-tests.yml @@ -0,0 +1,172 @@ +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: sdkmanager 'platforms;android-37' '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 diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index b613e38..e417dc5 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -158,8 +158,11 @@ jobs: run: | npm ci --no-audit --no-fund + - name: Install Android SDK packages + run: sdkmanager 'platforms;android-37' 'build-tools;36.0.0' + - name: Select paid package - run: npm pkg set name=com.foxdebug.acode + run: npm pkg set androidPackageId=com.foxdebug.acode - name: Build normal APK run: | From 42ac77c9b53367f7c8b5d1922cd18106e0f368a3 Mon Sep 17 00:00:00 2001 From: Raunak Raj <71929976+bajrangCoder@users.noreply.github.com> Date: Sat, 10 Oct 2026 17:03:51 +0530 Subject: [PATCH 2/4] fix: CI spelling errors and sdkmanager path sdkmanager is not on PATH on GitHub's Ubuntu runners, so call it from ANDROID_HOME. Allow Apple's udid in typos and fix the onSucess typo. --- .github/workflows/native-tests.yml | 2 +- .github/workflows/nightly-build.yml | 2 +- _typos.toml | 2 ++ src/native/types/sftp.d.ts | 4 ++-- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/native-tests.yml b/.github/workflows/native-tests.yml index f25c056..1349363 100644 --- a/.github/workflows/native-tests.yml +++ b/.github/workflows/native-tests.yml @@ -108,7 +108,7 @@ jobs: - name: Install dependencies run: npm ci --no-audit --no-fund - name: Install Android SDK packages - run: sdkmanager 'platforms;android-37' 'build-tools;36.0.0' + run: $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager 'platforms;android-37' 'build-tools;36.0.0' - name: Select package run: npm pkg set androidPackageId=${{ matrix.package }} - name: Native unit tests diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index e417dc5..8c11c79 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -159,7 +159,7 @@ jobs: npm ci --no-audit --no-fund - name: Install Android SDK packages - run: sdkmanager 'platforms;android-37' 'build-tools;36.0.0' + run: $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager 'platforms;android-37' 'build-tools;36.0.0' - name: Select paid package run: npm pkg set androidPackageId=com.foxdebug.acode diff --git a/_typos.toml b/_typos.toml index e1d830d..35a768b 100644 --- a/_typos.toml +++ b/_typos.toml @@ -57,3 +57,5 @@ multline = "multline" sav = "sav" ist = "ist" Hel = "Hel" +# Apple simulator device identifier +udid = "udid" diff --git a/src/native/types/sftp.d.ts b/src/native/types/sftp.d.ts index 9c92cd2..c40eef5 100644 --- a/src/native/types/sftp.d.ts +++ b/src/native/types/sftp.d.ts @@ -36,12 +36,12 @@ interface Sftp { /** * Executes command on ssh-server * @param command - * @param onSucess + * @param onSuccess * @param onFail */ exec( command: String, - onSucess: (res: ExecResult) => void, + onSuccess: (res: ExecResult) => void, onFail: (err: any) => void, ): void; /** Connects using credentials held by the native profile store. */ From a560aab89312754455b821cbe0290c12c34ec721 Mon Sep 17 00:00:00 2001 From: Raunak Raj <71929976+bajrangCoder@users.noreply.github.com> Date: Sat, 10 Oct 2026 17:05:53 +0530 Subject: [PATCH 3/4] fix: use android-37.0 SDK platform package name --- .github/workflows/native-tests.yml | 2 +- .github/workflows/nightly-build.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/native-tests.yml b/.github/workflows/native-tests.yml index 1349363..af77aaf 100644 --- a/.github/workflows/native-tests.yml +++ b/.github/workflows/native-tests.yml @@ -108,7 +108,7 @@ jobs: - 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' 'build-tools;36.0.0' + 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 diff --git a/.github/workflows/nightly-build.yml b/.github/workflows/nightly-build.yml index 8c11c79..2fd7c4d 100644 --- a/.github/workflows/nightly-build.yml +++ b/.github/workflows/nightly-build.yml @@ -159,7 +159,7 @@ jobs: npm ci --no-audit --no-fund - name: Install Android SDK packages - run: $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager 'platforms;android-37' 'build-tools;36.0.0' + run: $ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager 'platforms;android-37.0' 'build-tools;36.0.0' - name: Select paid package run: npm pkg set androidPackageId=com.foxdebug.acode From 9e560a550cf2c10c96e6f7cc8e7f857adae0b100 Mon Sep 17 00:00:00 2001 From: Raunak Raj <71929976+bajrangCoder@users.noreply.github.com> Date: Sat, 10 Oct 2026 17:11:28 +0530 Subject: [PATCH 4/4] test: drop removed ServiceName.fromKey assertion fromKey was removed from ServiceName; Bridge resolves services through the registry map, so the test now only checks keys are unique. --- .../src/test/java/com/foxdebug/acode/runtime/StartupTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/platforms/android/app/src/test/java/com/foxdebug/acode/runtime/StartupTest.java b/platforms/android/app/src/test/java/com/foxdebug/acode/runtime/StartupTest.java index 7e3c244..ed08c4f 100644 --- a/platforms/android/app/src/test/java/com/foxdebug/acode/runtime/StartupTest.java +++ b/platforms/android/app/src/test/java/com/foxdebug/acode/runtime/StartupTest.java @@ -54,7 +54,6 @@ public void startsAndResumesWithoutReloadingTheEditor() throws Exception { public void exposesEveryTransportKeyOnce() { java.util.HashSet keys = new java.util.HashSet<>(); for (ServiceName name : ServiceName.values()) { - assertSame(name, ServiceName.fromKey(name.getKey())); assertTrue("duplicate key " + name.getKey(), keys.add(name.getKey())); } }