Skip to content

test(swift-sdk): cover imported-wallet history either side of registration #742

test(swift-sdk): cover imported-wallet history either side of registration

test(swift-sdk): cover imported-wallet history either side of registration #742

name: Build and test Kotlin SDK
on:
workflow_call:
workflow_dispatch:
pull_request:
paths:
- 'packages/kotlin-sdk/**'
- 'packages/swift-sdk/**'
- 'Cargo.toml'
- 'Cargo.lock'
- 'packages/rs-*/**'
- 'packages/rs-unified-sdk-jni/**'
- 'packages/rs-sdk-ffi/**'
- 'packages/rs-platform-wallet-ffi/**'
- 'packages/dapi-grpc/**'
- 'packages/data-contracts/**'
- 'packages/*-contract/**'
- 'packages/simple-signer/**'
- 'docs/sdk/sdk-parity-manifest.json'
- 'docs/sdk/KOTLIN_SWIFT_SHARED_PARITY_SPEC.md'
- 'packages/kotlin-sdk/PARITY_SUMMARY.md'
- 'scripts/check_sdk_parity_manifest.py'
- 'scripts/tests/**'
- '.github/workflows/kotlin-sdk-build.yml'
concurrency:
group: kotlin-sdk-${{ github.workflow }}-${{ github.head_ref || github.ref }}
cancel-in-progress: true
jobs:
kotlin-sdk-build:
name: Kotlin SDK build + tests (x86_64 emulator)
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Validate executable SDK parity manifest
run: |
python3 scripts/check_sdk_parity_manifest.py
python3 -m unittest discover -s scripts/tests -p 'test_*.py'
- name: Free disk space
run: |
# The API-35 x86_64 system image + the shielded .so's cargo target
# dir (halo2/Orchard) + gradle outputs overflow the ~21 GB free on
# the runner root fs, surfacing as "No space left on device" during
# system-image install (the emulator then never boots). Reclaim the
# large preinstalled toolchains we don't use before building. None of
# these are needed by this job (JDK via setup-java, Android SDK via
# setup-android, Rust via rustup, NDK reinstalled below).
echo "Before:"; df -h /
sudo rm -rf \
/usr/share/dotnet \
/usr/local/.ghcup \
/opt/ghc \
/opt/hostedtoolcache/CodeQL \
/usr/local/lib/android/sdk/ndk \
/usr/local/share/powershell \
/usr/share/swift \
/opt/microsoft 2>/dev/null || true
sudo docker image prune --all --force 2>/dev/null || true
echo "After:"; df -h /
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
- name: Set up Android SDK
uses: android-actions/setup-android@v3
with:
packages: >-
platforms;android-35
build-tools;35.0.0
ndk;28.1.13356709
platform-tools
- name: Set up Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: x86_64-linux-android
- name: Restore cargo cache
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
target
key: kotlin-sdk-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: |
kotlin-sdk-cargo-
- name: Install cargo-ndk
run: cargo install cargo-ndk --locked
- name: Install protoc v32.0 (repo-standard; apt's 3.21 breaks tenderdash-proto)
run: |
curl -fsSL -o /tmp/protoc.zip https://github.com/protocolbuffers/protobuf/releases/download/v32.0/protoc-32.0-linux-x86_64.zip
sudo unzip -o /tmp/protoc.zip -d /usr/local 'bin/protoc' 'include/*'
protoc --version
- name: Build native library (x86_64, dev profile)
working-directory: packages/kotlin-sdk
env:
ANDROID_NDK_HOME: ${{ env.ANDROID_SDK_ROOT }}/ndk/28.1.13356709
run: ./build_android.sh --abi x86_64 --profile dev --verify
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Build SDK and run unit tests
working-directory: packages/kotlin-sdk
run: ./gradlew :sdk:assembleDebug :sdk:testDebugUnitTest --stacktrace
- name: Build KotlinExampleApp and run app unit tests
working-directory: packages/kotlin-sdk
run: ./gradlew :app:assembleDebug :app:testDebugUnitTest --stacktrace
- name: Compile instrumented test sources (incl. testnet-tagged)
working-directory: packages/kotlin-sdk
run: ./gradlew :sdk:compileDebugAndroidTestKotlin --stacktrace
- name: Enable KVM for emulator
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 instrumented FFI smoke test (API 35 emulator)
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 35
arch: x86_64
profile: pixel_6
disable-animations: true
emulator-options: -no-snapshot -no-window -no-audio -no-boot-anim -camera-back none -dns-server 8.8.8.8,1.1.1.1
working-directory: packages/kotlin-sdk
script: |
# NOTE: android-emulator-runner executes this script line by line —
# each line is its own `sh -c` with no shared state — so every
# command must be self-contained on a single line (multi-line loops
# or cross-line variables silently fail).
# Keep the screen on and never time out. THIS is the fix: the flake
# was the emulator screen turning off mid-run and RE-LOCKING the
# device. The mnemonic MASTER_ALIAS AES key is
# setUnlockedDeviceRequired(true), so once the device re-locks even
# an ENCRYPT throws `InvalidKeyException: Keystore operation failed`
# (see WalletStorage.storeMnemonic). Unlocking alone is not enough —
# a slower suite (more instrumented tests) crosses the screen-off
# deadline before its wallet tests run, which is why this branch
# failed where lighter ones passed. Prevent the re-lock outright.
adb shell settings put system screen_off_timeout 2147483647
adb shell svc power stayon true
# Enroll a device-wide secure lock screen (PIN) — Android Keystore
# refuses to generate an auth-required key
# (setUserAuthenticationRequired(true), used for the identity-key
# KEYS_ALIAS RSA pair) without one enrolled, even though nothing
# here ever prompts for it (private-key ENCRYPT is never auth-gated;
# only DECRYPT is).
adb shell locksettings set-pin 1234
# Unlock the keyguard. With the screen kept on above, the device now
# stays unlocked for the whole run instead of re-locking.
# Credential acceptance and keyguard dismissal can race during a
# cold emulator boot. Retry the complete sequence atomically, then
# fail loudly before tests if the device never reaches unlocked.
for attempt in 1 2 3; do adb shell input keyevent KEYCODE_WAKEUP; adb shell wm dismiss-keyguard; adb shell input text 1234; adb shell input keyevent KEYCODE_ENTER; sleep 2; adb shell wm dismiss-keyguard; sleep 1; adb shell dumpsys trust | grep -q 'deviceLocked=0' && exit 0; done; echo "::error::Emulator is still locked (deviceLocked=1); Keystore-backed tests would fail spuriously."; adb shell dumpsys trust; exit 1
./gradlew :sdk:connectedDebugAndroidTest --stacktrace
- name: Upload test reports on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: kotlin-sdk-test-reports
path: |
packages/kotlin-sdk/sdk/build/reports
packages/kotlin-sdk/sdk/build/outputs/androidTest-results
packages/kotlin-sdk/KotlinExampleApp/app/build/reports