Files
readest/.github/workflows/android-e2e.yml
T
Huang Xin 4ff96800d2 ci: pin android-emulator-runner by SHA + shard the slow PR test job (#4547)
* ci(security): pin android-emulator-runner action by commit SHA

Scorecard Pinned-Dependencies flagged the two
reactivecircus/android-emulator-runner@v2 usages in android-e2e.yml as
third-party actions not pinned by hash (code-scanning alerts #116, #117).

Pin both to the full commit SHA the v2 tag currently resolves to
(e89f39f = v2.37.0), matching the @<sha> # <version> convention already
used by every other action in this workflow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci(pull-request): shard web unit tests and split out test_extensions

The jsdom unit suite was ~115s of the 280s test_web_app job — the slowest
check on every PR. Split it across two parallel shards with vitest --shard,
and move the browser-extension + koplugin tests into a new test_extensions
job.

- test_web_app: matrix shard [1, 2] running `vitest run --shard=N/2`;
  Playwright + browser tests run on shard 1 only.
- test_extensions: extension tests + browser-ext build run always; the
  koplugin Lua tests (and their ~45s LuaJIT/busted install) run only when
  apps/readest.koplugin/** changed, detected via dorny/paths-filter
  (pinned by SHA; needs pull-requests: read to list PR files).
- package.json: add test:pr:web:unit so CI can append --shard;
  test:pr:web still runs the full sequence locally.

Cuts the PR critical path from ~280s toward ~188s (now build_tauri_app).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* ci(pull-request): isolate koplugin lint + LuaJIT install into test_extensions

build_web_app was the slowest PR job and installed LuaJIT + ran the koplugin
syntax check on every PR. Move all koplugin tooling into test_extensions,
gated on apps/readest.koplugin/** like the koplugin Lua tests already are:

- build_web_app drops the LuaJIT install.
- test_extensions installs LuaJIT/busted and runs `pnpm lint:lua` + `pnpm
  test:lua` only when the koplugin sources changed.
- `pnpm lint` is now web-only (tsgo + biome); `lint:lua` stays a standalone
  script that test_extensions (and local koplugin work) calls directly. This
  also drops koplugin lint from the pre-push hook.
- verification rule updated to match.

Most PRs now skip the koplugin toolchain entirely.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 08:53:51 +02:00

132 lines
4.6 KiB
YAML

name: Android E2E (CDP)
# On-device end-to-end tests: boots an x86_64 Android emulator (KVM), installs
# a debug APK, and runs the CDP-driven selection lane (pnpm test:android).
# Not PR-blocking: runs nightly, on demand, or when a PR is labeled
# `e2e-android`.
on:
workflow_dispatch:
schedule:
- cron: '30 19 * * *'
pull_request:
types: [labeled, synchronize]
concurrency:
group: android-e2e-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
android-e2e:
if: github.event_name != 'pull_request' || contains(github.event.pull_request.labels.*.name, 'e2e-android')
runs-on: ubuntu-latest
timeout-minutes: 90
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
- name: initialize git submodules
run: git submodule update --init --recursive
- name: enable KVM for the 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: setup pnpm
uses: pnpm/action-setup@0e279bb959325dab635dd2c09392533439d90093 # v6
- name: setup node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6
with:
node-version: 24
cache: pnpm
- name: setup Java
uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5
with:
distribution: 'zulu'
java-version: '17'
- name: setup Android SDK
uses: android-actions/setup-android@40fd30fb8d7440372e1316f5d1809ec01dcd3699 # v4
- name: install NDK
run: sdkmanager "ndk;28.2.13676358"
- name: install dependencies
run: pnpm install --frozen-lockfile --prefer-offline
- name: copy pdfjs-dist and simplecc-dist to public directory
run: pnpm --filter @readest/readest-app setup-vendors
- name: install Rust stable
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # stable
with:
targets: x86_64-linux-android
- uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2
with:
workspaces: apps/readest-app/src-tauri
- name: create .env.local file for Next.js
run: |
echo "NEXT_PUBLIC_APP_PLATFORM=tauri" >> .env.local
cp .env.local apps/readest-app/.env.local
- name: build debug APK (x86_64)
env:
NDK_HOME: ${{ env.ANDROID_HOME }}/ndk/28.2.13676358
run: |
cd apps/readest-app
# Only the customized files of gen/android are tracked — regenerate
# the gradle scaffolding, then restore the tracked customizations
# (same flow as the release workflow).
rm -rf src-tauri/gen/android
pnpm tauri android init
pnpm tauri icon ../../data/icons/readest-book.png
git checkout .
# Debug build: signed with the debug keystore, no release secrets
# needed (gradle only loads keystore.properties when it exists).
pnpm tauri android build --debug --target x86_64
APK=$(find src-tauri/gen/android/app/build/outputs/apk -name '*-debug.apk' | head -n 1)
echo "APK=$PWD/$APK" >> "$GITHUB_ENV"
test -n "$APK"
- name: cache AVD snapshot
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
id: avd-cache
with:
path: |
~/.android/avd/*
~/.android/adb*
key: avd-api-34
- name: create AVD snapshot for caching
if: steps.avd-cache.outputs.cache-hit != 'true'
uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a # v2
with:
api-level: 34
arch: x86_64
target: google_apis
force-avd-creation: false
emulator-options: -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: false
script: echo "AVD snapshot created"
- name: run Android e2e lane
uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a # v2
with:
api-level: 34
arch: x86_64
target: google_apis
force-avd-creation: false
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disable-animations: true
script: |
adb install -r "$APK"
cd apps/readest-app && pnpm test:android