NLDClient-yudde/Tool/build_env/jenkins_iOS_release.groovy

441 lines
23 KiB
Groovy
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// 对应管线任务参数
def PLATFORM_PARAM = "iOS"
def PROFILE_PARAM = "Debug"
def IPA_NAME = "NLDBuild.ipa"
def AAB_PARAM = "fasle"
def DEV_PARAM = false
// 构建时候的参数
def CHANNEL_PARAM = params.Channel
def DEBUGBUILD_PARAM = params.DebugBuild
def HOTUPDATE_PARAM = params.Enable_Hot_Update
def OBFUZ = params.Obfuz
def PackDefaultRes = params.PackDefaultRes
def PackDllRes = params.PackDllRes
def PackConfigRes = params.PackConfigRes
// Jenkins 归档地址
def ARTIFACT_URL = "http://${env.PHXH_BUILDER_IP_ADDRESS}:8080/job/${env.JOB_NAME}/"
def VERSION_PARAM // 版本号 根据项目获取
def OSS_UPLOAD_PATH_PARAM // 上传地址,根据项目获取
def ASSETS_END_POINT_PARAM // Assets endPoint根据项目获取
// 构建地址
def BUILD_PATH
// 日志地址
def log_path
// xcode 项目相关参数
def PROJECT_NAME = "Unity-iPhone"
def SCHEME_NAME = "Unity-iPhone"
def GetRemote(){
if('iOS' == params.Channel)
return 'release/ios_1_0_0';
if('Dev_iOS' == params.Channel)
return 'dev_ios';
else
return params.Channel;
}
def CheckRemoteBranchExists(repoUrl, branchName) {
def result = sh(
script: "git ls-remote --heads ${repoUrl} refs/heads/${branchName}",
returnStdout: true
).trim()
if (result == '') {
echo "警告: 远程分支 ${branchName} 不存在于 ${repoUrl}"
return false
}
echo "远程分支 ${branchName} 存在"
return true
}
def SendMessageToWechat(message){
if (!message) {
return }
def INNER_ROBOT="https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=3c92758c-1128-4931-ac8d-f19669d7befe"
sh "chmod +x $WORKSPACE/Tool/build_tools/send_wechat_message.sh"
sh "$WORKSPACE/Tool/build_tools/send_wechat_message.sh '${INNER_ROBOT}' '@all' '${message}'"
}
def ParseBuildLogError(logPath){
sh "chmod +x $WORKSPACE/Tool/build_tools/parse_unity_build_log.sh"
// 转译 "\[Build Exception\]:" 取消使用
// def exceptionFlag = '\\[Build Exception\\]:'
def errorMessage = sh(script: "${WORKSPACE}/Tool/build_tools/parse_unity_build_log.sh ${logPath} 'error CS' true true", returnStdout: true).trim()
def exceptionMessage = sh(script: "${WORKSPACE}/Tool/build_tools/parse_unity_build_log.sh ${logPath} 'Build Exception' false true", returnStdout: true).trim()
def sceneMessage = sh(script: "${WORKSPACE}/Tool/build_tools/parse_unity_build_log.sh ${logPath} 'Problem detected while' true true", returnStdout: true).trim()
def multipleMessage = sh(script: "${WORKSPACE}/Tool/build_tools/parse_unity_build_log.sh ${logPath} 'Multiple Unity' true false", returnStdout: true).trim()
def processSceneMessage = sh(script: "${WORKSPACE}/Tool/build_tools/parse_unity_build_log.sh ${logPath} 'Failed to process scene' true false", returnStdout: true).trim()
SendMessageToWechat(errorMessage)
SendMessageToWechat(exceptionMessage)
SendMessageToWechat(sceneMessage)
SendMessageToWechat(multipleMessage)
SendMessageToWechat(processSceneMessage)
}
pipeline {
agent any
//agent { label params.BUILD_NODE } // 选择节点
// environment { GITEA_CREDENTIALS = 'gitea_mac2'
// PATH = "/opt/homebrew/bin:${env.PATH}"
// } // 你在 Jenkins 中创建的凭证 ID
stages {
stage('拉最新工程') {
steps {
script {
try {
def currentPath = sh(script: 'pwd', returnStdout: true).trim()
echo "cd ${currentPath}"
// 1. 还原子模块修改
def gitDirExists = sh(script: '[ -d ".git" ] && echo "true" || echo "false"', returnStdout: true).trim()
def scriptPathExists = fileExists("${WORKSPACE}/Tool/build_tools/git_revert_modules_modification.sh")
if (gitDirExists == 'true' && scriptPathExists) {
sh "chmod +x $WORKSPACE/Tool/build_tools/git_revert_modules_modification.sh"
sh "$WORKSPACE/Tool/build_tools/git_revert_modules_modification.sh $WORKSPACE"
}
// 2. 拉取主项目代码
def repoUrl = 'http://1.14.122.170:3000/PHXH/NLDClient.git'
def remote = GetRemote();
echo "获取到分支名字:${remote}"
// 检查远程分支是否存在
if (!CheckRemoteBranchExists(repoUrl, remote)) {
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】远程分支 ${remote} 不存在,使用默认分支 dev"
SendMessageToWechat(message)
remote = 'dev' // 回退到默认分支
}
echo "拉取分支:${remote}"
checkout scmGit(
branches: [[name: "*/${remote}"]],
extensions: [
checkoutOption(60),
lfs(),
cloneOption(noTags: false, reference: '', shallow: false, timeout: 120),
submodule(recursiveSubmodules: true, reference: '', timeout: 1200)
],
userRemoteConfigs: [[url: repoUrl]]
)
// 3. 删除旧 GamePlay_Dll 文件夹
def gameplayDllPath = "${WORKSPACE}/ProjectNLD/Assets/Code/Scripts/GamePlay_Dll"
sh "if [ -d '${gameplayDllPath}' ]; then rm -rf '${gameplayDllPath}'; fi"
// 4. 拉取 GamePlay 仓库
def gameplayTargetPath = "${WORKSPACE}/ProjectNLD/Assets/Code/Scripts/GamePlay"
def gameplayUrl = "http://1.14.122.170:3000/PHXH/GamePlay.git"
def branch = GetRemote();
// 检查远程分支是否存在
if (!CheckRemoteBranchExists(gameplayUrl, branch)) {
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】远程分支 ${branch} 不存在,使用默认分支 dev"
SendMessageToWechat(message)
branch = 'dev' // 回退到默认分支
}
sh "chmod +x ${WORKSPACE}/Tool/build_tools/git_pull_gameplay.sh"
sh "$WORKSPACE/Tool/build_tools/git_pull_gameplay.sh ${gameplayTargetPath} ${gameplayUrl} ${branch}"
} catch (err) {
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】拉最新工程失败"
SendMessageToWechat(message)
error("Failure of the '拉最新工程' stage")
}
}
}
}
stage('获取项目配置') {
steps {
script {
try {
// 将项目相关配置复制到打包路径下
sh "chmod +x $WORKSPACE/Tool/build_tools/copy_env.sh"
sh "$WORKSPACE/Tool/build_tools/copy_env.sh $WORKSPACE/Tool/build_env"
// 将打包机器相关配置复制到打包路径下
echo "copy local env file to $WORKSPACE"
sh "cp /Users/mayuanzheng/Builds/local_env.sh $WORKSPACE/Tool/build_tools/"
} catch (err) {
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】获取项目配置失败"
SendMessageToWechat(message)
error("Failure of the '获取项目配置' stage")
}
}
}
}
stage('修改渠道文件夹') {
steps {
script {
try {
// 先安装pyyaml
sh "pip3 install pyyaml --user"
// 调用python脚本修改渠道文件夹
echo "根据 [${params.Channel}] 渠道修改文件夹"
def channelPath = "${WORKSPACE}/Tool/Channels/${CHANNEL_PARAM}"
def sdkPath = "${WORKSPACE}/Tool/sdk_packages"
echo "Channel Path: ${channelPath}"
echo "SDK Path: ${sdkPath}"
// python脚本: Tool/py_tools/PreHandle.py <sdk_path> <channel_path>
sh "chmod +x $WORKSPACE/Tool/py_tools/PreHandle.py"
// 使用 returnStatus 获取脚本的退出码
def pythonResult = sh(script: "python3 $WORKSPACE/Tool/py_tools/PreHandle.py ${sdkPath} ${channelPath} ${OBFUZ}", returnStatus: true)
if (pythonResult != 0) {
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】修改渠道文件夹失败: pythonResult=${pythonResult}"
SendMessageToWechat(message)
error("Failure of the '修改渠道文件夹' stage")
}
} catch (err) {
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】根据渠道修改工程失败"
SendMessageToWechat(message)
error("Failure of the '修改渠道文件夹' stage")
}
}
}
}
stage('根据渠道修改工程') {
steps {
script {
try {
echo "根据 [${CHANNEL_PARAM}] 渠道修改工程"
sh "chmod +x $WORKSPACE/Tool/build_tools/modify_project_by_channel.sh"
sh "$WORKSPACE/Tool/build_tools/modify_project_by_channel.sh $WORKSPACE ${CHANNEL_PARAM}"
} catch (err) {
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】根据渠道修改工程失败"
SendMessageToWechat(message)
error("Failure of the '根据渠道修改工程' stage")
}
}
}
}
stage('根据渠道获取相关参数') {
steps {
script {
try {
echo "根据 [${params.Channel}] 渠道获取相关参数"
def playersettings = "${WORKSPACE}/Tool/Channels/${CHANNEL_PARAM}/ChannelSetting.yaml"
// 1. 读取并解析 YAML得到一个 Groovy Map
def cfg = readYaml(file: playersettings)
// 2. 提取字段 根据 YAML 键名取值
VERSION_PARAM = (cfg?.Version ?: '').trim()
OSS_UPLOAD_PATH_PARAM = (cfg?.OssRemoteUploadPath ?: '').trim()
ASSETS_END_POINT_PARAM = (cfg?.AssetsEndPoint ?: '').trim()
// 3.其他数据
BUILD_PATH = "Builds/$CHANNEL_PARAM/$PLATFORM_PARAM/$VERSION_PARAM"
log_path="$BUILD_PATH/build.log"
echo "获取到的版本是 ${VERSION_PARAM}, 获取到的上传地址是 ${OSS_UPLOAD_PATH_PARAM}获取到的assets-oss-endpoint是 ${ASSETS_END_POINT_PARAM}"
} catch (err) {
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】根据渠道获取相关参数失败"
SendMessageToWechat(message)
error("Failure of the '根据渠道获取相关参数' stage")
}
}
}
}
stage('打包') {
steps {
sh "chmod +x $WORKSPACE/Tool/build_tools/build_unity.sh"
sh "chmod +x $WORKSPACE/Tool/build_tools/hot_update.sh"
script {
def build_result
if(params.Debug_AllLocal == true)
PROFILE_PARAM="AllLocal"
// Groovy 里 \"\" 标识空字符占位
if(params.Build_InitApp == false){
build_result=sh(script: "$WORKSPACE/Tool/build_tools/hot_update.sh ${VERSION_PARAM} ${PLATFORM_PARAM} ${PROFILE_PARAM} ${CHANNEL_PARAM} ${HOTUPDATE_PARAM} ${DEBUGBUILD_PARAM} \"\" \"\" ${OBFUZ} ${PackDefaultRes} ${PackDllRes} ${PackConfigRes}", returnStatus: true, returnStdout: false)
log_path="$BUILD_PATH/UpdatePreviousBuild.log"
}
else
build_result=sh(script: "$WORKSPACE/Tool/build_tools/build_unity.sh ${VERSION_PARAM} ${PLATFORM_PARAM} ${PROFILE_PARAM} ${CHANNEL_PARAM} ${HOTUPDATE_PARAM} ${DEBUGBUILD_PARAM} ${AAB_PARAM} ${DEV_PARAM} \"\" \"\" ${OBFUZ} \"\" ${PackDefaultRes} ${PackDllRes} ${PackConfigRes}", returnStatus: true, returnStdout: false)
def parse_log = "../../$log_path"
// 打包失败
if(build_result != 0)
{
// 归档并分析日志
archiveArtifacts artifacts: "$log_path" , followSymlinks: false
ParseBuildLogError(parse_log)
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】构建失败"
SendMessageToWechat(message)
error("Failure of the '打包' stage")
}
else{
sh "chmod +x $WORKSPACE/Tool/build_tools/check_unity_build_result.sh"
def check_result = sh(script: "sh $WORKSPACE/Tool/build_tools/check_unity_build_result.sh ${parse_log}", returnStatus: true)
if (check_result != 0) {
// 归档日志
archiveArtifacts artifacts: "$log_path" , followSymlinks: false
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】构建失败 日志捕捉到 Build Finished, Result: Failure."
SendMessageToWechat(message)
error("Failure of the '打包' stage")
}
}
}
}
}
stage('上传资源') {
steps {
script {
def asset_path="$WORKSPACE/ProjectNLD/ServerData/${PLATFORM_PARAM}"
def upload_path="${OSS_UPLOAD_PATH_PARAM}/${CHANNEL_PARAM}/${PLATFORM_PARAM}/${VERSION_PARAM}"
if(params.Upload_Incremental == true)
{
def upload_incremental_result=0
def last_manifest_path="$WORKSPACE/ProjectNLD/ServerData/LastManifests"
sh "chmod +x $WORKSPACE/Tool/build_tools/upload_incremental_oss.sh"
upload_incremental_result = sh(script: "$WORKSPACE/Tool/build_tools/upload_incremental_oss.sh ${asset_path} ${upload_path} ${ASSETS_END_POINT_PARAM} ${last_manifest_path}", returnStatus: true, returnStdout: false)
if(upload_incremental_result != 0)
{
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】上传资源失败"
SendMessageToWechat(message)
error("Failure of the '上传资源' stage")
}
}
else
{
sh "chmod +x $WORKSPACE/Tool/build_tools/upload_oss.sh"
def upload_result=0
upload_result = sh(script: "$WORKSPACE/Tool/build_tools/upload_oss.sh ${asset_path} ${upload_path} ${ASSETS_END_POINT_PARAM}", returnStatus: true, returnStdout: false)
if(upload_result != 0)
{
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】上传资源失败"
SendMessageToWechat(message)
error("Failure of the '上传资源' stage")
}
}
}
}
}
stage('导出IPA') {
steps {
script {
if (params.Build_InitApp == true) {
def project_path="$WORKSPACE/Builds/$CHANNEL_PARAM/$PLATFORM_PARAM/$VERSION_PARAM"
def export_result=0
sh "chmod +x $WORKSPACE/Tool/build_tools/build_xcode_xcodeproj.sh"
export_result = sh(script: "$WORKSPACE/Tool/build_tools/build_xcode_xcodeproj.sh ${PROJECT_NAME} ${SCHEME_NAME} ${project_path} ${OBFUZ}", returnStatus: true, returnStdout: false)
if(export_result != 0)
{
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】导出IPA失败"
SendMessageToWechat(message)
error("Failure of the '导出IPA' stage")
}
}
}
}
}
stage('重命名IPA') {
steps {
script {
if (params.Build_InitApp == true) {
def change_name_result=0
def path="$WORKSPACE/Builds/$CHANNEL_PARAM/$PLATFORM_PARAM/$VERSION_PARAM/"
sh "chmod +x $WORKSPACE/Tool/build_tools/rename_ipa.sh"
change_name_result = sh(script: "$WORKSPACE/Tool/build_tools/rename_ipa.sh ${path}", returnStatus: true, returnStdout: false)
if(change_name_result != 0)
{
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】重命名IPA失败"
SendMessageToWechat(message)
error("Failure of the '重命名IPA' stage")
}
}
}
}
}
// stage('发布debug版本号') {
// steps {
// script {
// sh "chmod +x $WORKSPACE/Tool/build_tools/debug_send_version.sh"
// def result=0
// result = sh(script: "$WORKSPACE/Tool/build_tools/debug_send_version.sh")
// }
// }
// }
/*stage('上传IPA') {
steps {
script {
// 增量更新不需要上传包体
if (params.Build_InitApp == true){
def ipa_path="$WORKSPACE/Builds/$CHANNEL_PARAM/$PLATFORM_PARAM/$VERSION_PARAM/$IPA_NAME"
def upload_path="${OSS_UPLOAD_PATH_PARAM}/${CHANNEL_PARAM}/${PLATFORM_PARAM}/"
def upload_path_with_version="${OSS_UPLOAD_PATH_PARAM}/${CHANNEL_PARAM}/${PLATFORM_PARAM}/${VERSION_PARAM}/"
def upload_result=0
def upload_result_with_version=0
upload_result=sh(script: "$WORKSPACE/Tool/build_tools/upload_oss.sh ${ipa_path} ${upload_path} ${ASSETS_END_POINT_PARAM}", returnStatus: true, returnStdout: false)
upload_result_with_version=sh(script: "$WORKSPACE/Tool/build_tools/upload_oss.sh ${ipa_path} ${upload_path_with_version} ${ASSETS_END_POINT_PARAM}", returnStatus: true, returnStdout: false)
if(upload_result != 0 || upload_result_with_version != 0)
{
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】上传IPA失败"
SendMessageToWechat(message)
error("Failure of the '上传IPA' stage")
}
}
}
}
}*/
stage('上传符号表') {
steps {
script {
// 增量更新不需要上传符号表
if(params.Upload_CrashSight == true && params.Build_InitApp == true)
{
sh "chmod +x $WORKSPACE/Tool/build_tools/upload_ios_symbol_file.sh"
def playersettings = "${WORKSPACE}/Tool/Channels/${CHANNEL_PARAM}/ChannelSetting.yaml"
def cfg = readYaml(file: playersettings)
def symbol_path="$WORKSPACE/Builds/$CHANNEL_PARAM/$PLATFORM_PARAM/$VERSION_PARAM"
def upload_result=0
def crashsightConfig = cfg?."CrashSight_${PLATFORM_PARAM}"
def crashsightId = (crashsightConfig?.id ?: '').trim()
def crashsightKey = (crashsightConfig?.key ?: '').trim()
upload_result = sh(script: "$WORKSPACE/Tool/build_tools/upload_ios_symbol_file.sh ${VERSION_PARAM} ${symbol_path} ${crashsightId} ${crashsightKey}", returnStatus: true, returnStdout: false)
if(upload_result != 0)
{
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】上传符号表异常"
SendMessageToWechat(message)
}
}
}
}
}
stage('归档') {
steps {
script {
try{
archiveArtifacts artifacts: "$log_path" , followSymlinks: false
if (params.Build_InitApp == true)
archiveArtifacts artifacts: "$BUILD_PATH/*.ipa" , followSymlinks: false
}
catch(Exception e){
SendMessageToWechat(e.message + "\r\n" + e.stackTrace)
currentBuild.result = 'FAILURE'
return
}
}
}
}
stage('通知') {
steps {
script {
if (params.Build_InitApp == true) {
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】客户端打包上传成功!下载链接:${ARTIFACT_URL}"
SendMessageToWechat(message)
} else {
def message = "【${PLATFORM_PARAM}】【${VERSION_PARAM}】【Release】【${CHANNEL_PARAM}】客户端增量更新上传成功!下载链接:${ARTIFACT_URL}"
SendMessageToWechat(message)
}
}
}
}
}
}