chore(ci): 更新 Jenkins 配置以支持多模块版本管理

- 为 Android、Flutter、iOS 和 RN SDK 的 Jenkinsfile 添加模块化版本控制
- 引入版本升级策略选择(major/minor/patch)和自定义版本号功能
- 实现多模块独立版本管理和选择性构建发布
- 更新 iOS SDK Package.swift 以支持独立模块化库
- 修改 iOS SDK podspec 文件以适应新的标签命名约定
- 优化 Jenkins 构建流程以支持按需选择特定模块进行构建和发布
- 修复 iOS 测试中的可选类型转换问题以提高代码健壮性
这个提交包含在:
XuqmGroup 2026-05-23 01:20:57 +08:00
父节点 eb27e8f112
当前提交 998e5384ff

142
Jenkinsfile vendored
查看文件

@ -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 构建成功" }
}
}