美文网首页
iOS-Unity2018.4.24f1使用Jenkins自动化

iOS-Unity2018.4.24f1使用Jenkins自动化

作者: OneKeyV | 来源:发表于2021-05-13 16:55 被阅读0次

    适合iOS工程是Unity为主导,native代码是作为插件形式接入。
    本文脚本是从Unity生成xcode工程之后开始执行,不一定完全适用,请按照自己需求进行修改。

    注意修改脚本中“xxxxxx”的地方。

    一.安装xcodeproj

    #安装ruby xcodeproj库
    $gem install xcodeproj
    #如果提示没有权限运行下面这条命令:
    $sudo gem install xcodeproj
    

    二、配置xcodeproj工程

    #执行脚本示例:
    ruby '配置脚本文件路径' 'Unity生成的xcode工程根目录'
    #或者增加参数可自动打开工程:
    ruby '配置脚本文件路径' 'Unity生成的xcode工程根目录'  1
    
    require "fileutils"
    require 'xcodeproj'
    
    xcodeproj_path_directory = ARGV[0]
    @config_asset_directory = File.dirname(__FILE__) + "/"
    
    FileUtils.cd(xcodeproj_path_directory) do
        is_auto_open_xcodeproj = ARGV[1]
    
        #工程中target名称
        TARGET_NAME = "xxxxxx"
    
        #打开项目工程.xcodeproj
        project_path = "#{TARGET_NAME}.xcodeproj"
        project = Xcodeproj::Project.open(project_path)
    
        #找到需要操作的target
        targetIndex = 0
        project.targets.each_with_index do |target,index|
            if target.name == TARGET_NAME
                targetIndex = index
            end
        end
        target = project.targets[targetIndex]
    
        #删除目录
        def delete_directory(dirPath)
            if File.directory?(dirPath)
                Dir.foreach(dirPath) do |subFile|
                    if subFile != '.' and subFile != '..'
                        delete_directory(dirPath + "/" + subFile);
                    end
                end
                Dir.rmdir(dirPath);
        #       puts "删除目录:#{dirPath}"
            else
        #       puts "删除文件:#{dirPath}"
                File.delete(dirPath);
            end
        end
    
        #拷贝文件
        def copy(from, to)
          File.open(from) do |input|
            File.open(to, "w") do |output|
              output.write(input.read)
            end
          end
        end
    
        #拷贝目录
        def copy_directory(from_path, to_path)
            if File.directory?(from_path)
                if File::exist?(to_path) == false
                    Dir::mkdir(to_path)
                    puts "\033[40m\033[37m创建文件夹: #{to_path}\033[0m\n"
                end
                
                Dir.foreach(from_path) do |sub_from_file|
                    if sub_from_file != '.' && sub_from_file != '..' && sub_from_file != ".DS_Store"
                        need_copy_file = from_path + "/" + sub_from_file
                        need_create_file = to_path + "/" + sub_from_file
        #               puts "递归遍历文件夹:#{need_copy_file}; #{need_create_file}"
                        copy_directory(need_copy_file, need_create_file)
                    end
                end
            else
                if File::exist?(to_path)
                    puts "\033[33m文件已存在,删除:#{to_path}\033[0m\n"
                    File.delete(to_path)
                end
                puts "\033[40m\033[37m创建文件:#{to_path}\033[0m\n"
                copy(from_path, to_path)
            end
        end
    
        #判断引用是否存在
        def exist_file_reference?(build_phase, file_name)
            if file_name != "." && file_name != ".." && file_name != " " && file_name != ".DS_Store" then
                build_phase.files.each do |file|
                    return true if file.file_ref.name == file_name
                end
            end
            false
        end
    
        #添加resource引用
        def add_resource_file_reference(project, group, file_name)
            project.targets.each do |target|
                next unless TARGET_NAME == target.name
    
                build_phase = target.resources_build_phase
                
                next if exist_file_reference?(build_phase, file_name)
                file_ref = group.new_reference(file_name)
                build_phase.add_file_reference(file_ref, false)
                puts "添加 #{file_name} reference\n"
                project.save
            end
        end
    
        #添加bundle文件并添加引用
        def add_asset_file(project, target, file_names)
            project.targets.each do |target|
                next unless TARGET_NAME == target.name
                
                file_names.each do |file_name|
                    old_file_full_path = @config_asset_directory + file_name
                    new_file_full_path = "./" + file_name
                    
        #           if File::exist?(new_file_full_path)
        #               puts "\033[32m#{file_name}已经添加过! #{new_file_full_path}\n\033[0m\n"
        #           else
                        if File::exist?(old_file_full_path)
                            #拷贝旧文件至新文件位置
                            FileUtils.cp_r(old_file_full_path, new_file_full_path)
                            #添加文件引用
                            if File::exist?(new_file_full_path)
                                add_resource_file_reference(project, project.main_group, new_file_full_path)
                                puts "\033[32m添加#{file_name}配置完成! #{new_file_full_path}\n\033[0m\n"
                            else
                                puts "\033[41mERROR:#{file_name}拷贝失败!!!#{old_file_full_path}\n"
                                exit
                            end
                        else
                            puts "\033[41mERROR:#{file_name}文件不存在!!!#{old_file_full_path}\n"
                            exit
                        end
        #           end
                end
            end
        end
    
        #add system framework
        def add_system_frameworks(project, names, optional = false)
            project.targets.each do |target|
                next unless TARGET_NAME == target.name
    
                build_phase = target.frameworks_build_phase
                framework_group = project.frameworks_group
    
                names.each do |name|
                    next if exist_file_reference?(build_phase, "#{name}.framework")
                    path = "System/Library/Frameworks/#{name}.framework"
                    file_ref = framework_group.new_reference(path)
                    file_ref.name = "#{name}.framework"
                    file_ref.source_tree = 'SDKROOT'
                    build_file = build_phase.add_file_reference(file_ref)
                    if optional
                        build_file.settings = { 'ATTRIBUTES' => ['Weak'] }
                    end
                    puts "添加 #{path} reference\n"
                end
                puts "\033[32mSystem framework reference添加完成\n\033[0m\n"
            end
        end
    
        #add system tbd
        def add_system_tbds(project, names, optional = false)
            project.targets.each do |target|
                next unless TARGET_NAME == target.name
    
                build_phase = target.frameworks_build_phase
                framework_group = project.frameworks_group
    
                names.each do |name|
                    next if exist_file_reference?(build_phase, "#{name}.tbd")
                    path = "usr/lib/#{name}.tbd"
                    file_ref = framework_group.new_reference(path)
                    file_ref.name = "#{name}.tbd"
                    file_ref.source_tree = 'SDKROOT'
                    build_file = build_phase.add_file_reference(file_ref)
                    if optional
                        build_file.settings = { 'ATTRIBUTES' => ['Weak'] }
                    end
                    puts "添加 #{path} reference\n"
                end
                puts "\033[32mSystem tbd 引用添加完成\n\033[0m\n"
            end
        end
    
        #添加bundle文件配置
        def add_bundle_files(project, target)
            file_names = ["xxxxxx.entitlements", "LaunchScreen-iPad.png", "LaunchScreen-iPad.storyboard", "LaunchScreen-iPhone.storyboard", "LaunchScreen-iPhoneLandscape.png", "LaunchScreen-iPhonePortrait.png"]
            add_asset_file(project, target, file_names)
        end
    
        #替换UnityAppController.h、UnityAppController.mm
        def replace_unity_app_controller(project, target)
            project.targets.each do |target|
                next unless TARGET_NAME == target.name
                file_names = ["UnityAppController.h", "UnityAppController.mm"]
                target_direcory_path = "./Classes/"
    
                file_names.each do |file_name|
                    old_file_full_path = @config_asset_directory + file_name
                    new_file_full_path = target_direcory_path + file_name
                    
                    #拷贝旧文件至新文件位置
                    FileUtils.cp_r(old_file_full_path, new_file_full_path)
                end
                puts "\033[32m替换UnityAppController.h、UnityAppController.mm完成\n\033[0m\n"
            end
        end
    
        #替换Unity生成的启动资源
        def replace_unity_launch_screen_resouce(project, target)
            project.targets.each do |target|
                next unless TARGET_NAME == target.name
                file_names = ["LaunchScreen-iPad.png", "LaunchScreen-iPad.storyboard", "LaunchScreen-iPhone.storyboard", "LaunchScreen-iPhoneLandscape.png", "LaunchScreen-iPhonePortrait.png"]
    
                file_names.each do |file_name|
                    old_file_full_path = @config_asset_directory + file_name
                    new_file_full_path = "./" + file_name
                    
                    #拷贝旧文件至新文件位置
                    FileUtils.cp_r(old_file_full_path, new_file_full_path)
                end
                puts "\033[32m替换Unity生成的启动资源完成\n\033[0m\n"
            end
        end
    
        #替换Images.xcassets文件夹
        def replace_assets_file(project, target)
            old_file_full_path = @config_asset_directory + "Images.xcassets"
            new_file_full_path = "./#{TARGET_NAME}/Images.xcassets"
            
            if File::exist?(new_file_full_path)
                puts "删除旧资源文件夹:#{new_file_full_path}"
                delete_directory(new_file_full_path);
            else
                puts "\033[41mERROR:#{new_file_full_path}不存在!!!\n"
                exit
            end
            
            puts "创建新资源文件夹:#{new_file_full_path}"
            FileUtils.cp_r(old_file_full_path, "./#{TARGET_NAME}")
        #   copy_directory(old_file_full_path, new_file_full_path)
            puts "\033[32m替换新资源文件夹完成\n\033[0m\n"
        end
    
        #替换Info.plist文件
        def replace_info_plist_file(project, target)
            old_file_full_path = @config_asset_directory + "Info.plist"
            if File::exist?(old_file_full_path)
                new_file_full_path = "./Info.plist"
                copy(old_file_full_path, new_file_full_path)
                puts "\033[32m替换info.plist文件完成\n\033[0m\n"
            else
                puts "\033[41mERROR:#{old_file_full_path}不存在!!!\n"
                exit
            end
        end
    
        #配置Build Settings
        def add_build_settings(project, target)
            target.build_configurations.each do |config|
            #   获得build settings
                build_settings = config.build_settings
                build_settings["GCC_PREPROCESSOR_DEFINITIONS"] = "DEBUG=1"
                puts "GCC_PREPROCESSOR_DEFINITIONS ==>  DEBUG=1"
                build_settings["CURRENT_PROJECT_VERSION"] = 0
                puts "CURRENT_PROJECT_VERSION ==>  0"
                build_settings["CODE_SIGN_ENTITLEMENTS"] = "xxxxxx.entitlements"
                puts "Build Settings: CODE_SIGN_ENTITLEMENTS ==>  xxxxxx.entitlements"
                build_settings["ARCHS"] = "arm64";
                puts "Build Settings: ARCHS ==>  arm64"
                build_settings["CODE_SIGN_STYLE"] = "Automatic"
                puts "Build Settings: CODE_SIGN_STYLE ==>  Automatic"
                build_settings["CODE_SIGN_IDENTITY"] = "Apple Development"
                puts "Build Settings: CODE_SIGN_IDENTITY ==>  Apple Development"
                build_settings["DEVELOPMENT_TEAM"] = "xxxxxx"
                puts "Build Settings: DEVELOPMENT_TEAM ==>  xxxxxx"
                build_settings["PROVISIONING_PROFILE_SPECIFIER"] = ""
                puts "Build Settings: PROVISIONING_PROFILE_SPECIFIER ==>  "
                build_settings["ENABLE_BITCODE"] = "NO";
                puts "Build Settings: ENABLE_BITCODE ==>  NO"
                build_settings["GCC_C_LANGUAGE_STANDARD"] = "gnu99";
                puts "Build Settings: GCC_C_LANGUAGE_STANDARD ==>  gnu99"
                build_settings["GCC_ENABLE_OBJC_EXCEPTIONS"] = "YES";
                puts "Build Settings: GCC_ENABLE_OBJC_EXCEPTIONS ==>  YES"
                puts "\033[32m#{config.name}模式Build Settings 设置完成\n\033[0m\n"
                project.save
            end
        end
    
        #######################################        Begin   ###########################################
    
        puts "\033[1m开始配置#{TARGET_NAME}.xcodeproj...\033[0m\n "
    
        #配置Build_Settings
        add_build_settings(project, target)
    
        #添加系统动态库
        system_frameworks_names = ["AudioToolbox", "AssetsLibrary", "AVFoundation", "AVKit", "CFNetWork", "CoreGraphics", "CoreMedia", "CoreMotion", "CoreLocation", "CoreText", "CoreVideo", "Foundation", "MobileCoreServices", "iAd", "StoreKit", "Photos", "MapKit", "Security", "WebKit", "AppTrackingTransparency", "CoreTelephony", "ImageIO"]
        add_system_frameworks(project, system_frameworks_names, false)
    
        #添加系统tdb库
        system_tbds_names = ["libresolv", "libz", "libsqlite3", "libc++"]
        add_system_tbds(project, system_tbds_names, false)
    
        #替换UnityAppController.h、UnityAppController.mm
        replace_unity_app_controller(project, target)
    
        #替换Unity生成的启动资源
        replace_unity_launch_screen_resouce(project, target)
    
        #添加Associated Domains文件配置
        add_bundle_files(project, target)
    
        #替换Info.plist文件
        replace_info_plist_file(project, target)
    
        #替换Images.xcassets文件夹
        replace_assets_file(project, target)
    
        #置灰iPhone X横条
        UIRectEdgeOldStr = "- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures\n{\n    UIRectEdge res = UIRectEdgeNone;\n    if (UnityGetDeferSystemGesturesTopEdge())\n        res |= UIRectEdgeTop;\n    if (UnityGetDeferSystemGesturesBottomEdge())\n        res |= UIRectEdgeBottom;\n    if (UnityGetDeferSystemGesturesLeftEdge())\n        res |= UIRectEdgeLeft;\n    if (UnityGetDeferSystemGesturesRightEdge())\n        res |= UIRectEdgeRight;\n    return res;\n}\n\n- (BOOL)prefersHomeIndicatorAutoHidden\n{\n    return UnityGetHideHomeButton();\n}"
    
        UIRectEdgeNewStr = "- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures\n{\n   return UIRectEdgeAll;\n}"
    
        File.open("./Classes/UI/UnityViewControllerBase+iOS.mm","r:utf-8") do |lines|
            read = lines.read.clone
            if read[UIRectEdgeNewStr]
                puts "已置灰iPhoneX横条"
            else
                buffer = read.gsub(UIRectEdgeOldStr,UIRectEdgeNewStr)
                File.open("./Classes/UI/UnityViewControllerBase+iOS.mm","w"){|l|
                    l.write(buffer)
                }
            end
        end
        puts "\033[32m置灰iPhone X横条完成\n\033[0m\n"
    
        #修改UNITY_TRAMPOLINE_IN_USE配置
        UNITY_TRAMPOLINE_IN_USE_old = "#define UNITY_USES_REMOTE_NOTIFICATIONS 0"
        UNITY_TRAMPOLINE_IN_USE_new = "#define UNITY_USES_REMOTE_NOTIFICATIONS 1"
    
        File.open("./Classes/Preprocessor.h","r:utf-8") do |lines|
            read = lines.read.clone
            if read.include?(UNITY_TRAMPOLINE_IN_USE_new)
                puts "\nPreprocessor.h已修改UNITY_USES_REMOTE_NOTIFICATIONS为1"
            else
                buffer = read.gsub(UNITY_TRAMPOLINE_IN_USE_old,UNITY_TRAMPOLINE_IN_USE_new)
                File.open("./Classes/Preprocessor.h","w"){|l|
                    l.write(buffer)
                }
            end
        end
        puts "\033[32mPreprocessor.h修改UNITY_USES_REMOTE_NOTIFICATIONS为1\n\033[0m\n"
    
        project.save
    
        puts "\033[1m结束配置#{TARGET_NAME}.xcodeproj\033[0m\n "
    
        if is_auto_open_xcodeproj == '1'
            puts " 🎉🎉🎉 \033[44m#{TARGET_NAME}.xcodeproj配置已经全部完成,2秒后将自动打开工程, Have fun!\033[0m\n"
            sleep 2
            system "open -- #{project_path}"
        else
            puts " 🎉🎉🎉 \033[44m#{TARGET_NAME}.xcodeproj配置已经全部完成,Have fun!\033[0m\n"
        end
    
    end
    
    exit
    
    

    三、编译Xcode工程、导出ipa、发布ipa包到fir和AppStore

    #!/bin/sh
    
    #Jenkins工作URL
    JENKINS_URL=$1
    
    #Jenkins BRANCH_NAME
    JECKINS_BRANCH_NAME=$2
    
    #Jenkins Job User ID
    JECKINS_BUILD_USER_ID=$3
    
    #版本号
    BUNDLE_VERSION=$4
    
    #build号
    BUNDLE_BUILD_VERSION=$5
    
    #应用网络环境
    APP_ENVIRONMENT=$6
    
    #打包类型(DEBUG、RELEASE、ALL)
    ORIGINAL_DISTRIBUTION_METHOD=$7
    
    #打包类型(DEBUG、RELEASE、ALL)
    DISTRIBUTION_METHOD=$7
    
    #fir更新日志
    FIR_CHANGE_LOG=$8
    
    #是否上传至OSS
    IS_UPLOAD_TO_OSS=$9
    
    echo ''
    echo "JENKINS_URL——${JENKINS_URL}——1111"
    echo "JECKINS_BRANCH_NAME——${JECKINS_BRANCH_NAME}——2222"
    echo "JECKINS_BUILD_USER_ID——${JECKINS_BUILD_USER_ID}——3333"
    echo "BUNDLE_VERSION——${BUNDLE_VERSION}——4444"
    echo "BUNDLE_BUILD_VERSION——${BUNDLE_BUILD_VERSION}——5555"
    echo "APP_ENVIRONMENT——${APP_ENVIRONMENT}——6666"
    echo "DISTRIBUTION_METHOD——${DISTRIBUTION_METHOD}——7777"
    echo "FIR_CHANGE_LOG——${FIR_CHANGE_LOG}——8888"
    echo "IS_UPLOAD_TO_OSS--${IS_UPLOAD_TO_OSS}--9999"
    echo ''
    
    #Jenkins脚本目录
    JENKINS_ROOT_DIR="/Users/${USER}/Desktop/Project/Script"
    
    #Unity代码目录
    UNITY_ROOT_DIR="/Users/${USER}/Desktop/Project/Unity_IOS/xxxxx"
    
    #iOS代码目录
    NATIVE_ROOT_DIR="/Users/${USER}/Desktop/Project/Native/iOS"
    
    #iOS打包脚本目录
    IOS_BUILD_SCRIPT_DIR="/Users/${USER}/Desktop/Project/Script"
    
    #iOS打包储存根目录
    IOS_BUILD_SAVE_DIR="/Users/${USER}/Desktop/Project/Local/iOS"
    
    #获取脚本执行目录
    SCRIP_PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
    
    #iOS工程目录
    PROJECT_PATH="${NATIVE_ROOT_DIR}/Project"
    
    #进入工程目录
    cd "${PROJECT_PATH}"
    
    #获取工程名
    PROJECT_NAME=`find . -name *.xcodeproj | awk -F "[/.]" '{print $(NF-1)}'`
    
    #scheme名
    SCHEME_NAME=${PROJECT_NAME}
    
    #获取工程plist配置文件
    INFO_PLIST_PATH="${PROJECT_PATH}/Info.plist"
    
    #PROJECT_TYPE 项目如果是用cocoapod,就改为 xcworkspace,否则用 xcodeproj
    PROJECT_TYPE=xcodeproj
    #打包类型
    if [ "$PROJECT_TYPE" = "xcodeproj" ]
    then
      PROJECT_BUILD_TYPE=project
    else
      PROJECT_BUILD_TYPE=workspace
    fi
    
    if [ -e "${PROJECT_PATH}/${PROJECT_NAME}.${PROJECT_TYPE}" ]
    then
      echo ''
      echo "存在${PROJECT_NAME}.${PROJECT_TYPE}工程"
    else
       echo '/// ----------'
       echo "/// ${PROJECT_NAME}.${PROJECT_TYPE}工程不存在!"
       echo '/// ----------'
    
       exit 1
    fi
    
    #编译所需json信息
    BUILD_SECRET_JSON="${IOS_BUILD_SCRIPT_DIR}/common/json/buildSecret.json"
    
    
    #获取Unity和Native git信息
    function getGitInfo(){
      CURRENT_PWD_DIR=$(pwd)/
    
      #获取Unit git信息
      cd ${UNITY_ROOT_DIR}
      UNITY_GIT_COMMIT_BRANCH=`git branch | grep \* | cut -d ' ' -f2`
      #Unity Git最后三次提交日志
      UNITY_GIT_COMMIT_DESC=`sh "${IOS_BUILD_SCRIPT_DIR}/common/shell/getGitLog.sh" "/Users/${USER}/Desktop/Project/Unity_IOS/kidsplus_bobo"`
    
      #获取Native git信息
      cd ${NATIVE_ROOT_DIR}
      NATIVE_GIT_COMMIT_BRANCH=`git branch | grep \* | cut -d ' ' -f2`
      #Native Git最后三次提交日志
      NATIVE_GIT_COMMIT_RECORD=`sh "${IOS_BUILD_SCRIPT_DIR}/common/shell/getGitLog.sh" "${NATIVE_ROOT_DIR}" qingwu`
    
      #回到之前操作目录
      cd $CURRENT_PWD_DIR
    }
    
    #添加git tag
    function addGitTag(){
      CURRENT_PWD_DIR=$(pwd)/
    
      #tag名称
      GIT_TAG_NAME="iOS_${BUNDLE_VERSION}"
      #添加git tag脚本路径
      ADD_GIT_TAG_SCRIPT_PATH="/Users/${USER}/Desktop/Project/Script/Common/shell/addGitTag.sh"
    
      #Jenkins
      sh ${ADD_GIT_TAG_SCRIPT_PATH} ${JENKINS_ROOT_DIR} ${GIT_TAG_NAME}
      #Unity
      sh ${ADD_GIT_TAG_SCRIPT_PATH} ${UNITY_ROOT_DIR} ${GIT_TAG_NAME}
      #iOS
      sh ${ADD_GIT_TAG_SCRIPT_PATH} ${NATIVE_ROOT_DIR} ${GIT_TAG_NAME}
    
      #回到之前操作目录
      cd $CURRENT_PWD_DIR
    }
    
    #解析本地储存json
    function analysisBuildSecretJson(){
      BUILD_SECRET_JSON="${IOS_BUILD_SCRIPT_DIR}/common/json/buildSecret.json"
      if [ -e $BUILD_SECRET_JSON ]
      then
        COMPUTER_USER_NAME=`jq -r .computer_user_name $BUILD_SECRET_JSON`
        FIR_API_TOKEN=`jq -r .fir_api_token $BUILD_SECRET_JSON`
      else
        echo '/// 缺少打包必要json文件!'
        echo ''
        exit 1
      fi
    }
    
    #根据分发方式定义各类路径名称
    function definePath(){
      if [ "$DISTRIBUTION_METHOD" = "AdHoc" ]
      then
        #打包模式 Debug/Release
        DEVELOPMENT_MODE="Debug"
        #exportOptionsPlist文件所在路径
        EXPORT_OPTIONS_PLIST_PATH=${IOS_BUILD_SCRIPT_DIR}/iOS/export_ipa_plist/ExportOptions-adhoc.plist
        #archive路径
        ARCHIVE_FILE_PATH=${IOS_BUILD_SAVE_DIR}/${BUNDLE_VERSION}/Build/${BUNDLE_BUILD_VERSION}/archive/AdHoc/bobo.xcarchive
        #导出.ipa文件所在路径
        EXPORT_IPA_PATH=${IOS_BUILD_SAVE_DIR}/${BUNDLE_VERSION}/Build/${BUNDLE_BUILD_VERSION}/ipa_file/AdHoc
        #ipa文件存放目标路径
        IPA_FILE_PATH=${EXPORT_IPA_PATH}/Apps/bobo.ipa
        #ipa文件存放OSS的名称
        IPA_FILE_NAME_WITH_OSS=AdHoc_${BUNDLE_VERSION}_${BUNDLE_BUILD_VERSION}_${APP_ENVIRONMENT}
        #fir安装二维码
        FIR_INSTALL_QRCODE_IMAGE_PATH=${EXPORT_IPA_PATH}/Apps/fir-bobo.png
      else
        DEVELOPMENT_MODE="Release"
        EXPORT_OPTIONS_PLIST_PATH=${IOS_BUILD_SCRIPT_DIR}/iOS/export_ipa_plist/ExportOptions-appstore.plist
        ARCHIVE_FILE_PATH=${IOS_BUILD_SAVE_DIR}/${BUNDLE_VERSION}/Build/${BUNDLE_BUILD_VERSION}/archive/AppStore/bobo.xcarchive
        EXPORT_IPA_PATH=${IOS_BUILD_SAVE_DIR}/${BUNDLE_VERSION}/Build/${BUNDLE_BUILD_VERSION}/ipa_file/AppStore
        IPA_FILE_PATH=${EXPORT_IPA_PATH}/bobo.ipa
        IPA_FILE_NAME_WITH_OSS=AppStore_${BUNDLE_VERSION}_${BUNDLE_BUILD_VERSION}_${APP_ENVIRONMENT}
        #fir安装二维码
        FIR_INSTALL_QRCODE_IMAGE_PATH=${EXPORT_IPA_PATH}/fir-bobo.png
      fi
    }
    
    #设置xcode工程版本号、编译号和网络环境配置
    function setBundleEnvironment(){
      build_info_json="${PROJECT_PATH}/Data/Raw/Build.json"
      #修改app环境配置json
      case "${APP_ENVIRONMENT}" in
        "T")
          sed -i "" 's/xxxxxx/xxxxxx/' ${build_info_json}
        ;;
        "Q")
          sed -i "" 's/xxxxxx/xxxxxx/' ${build_info_json}
        ;;
        *)
          sed -i "" 's/xxxxxx/xxxxxx/' ${build_info_json}
        ;;
      esac
    
      #设置本地json文件版本号
      BUILD_VERSION_WITH_JSON=`jq -r .Version ${build_info_json}`
      sed -i "" "s/${BUILD_VERSION_WITH_JSON}/${BUNDLE_VERSION}/" ${build_info_json}
    }
    
    #设置工程的version、build信息
    function setBundlePlistInfo(){
      #设置xcode版本号
      /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${BUNDLE_VERSION}" "${INFO_PLIST_PATH}"
      #设置xcode build号
      /usr/libexec/PlistBuddy -c "Set :CFBundleVersion ${BUNDLE_BUILD_VERSION}" "${INFO_PLIST_PATH}"
    }
    
    #检查归档文件、ipa包目录、dSYMs文件目录
    function checkArchiveIpaDir(){
      #清空上次相同版本的打包目录
      rm -rf "${IOS_BUILD_SAVE_DIR}/${BUNDLE_VERSION}/Build"
    
      #生成新的打包目录
      mkdir -p "${IOS_BUILD_SAVE_DIR}/${BUNDLE_VERSION}/Build/${BUNDLE_BUILD_VERSION}"
    
      #生成符号表目录
      if [ ! -d "${IOS_BUILD_SAVE_DIR}/symtab" ]
      then
        mkdir -p "${IOS_BUILD_SAVE_DIR}/symtab"
      fi
    }
    
    #清理工程
    function clearXcodeProject(){
      echo ''
      echo '///-----------'
      echo '/// 正在清理工程'
      echo '///-----------'
    
      xcodebuild \
        clean -configuration ${DEVELOPMENT_MODE} -quiet
    
      echo '///--------'
      echo '/// 清理完成'
      echo '///--------'
      echo ''
    }
    
    #归档工程
    function archiveXcodeProject(){
      echo '///-----------'
      echo "/// 正在Archive:${DEVELOPMENT_MODE}"
      echo '///-----------'
      
      xcodebuild \
        archive -${PROJECT_BUILD_TYPE} ${PROJECT_PATH}/${PROJECT_NAME}.${PROJECT_TYPE} \
        -scheme ${SCHEME_NAME} \
        -configuration ${DEVELOPMENT_MODE} \
        -archivePath ${ARCHIVE_FILE_PATH} \
        -allowProvisioningUpdates \
        -quiet
    
      if [ -e ${ARCHIVE_FILE_PATH} ]
      then
        echo '///--------'
        echo "/// ${IPA_FILE_NAME_WITH_OSS} Archive完成"
        echo '///--------'
        echo ''
      else
        echo '///--------'
        echo "/// Archive失败!"
        echo '///--------'
        echo ''
    
        exit 1
      fi
    }
    
    #保存符号表文件
    function saveSymtabFile(){
      if [ "$DISTRIBUTION_METHOD" = "AdHoc" ]
      then
        return
      fi
    
      echo '///--------'
      echo "/// 正在生成符号表文件..."
      echo '///--------'
      echo ''
    
      #dSYM文件路径
      dSYM_FILE_PATH="${ARCHIVE_FILE_PATH}/dSYMs/bobo.app.dSYM"
    
      if [ -e $dSYM_FILE_PATH ]
      then
        CURRENT_PWD_DIR=$(pwd)/
        cd "${ARCHIVE_FILE_PATH}/dSYMs/"
    
        #获取uuid
        dSYM_FILE_NAME_WITH_UUID=`xcrun dwarfdump --uuid bobo.app.dSYM`
        echo "dSYM_FILE_NAME_WITH_UUID:${dSYM_FILE_NAME_WITH_UUID}"
        dSYM_FILE_NAME_WITH_UUID=${dSYM_FILE_NAME_WITH_UUID:6:36}
    
        #生成符号表zip文件
        cd ${SCRIP_PATH}/tools/buglySymboliOS3.0.0
        java -jar buglySymboliOS.jar -i "${IOS_BUILD_SAVE_DIR}/dSYMs/bobo.app.dSYM" -o "${IOS_BUILD_SAVE_DIR}/symtab/${dSYM_FILE_NAME_WITH_UUID}.zip"
        
        if [ -e "${IOS_BUILD_SAVE_DIR}/symtab/${dSYM_FILE_NAME_WITH_UUID}.zip" ]
        then
          echo '///--------'
          echo "符号表成功生成"
          echo '///--------'
          echo ''
        fi
    
        cd "${CURRENT_PWD_DIR}"
      else
        echo '///--------'
        echo "dSYM文件不存在"
        echo '///--------'
        echo ''
      fi
    }
    
    #编译ipa包
    function buildIpa(){
      echo '///--------'
      echo "正在导出${IPA_FILE_NAME_WITH_OSS}.ipa ..."
      echo ''
    
      xcodebuild -exportArchive -archivePath ${ARCHIVE_FILE_PATH} \
        -configuration ${DEVELOPMENT_MODE} \
        -exportPath ${EXPORT_IPA_PATH} \
        -exportOptionsPlist ${EXPORT_OPTIONS_PLIST_PATH} \
        -allowProvisioningUpdates \
        -quiet
    
      if [ -e ${IPA_FILE_PATH} ]
      then
        echo '/// ----------'
        echo "/// ipa包已导出:$IPA_FILE_PATH "
        echo '/// ----------'
      else
        echo '///------------'
        echo '/// ipa包导出失败!'
        echo '///------------'
    
        #清空本次打包目录
        rm -rf "${IOS_BUILD_SAVE_DIR}/${BUNDLE_VERSION}/Build"
    
        exit 1
      fi
    }
    
    #上传文件到OSS 
    function uploadFileToOSS(){
      FILE_PATH=$1
      FILE_NAME=$2
    
      if [ -e "${FILE_PATH}" ]
      then
        UPLOAD_OSS_PY="${IOS_BUILD_SCRIPT_DIR}/common/python/uploadoss.py"
        if [ -e $UPLOAD_OSS_PY ]
        then
          python3 $UPLOAD_OSS_PY $FILE_PATH $FILE_NAME iOS/"$BUNDLE_VERSION"/"$DISTRIBUTION_METHOD"
        else
          echo '/// 无上传oss脚本'
          echo ''
        fi
      else
         echo '/// ----------'
         echo "/// [${FILE_PATH}]不存在!"
         echo '/// ----------'
      fi
    }
    
    #上传ipa包
    function uploadIpa(){
      if [ "$DISTRIBUTION_METHOD" = "AppStore" ]
      then
        if [ "${ORIGINAL_DISTRIBUTION_METHOD}" = "All" ]
        then
          disposeIpaUploadResult "导出Release ipa成功"
        else
          echo '/// ----------'
          echo "/// 正在验证ipa..."
          echo '/// ----------'
          echo ''
    
          #验证ipa
          IPA_VALIDATE_TO_APPSTORE_RESPONSE=`xcrun altool --validate-app -f $IPA_FILE_PATH -t ios --apiKey xxxxxx --apiIssuer xxxxxx --verbose --output-format json`
          
          if [[ "${IPA_VALIDATE_TO_APPSTORE_RESPONSE}" == *"No errors validating archive"* ]]
          then
            echo '/// ----------'
            echo "/// 验证ipa成功!"
            echo '/// ----------'
            echo ''
            echo "/// 正在上传ipa到AppStore..."
            echo ''
    
            #上传ipa
            IPA_UPLOAD_TO_APPSTORE_RESPONSE=`xcrun altool --upload-app -f $IPA_FILE_PATH -t ios --apiKey xxxxxx --apiIssuer xxxxxx --verbose --output-format json`
    
            if [[ "${IPA_UPLOAD_TO_APPSTORE_RESPONSE}" == *"No errors uploading"* ]]
            then
              disposeIpaUploadResult "上传AppStore成功"
            else
              if [[ "${IPA_UPLOAD_TO_APPSTORE_RESPONSE}" == *'already uploaded a build'* ]]
              then
                disposeIpaUploadResult "上传AppStore重复"
              else
                disposeIpaUploadResult "上传AppStore失败"
              fi
            fi
          else
            if [[ "${IPA_VALIDATE_TO_APPSTORE_RESPONSE}" == *'already uploaded a build'* ]]
            then
              disposeIpaUploadResult "上传AppStore重复"
            else
              disposeIpaUploadResult "上传AppStore验证失败"
            fi
          fi
        fi
      else
        if [ "$FIR_API_TOKEN" = "" ]
        then
          echo '/// ----------'
          echo "/// 上传fir失败!error:token不存在"
          echo '/// ----------'
          echo ''
        else
          echo '/// ----------'
          echo "/// 正在上传ipa到fir..."
          echo '/// ----------'
          echo ''
    
          fir login -T ${FIR_API_TOKEN}
          IPA_UPLOAD_TO_FIR_RESULT=`fir p ${IPA_FILE_PATH} -c ${FIR_CHANGE_LOG} --need_release_id`
          echo "IPA_UPLOAD_TO_FIR_RESULT:${IPA_UPLOAD_TO_FIR_RESULT}"
          IPA_RELEASE_URL=${IPA_UPLOAD_TO_FIR_RESULT##*'Published succeed: '}
          echo "IPA_RELEASE_URL2:${IPA_RELEASE_URL}"
    
          if [[ "$IPA_RELEASE_URL" == "http"* ]]
          then
            if [[ "$IPA_RELEASE_URL" == *","* ]]
            then
              IPA_RELEASE_URL=${IPA_RELEASE_URL%%','*}
              echo "IPA_RELEASE_URL3:${IPA_RELEASE_URL}"
              IPA_RELEASE_URL=${IPA_RELEASE_URL%??}
              echo "IPA_RELEASE_URL4:${IPA_RELEASE_URL}"
            fi
            disposeIpaUploadResult "上传fir成功"
          else
            disposeIpaUploadResult "上传fir失败"
          fi
        fi
      fi
    }
    
    #处理ipa上传结果
    function disposeIpaUploadResult(){
      #上传结果
      IPA_UPLOAD_TO_APPSTORE_RESULT=$1
    
      #获取发行人电话号码
      JECKINS_BUILD_USER_NAME=`jq -r ".${JECKINS_BUILD_USER_ID} | .name" "${IOS_BUILD_SCRIPT_DIR}/common/json/dingTalkPhone.json"`
      DING_TALK_NOTIFY_USER_PHONE=`jq -r ".${JECKINS_BUILD_USER_ID} | .phone" "${IOS_BUILD_SCRIPT_DIR}/common/json/dingTalkPhone.json"`
    
      if [[ -z ${JECKINS_BUILD_USER_NAME} ]]
      then
        JECKINS_BUILD_USER_NAME="未知"
      fi
      if [ "${DING_TALK_NOTIFY_USER_PHONE}" = "" ]
      then
        DING_TALK_NOTIFY_USER_PHONE="159xxxxxxx"
      fi
    
      SEND_DING_TALK_MSG_SCRIPT_PATH="/Users/${USER}/Desktop/Project/Script/common/shell/sendDingTalkMsg.sh"
    
      case "${IPA_UPLOAD_TO_APPSTORE_RESULT}" in
        "上传AppStore成功")
          echo '/// ----------'
          echo "/// ipa上传AppStore成功!"
          echo '/// ----------'
          echo ''
    
          #发送DingTalk消息
          DINGTALK_MESSAGE_TITLE='AppStore应用交付成功'
          DING_TALK_NOTIFY_USERS_INFO='{'isAtAll':true}'
          DINGTALK_MESSAGE_CONTENT="## ${DINGTALK_MESSAGE_TITLE} \n>#### - Jenkins执行参数:\n>###### · URL:${JENKINS_URL}\n>###### · 任务名:${JECKINS_BRANCH_NAME}\n>###### · 执行人:${JECKINS_BUILD_USER_NAME}\n>###### · 版本号:${BUNDLE_VERSION}\n>###### · Build:${BUNDLE_BUILD_VERSION}\n#### - Unity日志(${UNITY_GIT_COMMIT_BRANCH}):\n${UNITY_GIT_COMMIT_DESC}\n#### - iOS日志(${NATIVE_GIT_COMMIT_BRANCH}):\n${NATIVE_GIT_COMMIT_RECORD}\n\n@所有人\n"
          sh $SEND_DING_TALK_MSG_SCRIPT_PATH ${DINGTALK_MESSAGE_TITLE} ${DING_TALK_NOTIFY_USERS_INFO} ${DINGTALK_MESSAGE_CONTENT}
    
          #AppStore交付成功后添加git tag
          addGitTag
        ;;
        "上传AppStore重复")
          echo '/// ----------'
          echo "/// ipa上传重复!AppStore已存在版本号:${BUNDLE_VERSION} build:${BUNDLE_BUILD_VERSION}"
          echo '/// ----------'
          echo ''
    
          #发送DingTalk消息
          DINGTALK_MESSAGE_TITLE='AppStore应用重复提交'
          DING_TALK_NOTIFY_USERS_INFO="{'atMobiles':[${DING_TALK_NOTIFY_USER_PHONE}],'isAtAll':false}"
          DINGTALK_MESSAGE_CONTENT="## ${DINGTALK_MESSAGE_TITLE}\n>#### - Jenkins执行参数:\n>###### · URL:${JENKINS_URL}\n>###### · 任务名:${JECKINS_BRANCH_NAME}\n>###### · 执行人:${JECKINS_BUILD_USER_NAME}\n>###### · 版本号:${BUNDLE_VERSION}\n>###### · Build:${BUNDLE_BUILD_VERSION}\n#### - Unity日志(${UNITY_GIT_COMMIT_BRANCH}):\n${UNITY_GIT_COMMIT_DESC}\n#### - iOS日志(${NATIVE_GIT_COMMIT_BRANCH}):\n${NATIVE_GIT_COMMIT_RECORD}\n\n@${DING_TALK_NOTIFY_USER_PHONE}\n"
          sh $SEND_DING_TALK_MSG_SCRIPT_PATH ${DINGTALK_MESSAGE_TITLE} ${DING_TALK_NOTIFY_USERS_INFO} ${DINGTALK_MESSAGE_CONTENT}
        ;;
        "上传AppStore验证失败")
          echo '/// ----------'
          echo "/// ipa上传AppStore验证失败!"
          echo '/// ----------'
          echo ''
          echo "/// 正在上传ipa到OSS..."
          echo ''
    
          #上传ipa文件到OSS
          IPA_DOWNLOAD_URL=`uploadFileToOSS $IPA_FILE_PATH "${IPA_FILE_NAME_WITH_OSS}.ipa"`
    
          #发送DingTalk消息
          DINGTALK_MESSAGE_TITLE='AppStore应用验证失败'
          DING_TALK_NOTIFY_USERS_INFO="{'atMobiles':[${DING_TALK_NOTIFY_USER_PHONE}],'isAtAll':false}"
          DINGTALK_MESSAGE_CONTENT="## ${DINGTALK_MESSAGE_TITLE}\n>#### - Jenkins执行参数:\n>###### · URL:${JENKINS_URL}\n>###### · 任务名:${JECKINS_BRANCH_NAME}\n>###### · 执行人:${JECKINS_BUILD_USER_NAME}\n>###### · 版本号:${BUNDLE_VERSION}\n>###### · Build:${BUNDLE_BUILD_VERSION}\n#### - Unity日志(${UNITY_GIT_COMMIT_BRANCH}):\n${UNITY_GIT_COMMIT_DESC}\n#### - iOS日志(${NATIVE_GIT_COMMIT_BRANCH}):\n${NATIVE_GIT_COMMIT_RECORD}\n\n@${DING_TALK_NOTIFY_USER_PHONE}\n>##### **[ipa下载地址:${IPA_DOWNLOAD_URL}](${IPA_DOWNLOAD_URL})** \n>"
          sh $SEND_DING_TALK_MSG_SCRIPT_PATH ${DINGTALK_MESSAGE_TITLE} ${DING_TALK_NOTIFY_USERS_INFO} ${DINGTALK_MESSAGE_CONTENT}
        ;;
        "上传AppStore失败")
          echo '/// ----------'
          echo "/// ipa上传AppStore失败!"
          echo '/// ----------'
          echo ''
          echo "/// 正在上传ipa到OSS..."
          echo ''
    
          #上传ipa文件到OSS
          IPA_DOWNLOAD_URL=`uploadFileToOSS $IPA_FILE_PATH "${IPA_FILE_NAME_WITH_OSS}.ipa"`
    
          #发送DingTalk消息
          DINGTALK_MESSAGE_TITLE='AppStore应用交付失败'
          DING_TALK_NOTIFY_USERS_INFO="{'atMobiles':[${DING_TALK_NOTIFY_USER_PHONE}],'isAtAll':false}"
          DINGTALK_MESSAGE_CONTENT="## ${DINGTALK_MESSAGE_TITLE}\n>#### - Jenkins执行参数:\n>###### · URL:${JENKINS_URL}\n>###### · 任务名:${JECKINS_BRANCH_NAME}\n>###### · 执行人:${JECKINS_BUILD_USER_NAME}\n>###### · 版本号:${BUNDLE_VERSION}\n>###### · Build:${BUNDLE_BUILD_VERSION}\n#### - Unity日志(${UNITY_GIT_COMMIT_BRANCH}):\n${UNITY_GIT_COMMIT_DESC}\n#### - iOS日志(${NATIVE_GIT_COMMIT_BRANCH}):\n${NATIVE_GIT_COMMIT_RECORD}\n\n@${DING_TALK_NOTIFY_USER_PHONE}\n>##### **[ipa下载地址:${IPA_DOWNLOAD_URL}](${IPA_DOWNLOAD_URL})** \n"
          sh $SEND_DING_TALK_MSG_SCRIPT_PATH ${DINGTALK_MESSAGE_TITLE} ${DING_TALK_NOTIFY_USERS_INFO} ${DINGTALK_MESSAGE_CONTENT}
        ;;
        "上传fir成功")
          echo '/// ----------'
          echo "/// ipa上传fir成功!"
          echo '/// ----------'
          echo ''
    
          #上传安装二维码图片
          QRCODE_IMAGE_DOWNLOAD_URL=`uploadFileToOSS ${FIR_INSTALL_QRCODE_IMAGE_PATH} "${IPA_FILE_NAME_WITH_OSS}.png"`
    
          if [[ "${IS_UPLOAD_TO_OSS}" = "是" ]]
          then
            echo "///正在上传ipa到OSS..."
            echo ''
    
            #上传ipa文件到OSS
            IPA_DOWNLOAD_URL=`uploadFileToOSS $IPA_FILE_PATH "${IPA_FILE_NAME_WITH_OSS}.ipa"`
    
            #发送钉钉消息
            DINGTALK_MESSAGE_TITLE="fir-iOS内测应用更新成功"
            DING_TALK_NOTIFY_USERS_INFO="{'atMobiles':[${DING_TALK_NOTIFY_USER_PHONE}],'isAtAll':false}"
            DINGTALK_MESSAGE_CONTENT="## ${DINGTALK_MESSAGE_TITLE}\n>#### - Jenkins执行参数:\n>###### · URL:${JENKINS_URL}\n>###### · 任务名:${JECKINS_BRANCH_NAME}\n>###### · 执行人:${JECKINS_BUILD_USER_NAME}\n>###### · 版本号:${BUNDLE_VERSION}\n>###### · Build:${BUNDLE_BUILD_VERSION}\n>###### · 环境:${APP_ENVIRONMENT}\n>###### · 更新描述:${FIR_CHANGE_LOG}\n#### - Unity日志(${UNITY_GIT_COMMIT_BRANCH}):\n${UNITY_GIT_COMMIT_DESC}\n#### - iOS日志(${NATIVE_GIT_COMMIT_BRANCH}):\n${NATIVE_GIT_COMMIT_RECORD} ![screenshot](${QRCODE_IMAGE_DOWNLOAD_URL})\n[向右] **[点击这里进行安装](${IPA_RELEASE_URL})** \n\n@${DING_TALK_NOTIFY_USER_PHONE}\n>##### **[ipa下载地址:${IPA_DOWNLOAD_URL}](${IPA_DOWNLOAD_URL})** \n"
            sh $SEND_DING_TALK_MSG_SCRIPT_PATH ${DINGTALK_MESSAGE_TITLE} ${DING_TALK_NOTIFY_USERS_INFO} ${DINGTALK_MESSAGE_CONTENT}
          else
            #发送钉钉消息
            DINGTALK_MESSAGE_TITLE="fir-iOS内测应用更新成功"
            DING_TALK_NOTIFY_USERS_INFO="{'atMobiles':[${DING_TALK_NOTIFY_USER_PHONE}],'isAtAll':false}"
            DINGTALK_MESSAGE_CONTENT="## ${DINGTALK_MESSAGE_TITLE}\n>#### - Jenkins执行参数:\n>###### · URL:${JENKINS_URL}\n>###### · 任务名:${JECKINS_BRANCH_NAME}\n>###### · 执行人:${JECKINS_BUILD_USER_NAME}\n>###### · 版本号:${BUNDLE_VERSION}\n>###### · Build:${BUNDLE_BUILD_VERSION}\n>###### · 环境:${APP_ENVIRONMENT}\n>###### · 更新描述:${FIR_CHANGE_LOG}\n#### - Unity日志(${UNITY_GIT_COMMIT_BRANCH}):\n${UNITY_GIT_COMMIT_DESC}\n#### - iOS日志(${NATIVE_GIT_COMMIT_BRANCH}):\n${NATIVE_GIT_COMMIT_RECORD} ![screenshot](${QRCODE_IMAGE_DOWNLOAD_URL})\n[向右] **[点击这里进行安装](${IPA_RELEASE_URL})** \n\n@${DING_TALK_NOTIFY_USER_PHONE}\n"
            sh $SEND_DING_TALK_MSG_SCRIPT_PATH ${DINGTALK_MESSAGE_TITLE} ${DING_TALK_NOTIFY_USERS_INFO} ${DINGTALK_MESSAGE_CONTENT}
          fi
        ;;
        "上传fir失败")
          echo '/// ----------'
          echo "/// ipa上传fir失败!"
          echo '/// ----------'
          echo ''
          echo "/// 正在上传ipa到OSS..."
          echo ''
    
          #上传ipa文件到OSS
          IPA_DOWNLOAD_URL=`uploadFileToOSS $IPA_FILE_PATH "${IPA_FILE_NAME_WITH_OSS}.ipa"`
    
          #发送DingTalk消息
          DINGTALK_MESSAGE_TITLE='fir-iOS内测应用更新失败'
          DING_TALK_NOTIFY_USERS_INFO="{'atMobiles':[${DING_TALK_NOTIFY_USER_PHONE}],'isAtAll':false}"
          DINGTALK_MESSAGE_CONTENT="## ${DINGTALK_MESSAGE_TITLE}\n>#### - Jenkins执行参数:\n>###### · URL:${JENKINS_URL}\n>###### · 任务名:${JECKINS_BRANCH_NAME}\n>###### · 执行人:${JECKINS_BUILD_USER_NAME}\n>###### · 版本号:${BUNDLE_VERSION}\n>###### · Build:${BUNDLE_BUILD_VERSION}\n>###### · 环境:${APP_ENVIRONMENT}\n>###### · 更新描述:${FIR_CHANGE_LOG}\n#### - Unity日志(${UNITY_GIT_COMMIT_BRANCH}):\n${UNITY_GIT_COMMIT_DESC}\n#### - iOS日志(${NATIVE_GIT_COMMIT_BRANCH}):\n${NATIVE_GIT_COMMIT_RECORD}\n\n@${DING_TALK_NOTIFY_USER_PHONE}\n>##### **[ipa下载地址:${IPA_DOWNLOAD_URL}](${IPA_DOWNLOAD_URL})** \n"
          sh $SEND_DING_TALK_MSG_SCRIPT_PATH ${DINGTALK_MESSAGE_TITLE} ${DING_TALK_NOTIFY_USERS_INFO} ${DINGTALK_MESSAGE_CONTENT}
        ;;
        "导出Release ipa成功")
          echo '/// ----------'
          echo "/// 导出release ipa成功!"
          echo '/// ----------'
          echo ''
          echo "/// 正在上传ipa到OSS..."
          echo ''
    
          #上传ipa文件到OSS
          IPA_DOWNLOAD_URL=`uploadFileToOSS $IPA_FILE_PATH "${IPA_FILE_NAME_WITH_OSS}.ipa"`
    
          #发送DingTalk消息
          DINGTALK_MESSAGE_TITLE='导出ReleaseIpa成功'
          DING_TALK_NOTIFY_USERS_INFO="{'atMobiles':[${DING_TALK_NOTIFY_USER_PHONE}],'isAtAll':false}"
          DINGTALK_MESSAGE_CONTENT="## ${DINGTALK_MESSAGE_TITLE}\n>#### - Jenkins执行参数:\n>###### · URL:${JENKINS_URL}\n>###### · 任务名:${JECKINS_BRANCH_NAME}\n>###### · 执行人:${JECKINS_BUILD_USER_NAME}\n>###### · 版本号:${BUNDLE_VERSION}\n>###### · Build:${BUNDLE_BUILD_VERSION}\n>###### · 环境:${APP_ENVIRONMENT}\n>###### · 更新描述:${FIR_CHANGE_LOG}\n#### - Unity日志(${UNITY_GIT_COMMIT_BRANCH}):\n${UNITY_GIT_COMMIT_DESC}\n#### - iOS日志(${NATIVE_GIT_COMMIT_BRANCH}):\n${NATIVE_GIT_COMMIT_RECORD}\n\n@${DING_TALK_NOTIFY_USER_PHONE}\n>##### **[ipa下载地址:${IPA_DOWNLOAD_URL}](${IPA_DOWNLOAD_URL})** \n"
          sh $SEND_DING_TALK_MSG_SCRIPT_PATH ${DINGTALK_MESSAGE_TITLE} ${DING_TALK_NOTIFY_USERS_INFO} ${DINGTALK_MESSAGE_CONTENT}
        ;;
      esac
    }
    
    #打包所有活动
    function buildActive(){
      #根据分发方式定义各类路径名称
      definePath
      #检查归档文件及ipa包目录
      checkArchiveIpaDir
      #设置工程网络环境配置
      setBundleEnvironment
      #清理工程
      clearXcodeProject
      #归档工程
      archiveXcodeProject
      #生成符号表文件
      saveSymtabFile
      #编译ipa包
      buildIpa
      #上传ipa包
      uploadIpa
    }
    
    
    #解析本地储存json
    analysisBuildSecretJson
    #设置ipa的version、build信息
    setBundlePlistInfo
    #获取Unity和Native git信息
    getGitInfo
    
    #开始执行打包流程
    case "${DISTRIBUTION_METHOD}" in
      "AdHoc")
        #打测试分发包
        buildActive
      ;;
      "AppStore")
        #打AppStore包
        APP_ENVIRONMENT="P"
        buildActive
      ;;
    esac
    
    echo ''
    echo '/// 自动打包脚本已执行完毕'
    echo ''
    
    exit 0
    
    
    打包脚本包含功能:

    1、读取、修改本地配置json文件
    2、修改Xcode工程版本、编译等信息
    3、归档、导出ipa包
    4、上传fir、App Store
    5、保存dSYM文件
    6、发布App Store成功给git打上版本号标签
    7、将Jenkins任务结果发布到钉钉群消息并@执行人
    8、钉钉消息添加git最后提交的三次git记录
    9、一些容错处理,比如上传失败自动上传OSS

    以上功能分为多个脚本文件,可以给安卓进行自动化构建使用。
    最后贴上钉钉消息样式:
    DingTalk消息(上传AppStore成功).jpeg DingTalk消息(上传fir成功).jpeg

    相关文章

      网友评论

          本文标题:iOS-Unity2018.4.24f1使用Jenkins自动化

          本文链接:https://www.haomeiwen.com/subject/jacxjltx.html