From 998e5384ffef3c0f771e7d9569ac11636355b84c Mon Sep 17 00:00:00 2001 From: XuqmGroup Date: Sat, 23 May 2026 01:20:57 +0800 Subject: [PATCH] =?UTF-8?q?chore(ci):=20=E6=9B=B4=E6=96=B0=20Jenkins=20?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E4=BB=A5=E6=94=AF=E6=8C=81=E5=A4=9A=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E7=89=88=E6=9C=AC=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 为 Android、Flutter、iOS 和 RN SDK 的 Jenkinsfile 添加模块化版本控制 - 引入版本升级策略选择(major/minor/patch)和自定义版本号功能 - 实现多模块独立版本管理和选择性构建发布 - 更新 iOS SDK Package.swift 以支持独立模块化库 - 修改 iOS SDK podspec 文件以适应新的标签命名约定 - 优化 Jenkins 构建流程以支持按需选择特定模块进行构建和发布 - 修复 iOS 测试中的可选类型转换问题以提高代码健壮性 --- Jenkinsfile | 142 +++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 124 insertions(+), 18 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index bd30242..5f0a311 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -2,28 +2,128 @@ pipeline { agent any parameters { - string(name: 'VERSION', defaultValue: '', description: '发布版本号(留空使用 gradle.properties 中的 PUBLISH_VERSION)') - booleanParam(name: 'RUN_TESTS', defaultValue: true, description: '是否运行自动化测试') - booleanParam(name: 'PUBLISH', defaultValue: true, description: '是否发布到 Nexus') + // ── 版本升级策略 ───────────────────────────────────────────────────── + choice(name: 'VERSION_BUMP', defaultValue: 'patch', + description: '版本升级策略: major(1.0.0→2.0.0), minor(1.0.0→1.1.0), patch(1.0.0→1.0.1)') + booleanParam(name: 'CUSTOM_VERSION', defaultValue: false, + description: '勾选后使用下方自定义版本号(忽略VERSION_BUMP)') + + // 模块自定义版本号(仅CUSTOM_VERSION=true时生效) + string(name: 'CORE_VERSION', defaultValue: '', description: 'sdk-core 自定义版本号(仅CUSTOM_VERSION=true时生效)') + string(name: 'IM_VERSION', defaultValue: '', description: 'sdk-im 自定义版本号') + string(name: 'PUSH_VERSION', defaultValue: '', description: 'sdk-push 自定义版本号') + string(name: 'UPDATE_VERSION', defaultValue: '', description: 'sdk-update 自定义版本号') + string(name: 'WEBVIEW_VERSION', defaultValue: '', description: 'sdk-webview 自定义版本号') + string(name: 'LICENSE_VERSION', defaultValue: '', description: 'sdk-license 自定义版本号') + + // 要构建并发布的模块列表,每行一个(空 = 全部) + string( + name: 'MODULES', + defaultValue: 'sdk-core\nsdk-im\nsdk-push\nsdk-update\nsdk-webview\nsdk-license', + description: '要构建并发布的模块列表,每行一个(空 = 全部)' + ) + + booleanParam(name: 'RUN_TESTS', defaultValue: true, description: '是否运行自动化测试') + booleanParam(name: 'PUBLISH', defaultValue: true, description: '是否发布到 Nexus') } environment { - NEXUS_USER = credentials('nexus-android-user') - NEXUS_PASS = credentials('nexus-android-pass') + NEXUS_USER = credentials('nexus-android-user') + NEXUS_PASS = credentials('nexus-android-pass') } stages { stage('Checkout') { steps { checkout([ - $class: 'GitSCM', - branches: [[name: 'main']], - extensions: [[$class: 'CleanBeforeCheckout']], - userRemoteConfigs: scm.userRemoteConfigs + $class: 'GitSCM', + branches: [[name: 'main']], + extensions: [[$class: 'CleanBeforeCheckout']], + userRemoteConfigs: scm.userRemoteConfigs ]) script { - if (params.VERSION?.trim()) { - bat "powershell -Command \"(Get-Content gradle.properties) -replace '^PUBLISH_VERSION=.*', 'PUBLISH_VERSION=${params.VERSION}' | Set-Content gradle.properties\"" + // 构建 -P 参数字符串 + def versionMap = [ + 'SDK_CORE_VERSION' : params.CORE_VERSION?.trim(), + 'SDK_IM_VERSION' : params.IM_VERSION?.trim(), + 'SDK_PUSH_VERSION' : params.PUSH_VERSION?.trim(), + 'SDK_UPDATE_VERSION' : params.UPDATE_VERSION?.trim(), + 'SDK_WEBVIEW_VERSION' : params.WEBVIEW_VERSION?.trim(), + 'SDK_LICENSE_VERSION' : params.LICENSE_VERSION?.trim(), + ] + + env.VERSION_ARGS = versionMap + .findAll { k, v -> v } + .collect { k, v -> "-P${k}=${v}" } + .join(' ') + + // 解析要操作的模块列表 + def allModules = ['sdk-core', 'sdk-im', 'sdk-push', 'sdk-update', 'sdk-webview', 'sdk-license'] + def requestedRaw = params.MODULES?.trim() + def requested = requestedRaw + ? requestedRaw.split(/[\r\n]+/).collect { it.trim() }.findAll { it } + : allModules + + // 过滤出已知模块名 + def resolved = requested.findAll { allModules.contains(it) } + if (resolved.isEmpty()) { + error("MODULES param produced an empty list after filtering. Check spelling. Provided: ${requestedRaw}") + } + + // 保存为逗号分隔的环境变量供后续阶段使用 + env.PUBLISH_MODULES = resolved.join(',') + + echo "Version args : ${env.VERSION_ARGS ?: '(none — using gradle.properties values)'}" + echo "Modules : ${env.PUBLISH_MODULES}" + } + } + } + + stage('Resolve Versions') { + steps { + script { + if (!params.CUSTOM_VERSION) { + // 从 gradle.properties 读取当前版本号 + def currentVer = sh( + script: "grep '^PUBLISH_VERSION=' gradle.properties | cut -d= -f2", + returnStdout: true + ).trim() + echo "Current PUBLISH_VERSION: ${currentVer}" + + def parts = currentVer.tokenize('.') + while (parts.size() < 3) { parts.add('0') } + switch (params.VERSION_BUMP) { + case 'major': + parts[0] = (parts[0].toInteger() + 1).toString() + parts[1] = '0' + parts[2] = '0' + break + case 'minor': + parts[1] = (parts[1].toInteger() + 1).toString() + parts[2] = '0' + break + case 'patch': + default: + parts[2] = (parts[2].toInteger() + 1).toString() + break + } + def newVer = parts.join('.') + echo "Auto-bumped PUBLISH_VERSION: ${currentVer} → ${newVer}" + + // 更新 gradle.properties + sh "sed -i '' 's/^PUBLISH_VERSION=.*/PUBLISH_VERSION=${newVer}/' gradle.properties" + + // 用新版本号重建所有模块的 VERSION_ARGS + def modules = env.PUBLISH_MODULES.split(',').toList() + def versionMap = [:] + for (mod in modules) { + def propName = "SDK_${mod.replace('sdk-', '').toUpperCase()}_VERSION" + versionMap[propName] = newVer + } + env.VERSION_ARGS = versionMap + .collect { k, v -> "-P${k}=${v}" } + .join(' ') + echo "Updated VERSION_ARGS: ${env.VERSION_ARGS}" } } } @@ -31,7 +131,13 @@ pipeline { stage('Build AARs & APKs') { steps { - bat 'gradlew.bat :sample-app:assembleDebug :sample-app:assembleDebugAndroidTest --no-daemon' + script { + // 构建 sample-app(测试用)和各选中模块的 release + def modules = env.PUBLISH_MODULES.split(',').toList() + def moduleTasks = modules.collect { ":${it}:assembleRelease" }.join(' ') + def testTasks = ':sample-app:assembleDebug :sample-app:assembleDebugAndroidTest' + bat "gradlew.bat ${moduleTasks} ${testTasks} ${env.VERSION_ARGS} --no-daemon" + } } } @@ -96,13 +202,13 @@ pipeline { } stage('Publish to Nexus') { - when { - expression { return params.PUBLISH } - } + when { expression { return params.PUBLISH } } steps { 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" + def modules = env.PUBLISH_MODULES.split(',').toList() + def publishTasks = modules.collect { ":${it}:publish" }.join(' ') + def credArgs = "-PNEXUS_USER=%NEXUS_USER% -PNEXUS_PASSWORD=%NEXUS_PASS%" + bat "gradlew.bat ${publishTasks} ${env.VERSION_ARGS} ${credArgs} --no-daemon" } } } @@ -120,6 +226,6 @@ pipeline { ''' archiveArtifacts artifacts: 'logcat-*.txt', allowEmptyArchive: true } - success { echo "✅ Android SDK 构建成功" } + success { echo "Android SDK 构建成功" } } }