2026-05-05 16:06:32 +08:00
|
|
|
|
pipeline {
|
|
|
|
|
|
agent any
|
|
|
|
|
|
|
2026-05-08 18:47:02 +08:00
|
|
|
|
parameters {
|
|
|
|
|
|
string(name: 'VERSION', defaultValue: '', description: '发布版本号(留空使用 gradle.properties 中的 PUBLISH_VERSION)')
|
|
|
|
|
|
booleanParam(name: 'RUN_TESTS', defaultValue: true, description: '是否运行自动化测试')
|
|
|
|
|
|
booleanParam(name: 'PUBLISH', defaultValue: true, description: '是否发布到 Nexus')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-05-05 16:06:32 +08:00
|
|
|
|
environment {
|
|
|
|
|
|
NEXUS_USER = credentials('nexus-android-user')
|
|
|
|
|
|
NEXUS_PASS = credentials('nexus-android-pass')
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stages {
|
2026-05-08 18:47:02 +08:00
|
|
|
|
stage('Checkout') {
|
|
|
|
|
|
steps {
|
2026-05-16 12:48:17 +08:00
|
|
|
|
checkout([
|
|
|
|
|
|
$class: 'GitSCM',
|
|
|
|
|
|
branches: [[name: 'main']],
|
|
|
|
|
|
extensions: [[$class: 'CleanBeforeCheckout']],
|
|
|
|
|
|
userRemoteConfigs: scm.userRemoteConfigs
|
|
|
|
|
|
])
|
2026-05-08 18:47:02 +08:00
|
|
|
|
script {
|
|
|
|
|
|
if (params.VERSION?.trim()) {
|
|
|
|
|
|
bat "powershell -Command \"(Get-Content gradle.properties) -replace '^PUBLISH_VERSION=.*', 'PUBLISH_VERSION=${params.VERSION}' | Set-Content gradle.properties\""
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stage('Build AARs & APKs') {
|
2026-05-05 16:06:32 +08:00
|
|
|
|
steps {
|
2026-05-08 18:47:02 +08:00
|
|
|
|
bat 'gradlew.bat :sample-app:assembleDebug :sample-app:assembleDebugAndroidTest --no-daemon'
|
2026-05-05 16:06:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stage('Start Emulators') {
|
2026-05-08 18:47:02 +08:00
|
|
|
|
when { expression { return params.RUN_TESTS } }
|
2026-05-05 16:06:32 +08:00
|
|
|
|
steps {
|
2026-05-08 18:47:02 +08:00
|
|
|
|
bat '''
|
|
|
|
|
|
start /B emulator -avd Pixel_9_Pro -no-audio -no-boot-anim -no-snapshot-save -no-window
|
|
|
|
|
|
start /B emulator -avd Pixel_9_Pro_2 -no-audio -no-boot-anim -no-snapshot-save -no-window
|
|
|
|
|
|
adb wait-for-device
|
|
|
|
|
|
timeout /t 20 /nobreak >nul
|
|
|
|
|
|
adb devices
|
|
|
|
|
|
'''
|
2026-05-05 16:06:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stage('Install APKs') {
|
2026-05-08 18:47:02 +08:00
|
|
|
|
when { expression { return params.RUN_TESTS } }
|
2026-05-05 16:06:32 +08:00
|
|
|
|
steps {
|
2026-05-08 18:47:02 +08:00
|
|
|
|
bat '''
|
|
|
|
|
|
set APK=sample-app\\build\\outputs\\apk\\debug\\sample-app-debug.apk
|
|
|
|
|
|
set TEST_APK=sample-app\\build\\outputs\\apk\\androidTest\\debug\\sample-app-debug-androidTest.apk
|
|
|
|
|
|
for %%D in (emulator-5554 emulator-5556) do (
|
|
|
|
|
|
adb -s %%D install -r "%APK%"
|
|
|
|
|
|
adb -s %%D install -r "%TEST_APK%"
|
|
|
|
|
|
)
|
|
|
|
|
|
'''
|
2026-05-05 16:06:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stage('Single-Device Tests') {
|
2026-05-08 18:47:02 +08:00
|
|
|
|
when { expression { return params.RUN_TESTS } }
|
2026-05-05 16:06:32 +08:00
|
|
|
|
steps {
|
2026-05-08 18:47:02 +08:00
|
|
|
|
bat '''
|
|
|
|
|
|
set ALL_SINGLE=com.xuqm.sdk.sample.SdkIntegrationTest,com.xuqm.sdk.sample.PushSdkTest,com.xuqm.sdk.sample.NetworkResilienceTest
|
|
|
|
|
|
adb -s emulator-5554 shell am instrument -w -r -e class "%ALL_SINGLE%" "com.xuqm.demo.test/androidx.test.runner.AndroidJUnitRunner" > test-results-5554.txt
|
|
|
|
|
|
findstr /C:"FAILURES" test-results-5554.txt && exit 1 || exit 0
|
|
|
|
|
|
'''
|
2026-05-05 16:06:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stage('Cross-Device Tests') {
|
2026-05-08 18:47:02 +08:00
|
|
|
|
when { expression { return params.RUN_TESTS } }
|
2026-05-05 16:06:32 +08:00
|
|
|
|
parallel {
|
|
|
|
|
|
stage('Sender (5554)') {
|
|
|
|
|
|
steps {
|
2026-05-08 18:47:02 +08:00
|
|
|
|
bat '''
|
|
|
|
|
|
adb -s emulator-5554 shell am instrument -w -r -e class "com.xuqm.sdk.sample.CrossDeviceSenderTest" "com.xuqm.demo.test/androidx.test.runner.AndroidJUnitRunner" > cross-sender.txt
|
|
|
|
|
|
findstr /C:"FAILURES" cross-sender.txt && exit 1 || exit 0
|
|
|
|
|
|
'''
|
2026-05-05 16:06:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
stage('Receiver (5556)') {
|
|
|
|
|
|
steps {
|
2026-05-08 18:47:02 +08:00
|
|
|
|
bat '''
|
|
|
|
|
|
adb -s emulator-5556 shell am instrument -w -r -e class "com.xuqm.sdk.sample.CrossDeviceReceiverTest" "com.xuqm.demo.test/androidx.test.runner.AndroidJUnitRunner" > cross-receiver.txt
|
|
|
|
|
|
findstr /C:"FAILURES" cross-receiver.txt && exit 1 || exit 0
|
|
|
|
|
|
'''
|
2026-05-05 16:06:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
stage('Publish to Nexus') {
|
|
|
|
|
|
when {
|
2026-05-16 12:48:17 +08:00
|
|
|
|
expression { return params.PUBLISH }
|
2026-05-05 16:06:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
steps {
|
2026-05-08 18:47:02 +08:00
|
|
|
|
script {
|
|
|
|
|
|
def versionArg = params.VERSION?.trim() ? "-PPUBLISH_VERSION=${params.VERSION}" : ''
|
|
|
|
|
|
bat "gradlew.bat publish ${versionArg} -PNEXUS_USER=%NEXUS_USER% -PNEXUS_PASSWORD=%NEXUS_PASS% --no-daemon"
|
|
|
|
|
|
}
|
2026-05-05 16:06:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
post {
|
|
|
|
|
|
always {
|
2026-05-08 18:47:02 +08:00
|
|
|
|
bat 'adb emu kill || exit 0'
|
2026-05-05 16:06:32 +08:00
|
|
|
|
archiveArtifacts artifacts: 'test-results-*.txt, cross-*.txt', allowEmptyArchive: true
|
|
|
|
|
|
}
|
|
|
|
|
|
failure {
|
2026-05-08 18:47:02 +08:00
|
|
|
|
bat '''
|
|
|
|
|
|
adb -s emulator-5554 logcat -d -s XuqmImSDK:D XuqmPushSDK:W XuqmUpdateSDK:D > logcat-5554.txt || exit 0
|
|
|
|
|
|
adb -s emulator-5556 logcat -d -s XuqmImSDK:D XuqmPushSDK:W XuqmUpdateSDK:D > logcat-5556.txt || exit 0
|
|
|
|
|
|
'''
|
2026-05-05 16:06:32 +08:00
|
|
|
|
archiveArtifacts artifacts: 'logcat-*.txt', allowEmptyArchive: true
|
|
|
|
|
|
}
|
2026-05-08 18:47:02 +08:00
|
|
|
|
success { echo "✅ Android SDK 构建成功" }
|
2026-05-05 16:06:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|