Files
qqq-android/.github/workflows/scanner.yml
T
james.maesandClaude Sonnet 5.5 c55d3002b0 test(ci): run no-device Echo guards
Run the eight fixture, device-identity and redaction guards in the existing verify lane without introducing device operations or additional dependencies.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-01 16:12:32 -06:00

164 lines
7.3 KiB
YAML

name: Scanner Android
on:
push:
branches: [main, 'feature/**', 'fix/**', 'release/**', 'hotfix/**']
pull_request:
workflow_call:
workflow_dispatch:
inputs:
emulator:
description: Run native UI and real-server scanner end-to-end tests
type: boolean
default: true
permissions:
contents: read
concurrency:
group: scanner-${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true
jobs:
verify:
name: Tests, lint, and debug APK
runs-on: ubuntu-24.04
timeout-minutes: 30
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: actions/setup-java@cf277c60eb25467037889841efdb72551f06f6c3 # v4
with:
distribution: temurin
java-version: '21'
- uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4
with:
cache-read-only: ${{ github.event_name == 'pull_request' }}
- name: Verify source headers, whitespace, imports and JavaScript syntax
run: node scripts/ci/check-source-standards.mjs
- name: Run no-device Echo fixture guard tests
run: node --test scripts/ci/scanner-echo-guards.test.mjs
- name: Install required Android SDK packages
run: |
"$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager" "platforms;android-35" "build-tools;34.0.0" "build-tools;35.0.0" "platform-tools"
- name: Verify shared libraries and scanner host
run: >-
./gradlew --no-daemon --console=plain
:qqq:android:core:testDebugUnitTest
:qqq:android:mobileapp:testDebugUnitTest
:scanner-host:testDebugUnitTest
:scanner-host:lintDebug
:scanner-host:assembleDebug
- name: Compile opt-in physical QA acceptance
run: >-
./gradlew --no-daemon --console=plain -PscannerTestBuildType=qa
:scanner-host:assembleQa :scanner-host:assembleQaAndroidTest
- name: Hash debug APK
run: |
mkdir -p scanner-host/build/outputs/apk/debug/notices
cp scanner-host/build/reports/third-party/debug/{aboutlibraries.json,LICENSE,NOTICE} scanner-host/build/outputs/apk/debug/notices/
(cd scanner-host/build/outputs/apk/debug && sha256sum scanner-host-debug.apk notices/* > SHA256SUMS)
- name: Upload installable development APK
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: scanner-debug-${{ github.sha }}
path: scanner-host/build/outputs/apk/debug/
if-no-files-found: error
retention-days: 14
- name: Upload test and lint evidence
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: scanner-checks-${{ github.sha }}
path: |
qqq/android/core/build/test-results/
qqq/android/mobileapp/build/test-results/
scanner-host/build/test-results/
scanner-host/build/reports/
retention-days: 14
emulator:
name: Native UI and real-server scanner E2E
if: github.event_name != 'workflow_dispatch' || inputs.emulator
needs: verify
runs-on: ubuntu-24.04
timeout-minutes: 40
env:
QQQ_CORE_SHA: ecf0f550a0357cec6387c2b54efca128a405a629
SCANNER_SERVER_SHA: 10416938724c9663d66f7848ff2b1a63fe635794
MAVEN_OPTS: -XX:ActiveProcessorCount=2 -Xmx768m
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
persist-credentials: false
- uses: actions/setup-java@cf277c60eb25467037889841efdb72551f06f6c3 # v4
with:
distribution: temurin
java-version: '21'
- uses: gradle/actions/setup-gradle@ed408507eac070d1f99cc633dbcf757c94c7933a # v4
- name: Check out the pinned QQQ core source
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
repository: QRun-IO/qqq
ref: ${{ env.QQQ_CORE_SHA }}
path: .e2e-core
persist-credentials: false
- name: Check out the pinned real QQQ demo
uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4
with:
repository: QRun-IO/qbit-mobile-scanners
ref: ${{ env.SCANNER_SERVER_SHA }}
path: .e2e-server
persist-credentials: false
- name: Verify and build the isolated source-pinned server fixture
env:
JAVA_TOOL_OPTIONS: -XX:ActiveProcessorCount=2 -Xmx768m
run: |
test "$(git -C .e2e-core rev-parse HEAD)" = "$QQQ_CORE_SHA"
test "$(git -C .e2e-server rev-parse HEAD)" = "$SCANNER_SERVER_SHA"
fixture_m2=$(mktemp -d "$RUNNER_TEMP/scanner-fixture-m2.XXXXXX")
core_revision="4.1.0-ci.$QQQ_CORE_SHA"
(cd .e2e-core && ./mvnw --batch-mode --no-transfer-progress \
-Dmaven.repo.local="$fixture_m2" -Drevision="$core_revision" \
-pl qqq-bom,qqq-middleware-api -am clean install)
(cd .e2e-server && ./mvnw --batch-mode --no-transfer-progress \
-Dmaven.repo.local="$fixture_m2" -Dqqq.version="$core_revision" clean install)
(cd .e2e-server && ./mvnw --batch-mode --no-transfer-progress -f demo/pom.xml \
-Dmaven.repo.local="$fixture_m2" -Dqqq.version="$core_revision" clean verify \
dependency:build-classpath -DincludeScope=runtime -Dmdep.outputFile=target/e2e-classpath.txt \
dependency:tree -Dscope=runtime -DoutputFile=target/fixture-dependencies.txt \
help:effective-pom -Doutput=target/fixture-effective-pom.xml)
node scripts/ci/verify-fixture-provenance.mjs .e2e-server "$fixture_m2" "$QQQ_CORE_SHA" "$SCANNER_SERVER_SHA"
- name: Enable hosted-runner hardware acceleration
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 emulator checks
uses: ReactiveCircus/android-emulator-runner@a421e43855164a8197daf9d8d40fe71c6996bb0d # v2
with:
api-level: 35
target: google_apis
arch: x86_64
disable-animations: true
script: |
./gradlew --no-daemon --console=plain :qqqsampleandroidmobileapp:connectedDebugAndroidTest :scanner-host:assembleE2e :scanner-host:assembleE2eAndroidTest
node scripts/ci/scanner-e2e.mjs .e2e-server
- name: Upload emulator evidence
if: always()
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: scanner-emulator-${{ github.sha }}
include-hidden-files: true
path: |
qqqsampleandroidmobileapp/build/reports/androidTests/
qqqsampleandroidmobileapp/build/outputs/androidTest-results/
scanner-host/build/native-e2e/
.e2e-server/demo/target/fixture-provenance.json
.e2e-server/demo/target/fixture-dependencies.txt
.e2e-server/demo/target/fixture-effective-pom.xml
.e2e-core/**/target/surefire-reports/TEST-*.xml
.e2e-server/**/target/surefire-reports/TEST-*.xml
retention-days: 14