Skip to content

Instantly share code, notes, and snippets.

@yueban
Last active July 24, 2022 08:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save yueban/c9d1ab1167eb842648e31511f5543e46 to your computer and use it in GitHub Desktop.
Save yueban/c9d1ab1167eb842648e31511f5543e46 to your computer and use it in GitHub Desktop.
node {
// TODO: replace REPO_URL & WEB_HOOK_URL with yours
def REPO_URL = ''
def WEB_HOOK_URL = ""
// 配置 PATH
withEnv(["PATH+EXTRA=/opt/homebrew/bin:${env.ANDROID_HOME}/platform-tools:${env.ANDROID_HOME}/emulator:${env.ANDROID_HOME}/build-tools/32.0.0:${env.ANDROID_HOME}/cmdline-tools/latest/bin"]) {
stage('pull code') {
// TODO: replace gitlab_jenkins_password with yours
git branch: "develop", url: REPO_URL, credentialsId: 'gitlab_jenkins_password'
}
stage('detekt') {
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE', message: 'detekt fail') {
sh 'rm -rf local.properties'
sh './gradlew clean detekt'
}
if (currentBuild.currentResult == "FAILURE") {
archiveDetektReport()
}
}
stage('java tests') {
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE', message: 'java tests fail') {
sh "./gradlew testDebugUnitTest"
}
archiveTestReport()
}
stage('android tests') {
catchError(buildResult: 'FAILURE', stageResult: 'FAILURE', message: 'android tests fail') {
// find targetSdkVersion
def targetSdkVersion = sh(
script: "cat build.gradle | ggrep -Poi 'TargetSdkVersion = \\K\\d*'",
returnStdout: true
).trim()
// find emulator against targetSdkVersion
def emulatorName = sh(
script: "emulator -list-avds | ggrep -Poi -m1 '\\w+API_$targetSdkVersion'",
returnStdout: true
).trim()
// start emulator
def emulatorPid = sh(
script: """
emulator -avd $emulatorName -no-boot-anim -noaudio -wipe-data -no-window > /dev/null 2>&1 &
echo \$!
""",
returnStdout: true
).trim()
// wait until emulator boot completed
timeout(time: 120, unit: 'SECONDS') {
sh "adb wait-for-device shell 'while [[ -z \$(getprop sys.boot_completed) ]]; do sleep 1; done;'"
}
// run android tests
sh "./gradlew connectedDebugAndroidTest"
// terminate emulator
sh "kill -9 $emulatorPid"
}
archiveAndroidTestReport()
}
// clear workspace
cleanWs notFailBuild: true
// notify feishu bot
if (currentBuild.currentResult == "FAILURE") {
stage('notify') {
notifyFeishuBot(WEB_HOOK_URL, false)
}
}
}
}
def archiveDetektReport() {
publishHTML (target : [allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: "build/reports/detekt",
reportFiles: 'merge.xml',
reportName: "report - detekt",
reportTitles: "report - detekt"])
}
def archiveAndroidTestReport() {
archiveTestReport(true)
}
def archiveTestReport(boolean isAndroid = false) {
def moduleList = sh(
script: """
./gradlew projects | ggrep -Poi ".+Project ':\\K[\\w:]+'" | sort -u | rev | cut -c 2- | rev | tr '\\n' ','
""",
returnStdout: true
).split(",")
moduleList.each { moduleName ->
// resovle subdirectory module
def modulePath = "./${moduleName.replace(':', '/')}"
// whether reports exists
def reportDir
if (isAndroid) {
reportDir = "$modulePath/build/reports/androidTests/connected"
def htmlFileCount = sh(script: "ls -l $reportDir 2>/dev/null | grep .html | wc -l", returnStdout: true).trim().toInteger()
if (htmlFileCount <= 1) {
return
}
} else {
reportDir = "$modulePath/build/reports/tests/testDebugUnitTest"
def testDirExists = sh(script: "(ls $reportDir >> /dev/null 2>&1 && echo true) || echo false", returnStdout: true).trim().toBoolean()
if (!testDirExists) {
return
}
}
def reportName
if (isAndroid) {
reportName = "report - androidTest - $moduleName"
} else {
reportName = "report - test - $moduleName"
}
// android tests output missing last tag "</html>"
if (isAndroid) {
sh "echo '</html>' >> $reportDir/index.html"
}
def failCount = sh(script: "xmllint --xpath '//*[@id=\"failures\"]/div/text()' $reportDir/index.html", returnStdout: true).trim().toInteger()
if (failCount > 0) {
reportName = "(error) $reportName"
}
publishHTML (target : [allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: "$reportDir",
reportFiles: 'index.html',
reportName: "$reportName",
reportTitles: "$reportName"])
}
}
def notifyFeishuBot(String webHookUrl, boolean success) {
def msg
if (success) {
msg = "CI Success: $BUILD_URL"
} else {
msg = "CI Failed: $BUILD_URL"
}
sh """
curl -X POST -H "Content-Type: application/json" \
-d '{"msg_type":"text","content": {"text": "$msg"}}' \
$webHookUrl
"""
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment