mirror of
https://github.com/pezkuwichain/pezkuwi-wallet-android.git
synced 2026-07-22 18:25:50 +00:00
7dea79dbee
* fix: use arm64-v8a emulator image on macos-14 runners
The "Run balances tests" job has been failing on every scheduled run
for weeks: the emulator requested an x86 system image while
macos-14 GitHub-hosted runners are Apple Silicon (aarch64) - QEMU2
refuses to boot a mismatched-architecture image ("Avd's CPU
Architecture 'x86' is not supported by the QEMU2 emulator on
aarch64 host"), so every adb command against the never-booted
emulator failed with "device not found" for the full 10-minute
boot timeout on every run.
* fix(ci): run balances-test emulator on ubuntu-latest with KVM instead of macos-14
macos-14 (Apple Silicon) GitHub-hosted runners don't expose nested
virtualization to guests, so the Android emulator's HVF backend fails
with HV_UNSUPPORTED and the job times out waiting for boot - this
affects both x86 and arm64-v8a system images, so the arch: arm64-v8a
change alone wasn't sufficient. macos-13 (which previously supported
this via HAXM) was retired by GitHub.
Linux hosted runners support KVM-accelerated emulators once the kvm
device's udev permissions are relaxed, which is the documented setup
for reactivecircus/android-emulator-runner and also faster/cheaper
than macOS runners.
* fix(ci): build instrumentialTest androidTest APK to match AllureAndroidJUnitRunner
run_balances_test.sh has always targeted
io.novafoundation.nova.debug.test/io.qameta.allure.android.runners.AllureAndroidJUnitRunner,
but android_build.yml's "Build debug tests" step built the plain
debug variant's androidTest APK, whose manifest declares the module
default runner (androidx.test.runner.AndroidJUnitRunner, from
allmodules.gradle) - AllureAndroidJUnitRunner is only wired via
testInstrumentationRunner on the dedicated instrumentialTest build
type (app/build.gradle), which was apparently created for exactly
this purpose but never actually wired into CI. Result:
INSTRUMENTATION_FAILED as soon as the emulator boot issue was fixed
and this step was reached for the first time.
instrumentialTest initWith buildTypes.debug (same applicationIdSuffix
'.debug', same default debug signing), so it installs under the same
package next to the already-built debug app APK - only the
androidTest APK's build type needs to change, not the main app build.
Only balances_test.yml sets build-debug-tests: true, so this doesn't
affect any other android_build.yml caller (pull_request.yml has it
explicitly disabled with its own separate pre-existing TODO).
* test: temporarily point android_build.yml ref at this branch for verification
TEMPORARY - reusable workflow calls (uses: ...@ref) pin to that ref's
copy regardless of the caller's branch, so android_build.yml's fix
never actually ran in the previous verification attempts even though
it was committed to this branch. Must revert to @main before merging
this PR, once android_build.yml's changes are on main.
* fix(ci): declare AllureAndroidJUnitRunner on debug build type, not instrumentialTest
AGP only ever compiles one androidTest APK per module, tied to
android.testBuildType (default "debug", never overridden in this
project) - so a testInstrumentationRunner override on any other build
type, including instrumentialTest, is unreachable regardless of which
gradle task or main-app variant is used. That's why the previous
attempt (assembleInstrumentialTestAndroidTest) failed outright: no
such task exists, since androidTest is only ever generated for
testBuildType.
Reverts the previous commit's task/path changes back to
assembleDebugAndroidTest / app/androidTest/debug/..., and instead
moves the testInstrumentationRunner override onto the debug build
type itself, which is what androidTest actually compiles against and
what run_balances_test.sh has always targeted. Also drops the dead
override from instrumentialTest now that it's confirmed non-functional
there.
* debug(ci): dump pm list instrumentation before running balances test
Diagnostic only - the previous fix (testInstrumentationRunner moved
to the debug build type's defaultConfig) still hit the identical
INSTRUMENTATION_FAILED for AllureAndroidJUnitRunner even though both
APKs now install successfully with the corrected paths. Need to see
what PackageManager actually registered for the installed test APK
rather than keep guessing from Gradle DSL evaluation-order theory -
allmodules.gradle's subprojects{} block also sets
testInstrumentationRunner on every module including app, and it's not
yet confirmed which assignment wins.
* fix(ci): use current io.pezkuwichain.wallet package instead of stale upstream name
Diagnostic (pm list instrumentation) confirmed the real, final root
cause: AllureAndroidJUnitRunner IS correctly registered on-device
after the previous fix, but under the app's real applicationId
(io.pezkuwichain.wallet, set in build.gradle since the Pezkuwi rebrand)
- not the pre-rebrand upstream Nova Wallet package
(io.novafoundation.nova) these scripts still hardcoded. Every previous
INSTRUMENTATION_FAILED was simply am instrument targeting a package
that was never installed.
Also fixes the identical stale reference in run_instrumental_tests.sh
(currently unused by any workflow, but has the same bug).
The BalancesIntegrationTest class's own Kotlin package
(io.novafoundation.nova.balances) is untouched - that's the test
class's real source package on disk, unrelated to the app's
applicationId, and was never part of the bug.
* fix(ci): bound run-tests to 25min and unbuffer python output
Latest verification run hung for 1h15m+ inside am instrument with
zero visible progress - had to be cancelled manually. Post-mortem:
Python's stdout is fully buffered (not line-buffered) when piped
under GitHub Actions' `run:`, so the script's own 5s heartbeat prints
(explicitly there to avoid CI's inactivity-based cancellation) never
actually reached the log until the buffer filled near the very end,
making the run look identical to a genuine hang for its entire
duration with no way to tell what BalancesIntegrationTest was doing.
- timeout-minutes: 25 on run-tests bounds any future hang to a fixed,
reasonable ceiling instead of requiring a manual cancel after an
hour+.
- python -u unbuffers stdout so the next run's logs show real-time
heartbeat/output, giving actual visibility into where a hang (or
slow chain RPC) occurs instead of a silent multi-hour gap.
Root cause of the hang itself is still open - this only makes it
diagnosable and bounds its cost.
* fix: skip WSS ChainConnection setup for Tron-based chains
Real root cause of the 1h15m+ hang in the previous verification run
(had to be cancelled manually): ChainRegistry registers all chains
sequentially (diff.newOrUpdated.forEach { registerChain(it) }), and
registerConnection() unconditionally called
connectionPool.setupConnection(chain), which creates a ChainConnection
backed by a WSS-only SocketService - for every chain, with no check
for chain type. Tron's node (https://api.trongrid.io) is a plain REST
API with no WebSocket support, so this connection attempt just hangs
forever with no timeout, and since registration is sequential and
Pezkuwi chains (including Tron) are ordered first in the merged chain
list, every chain after it in the list never finishes registering
either - including all the third-party chains BalancesIntegrationTest
actually exercises.
This isn't just a test problem: any real user with the Tron chain
enabled would hit the same registry-wide freeze during chain sync.
Tron balance/transfer operations already go through their own
TronGridApi REST client (built in the Phase 1/2 Tron work),
independent of ConnectionPool/ChainConnection - confirmed nothing else
reads chainRegistry.getConnection() for a Tron chain id - so skipping
ChainConnection setup entirely for isTronBased chains is safe.
* debug(ci): stream live logcat during test run
Diagnostic only. Previous fix (skip WSS ChainConnection for
isTronBased chains) did NOT resolve the hang - identical symptom
(silent for the full 25min timeout, just heartbeats, nothing from the
actual test process). Need real device-side visibility into what's
actually happening (network calls, coroutine timeouts, ANRs) instead
of guessing blind from am instrument's own stdout/stderr, which stays
completely silent until the process exits.
* debug(ci): SIGQUIT thread dump 3min into a hung run, bump logcat to debug level
Previous diagnostic (live logcat at info level) showed the app staying
genuinely alive (GC cycles, system chatter) but produced zero signal
from the test itself after the initial successful chains.json fetch -
no WSS/DB/coroutine activity visible, likely because relevant logging
is below info level. Static code reading (ChainConnection.setup(),
ChainSyncService.syncUp(), ChainFetcher) hasn't turned up an obvious
blocking call, and this exact hang predates this session by at least
a month (zero successes in the last 100 scheduled runs going back to
2026-06-09) - so it's a real, previously-latent bug in the app/test
itself, never previously reached because every earlier run failed at
an earlier CI-infra stage.
kill -3 on the app process forces ART to dump every thread's Java
stack trace to logcat (the standard ANR-diagnosis technique) - this
should show exactly which coroutine/thread is parked and where,
instead of continuing to guess from log filtering.
* fix(ci): bump run-tests timeout to 90min, drop now-unneeded SIGQUIT diagnostic
With the chain blacklist fixed, the previous run genuinely started
executing the 160-case parameterized test suite (visible TestRunner
started/finished events for real chains) instead of hanging silently
- first time this has happened in this entire investigation.
It still hit the 25min ceiling: each test case has an explicit
withTimeout(80.seconds), and several chains that aren't fully dead
(so not blacklisted) but are slow/unresponsive burn the full 80s
before failing. With 160 total test cases, the worst-case aggregate
easily exceeds 25 minutes even with zero actual hangs - so the
timeout needs to be realistic for the test's own design, not just
long enough to catch a true infinite hang. 90min matches
android_build.yml's existing precedent for this project's CI jobs.
The SIGQUIT-after-3-minutes diagnostic added earlier is now
counterproductive noise: any healthy run legitimately takes far
longer than 3 minutes to get through 160 cases, so it would fire on
every run rather than only genuine hangs. Removed now that its actual
purpose (finding the real hang) is done - the blacklist was the
answer, not something a thread dump would have caught anyway (dead
sockets, not deadlocked application code).
* chore: revert temporary android_build.yml ref pin back to @main
Was pointed at this branch only to verify android_build.yml's own
fixes actually took effect during iteration (reusable workflow calls
resolve against the ref they're pinned to, not the caller's branch).
android_build.yml is now byte-identical to main (the wrong task-name
attempt was fully reverted in an earlier commit), so this is a no-op
functionally - just restoring the correct long-term reference before
merge.
103 lines
2.7 KiB
YAML
103 lines
2.7 KiB
YAML
name: Run balances tests
|
|
|
|
on:
|
|
workflow_dispatch:
|
|
schedule:
|
|
- cron: '0 */8 * * *'
|
|
|
|
jobs:
|
|
build-app:
|
|
uses: pezkuwichain/pezkuwi-wallet-android/.github/workflows/android_build.yml@main
|
|
with:
|
|
branch: ${{ github.head_ref || github.ref_name || 'main' }}
|
|
gradlew-command: assembleDebug
|
|
upload-name: develop-apk
|
|
run-tests: false
|
|
build-debug-tests: true
|
|
free-disk-space: true
|
|
secrets: inherit
|
|
|
|
run-tests:
|
|
needs: [build-app]
|
|
runs-on: ubuntu-latest
|
|
timeout-minutes: 90
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
|
|
- name: Download built artifact
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
name: develop-apk
|
|
path: app
|
|
|
|
- name: Debug path
|
|
run: |
|
|
ls -laR app
|
|
|
|
- name: Add permissions
|
|
run: chmod +x .github/scripts/run_balances_test.sh
|
|
|
|
- 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: Run tests
|
|
uses: reactivecircus/android-emulator-runner@v2
|
|
with:
|
|
disable-animations: true
|
|
profile: Nexus 6
|
|
api-level: 29
|
|
arch: x86_64
|
|
script: .github/scripts/run_balances_test.sh
|
|
|
|
- uses: actions/upload-artifact@v4
|
|
if: always()
|
|
with:
|
|
name: android-results
|
|
path: ./allure-results.tar
|
|
|
|
report:
|
|
needs: [run-tests]
|
|
if: ${{ always() }}
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- name: Download artifact
|
|
uses: actions/download-artifact@v4
|
|
with:
|
|
path: artifacts
|
|
|
|
- name: Unzip results
|
|
run: |
|
|
find artifacts -name allure-results.tar -exec tar -xvf {} \;
|
|
|
|
- name: Debug path
|
|
run: |
|
|
ls -laR
|
|
|
|
- name: Generate report
|
|
uses: ./.github/workflows/report/
|
|
with:
|
|
token: ${{ secrets.ACTIONS_DEPLOY_KEY }}
|
|
keep-reports-history: 30
|
|
|
|
telegram-notification:
|
|
needs: [report]
|
|
runs-on: ubuntu-latest
|
|
if: failure()
|
|
steps:
|
|
- name: Notify Telegram channel
|
|
uses: appleboy/telegram-action@master
|
|
with:
|
|
to: ${{ secrets.TELEGRAM_TO }}
|
|
token: ${{ secrets.TELEGRAM_TOKEN }}
|
|
format: html
|
|
message: |
|
|
💸 Balances tests failed.
|
|
|
|
Test Results: https://pezkuwichain.github.io/balances_test_result/${{ github.run_number }}/index.html
|
|
|
|
Github run: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}
|