iOS-Unity2018.4.24f1使用Jenkins自動化構(gòu)建

適合iOS工程是Unity為主導,native代碼是作為插件形式接入。
本文腳本是從Unity生成xcode工程之后開始執(zhí)行,不一定完全適用,請按照自己需求進行修改。

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

一.安裝xcodeproj

#安裝ruby xcodeproj庫
$gem install xcodeproj
#如果提示沒有權(quán)限運行下面這條命令:
$sudo gem install xcodeproj

二、配置xcodeproj工程

#執(zhí)行腳本示例:
ruby '配置腳本文件路徑' 'Unity生成的xcode工程根目錄'
#或者增加參數(shù)可自動打開工程:
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創(chuàng)建文件夾: #{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創(chuàng)建文件:#{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}已經(jīng)添加過! #{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 "創(chuàng)建新資源文件夾:#{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 設(shè)置完成\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)

    #添加系統(tǒng)動態(tài)庫
    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)

    #添加系統(tǒng)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結(jié)束配置#{TARGET_NAME}.xcodeproj\033[0m\n "

    if is_auto_open_xcodeproj == '1'
        puts " ?????? \033[44m#{TARGET_NAME}.xcodeproj配置已經(jīng)全部完成,2秒后將自動打開工程, Have fun!\033[0m\n"
        sleep 2
        system "open -- #{project_path}"
    else
        puts " ?????? \033[44m#{TARGET_NAME}.xcodeproj配置已經(jīng)全部完成,Have fun!\033[0m\n"
    end

end

exit

三、編譯Xcode工程、導出ipa、發(fā)布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

#應(yīng)用網(wǎng)絡(luò)環(huán)境
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"

#獲取腳本執(zhí)行目錄
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 "http:/// ${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
}

#根據(jù)分發(fā)方式定義各類路徑名稱
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
}

#設(shè)置xcode工程版本號、編譯號和網(wǎng)絡(luò)環(huán)境配置
function setBundleEnvironment(){
  build_info_json="${PROJECT_PATH}/Data/Raw/Build.json"
  #修改app環(huán)境配置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

  #設(shè)置本地json文件版本號
  BUILD_VERSION_WITH_JSON=`jq -r .Version ${build_info_json}`
  sed -i "" "s/${BUILD_VERSION_WITH_JSON}/${BUNDLE_VERSION}/" ${build_info_json}
}

#設(shè)置工程的version、build信息
function setBundlePlistInfo(){
  #設(shè)置xcode版本號
  /usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString ${BUNDLE_VERSION}" "${INFO_PLIST_PATH}"
  #設(shè)置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 "http:/// 正在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 "http:/// ${IPA_FILE_NAME_WITH_OSS} Archive完成"
    echo '///--------'
    echo ''
  else
    echo '///--------'
    echo "http:/// Archive失敗!"
    echo '///--------'
    echo ''

    exit 1
  fi
}

#保存符號表文件
function saveSymtabFile(){
  if [ "$DISTRIBUTION_METHOD" = "AdHoc" ]
  then
    return
  fi

  echo '///--------'
  echo "http:/// 正在生成符號表文件..."
  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 "http:/// 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 "http:/// [${FILE_PATH}]不存在!"
     echo '/// ----------'
  fi
}

#上傳ipa包
function uploadIpa(){
  if [ "$DISTRIBUTION_METHOD" = "AppStore" ]
  then
    if [ "${ORIGINAL_DISTRIBUTION_METHOD}" = "All" ]
    then
      disposeIpaUploadResult "導出Release ipa成功"
    else
      echo '/// ----------'
      echo "http:/// 正在驗證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 "http:/// 驗證ipa成功!"
        echo '/// ----------'
        echo ''
        echo "http:/// 正在上傳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 "http:/// 上傳fir失敗!error:token不存在"
      echo '/// ----------'
      echo ''
    else
      echo '/// ----------'
      echo "http:/// 正在上傳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上傳結(jié)果
function disposeIpaUploadResult(){
  #上傳結(jié)果
  IPA_UPLOAD_TO_APPSTORE_RESULT=$1

  #獲取發(fā)行人電話號碼
  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 "http:/// ipa上傳AppStore成功!"
      echo '/// ----------'
      echo ''

      #發(fā)送DingTalk消息
      DINGTALK_MESSAGE_TITLE='AppStore應(yīng)用交付成功'
      DING_TALK_NOTIFY_USERS_INFO='{'isAtAll':true}'
      DINGTALK_MESSAGE_CONTENT="## ${DINGTALK_MESSAGE_TITLE} \n>#### - Jenkins執(zhí)行參數(shù):\n>###### · URL:${JENKINS_URL}\n>###### · 任務(wù)名:${JECKINS_BRANCH_NAME}\n>###### · 執(zhí)行人:${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 "http:/// ipa上傳重復!AppStore已存在版本號:${BUNDLE_VERSION} build:${BUNDLE_BUILD_VERSION}"
      echo '/// ----------'
      echo ''

      #發(fā)送DingTalk消息
      DINGTALK_MESSAGE_TITLE='AppStore應(yīng)用重復提交'
      DING_TALK_NOTIFY_USERS_INFO="{'atMobiles':[${DING_TALK_NOTIFY_USER_PHONE}],'isAtAll':false}"
      DINGTALK_MESSAGE_CONTENT="## ${DINGTALK_MESSAGE_TITLE}\n>#### - Jenkins執(zhí)行參數(shù):\n>###### · URL:${JENKINS_URL}\n>###### · 任務(wù)名:${JECKINS_BRANCH_NAME}\n>###### · 執(zhí)行人:${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 "http:/// ipa上傳AppStore驗證失敗!"
      echo '/// ----------'
      echo ''
      echo "http:/// 正在上傳ipa到OSS..."
      echo ''

      #上傳ipa文件到OSS
      IPA_DOWNLOAD_URL=`uploadFileToOSS $IPA_FILE_PATH "${IPA_FILE_NAME_WITH_OSS}.ipa"`

      #發(fā)送DingTalk消息
      DINGTALK_MESSAGE_TITLE='AppStore應(yīng)用驗證失敗'
      DING_TALK_NOTIFY_USERS_INFO="{'atMobiles':[${DING_TALK_NOTIFY_USER_PHONE}],'isAtAll':false}"
      DINGTALK_MESSAGE_CONTENT="## ${DINGTALK_MESSAGE_TITLE}\n>#### - Jenkins執(zhí)行參數(shù):\n>###### · URL:${JENKINS_URL}\n>###### · 任務(wù)名:${JECKINS_BRANCH_NAME}\n>###### · 執(zhí)行人:${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 "http:/// ipa上傳AppStore失敗!"
      echo '/// ----------'
      echo ''
      echo "http:/// 正在上傳ipa到OSS..."
      echo ''

      #上傳ipa文件到OSS
      IPA_DOWNLOAD_URL=`uploadFileToOSS $IPA_FILE_PATH "${IPA_FILE_NAME_WITH_OSS}.ipa"`

      #發(fā)送DingTalk消息
      DINGTALK_MESSAGE_TITLE='AppStore應(yīng)用交付失敗'
      DING_TALK_NOTIFY_USERS_INFO="{'atMobiles':[${DING_TALK_NOTIFY_USER_PHONE}],'isAtAll':false}"
      DINGTALK_MESSAGE_CONTENT="## ${DINGTALK_MESSAGE_TITLE}\n>#### - Jenkins執(zhí)行參數(shù):\n>###### · URL:${JENKINS_URL}\n>###### · 任務(wù)名:${JECKINS_BRANCH_NAME}\n>###### · 執(zhí)行人:${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 "http:/// 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 "http:///正在上傳ipa到OSS..."
        echo ''

        #上傳ipa文件到OSS
        IPA_DOWNLOAD_URL=`uploadFileToOSS $IPA_FILE_PATH "${IPA_FILE_NAME_WITH_OSS}.ipa"`

        #發(fā)送釘釘消息
        DINGTALK_MESSAGE_TITLE="fir-iOS內(nèi)測應(yīng)用更新成功"
        DING_TALK_NOTIFY_USERS_INFO="{'atMobiles':[${DING_TALK_NOTIFY_USER_PHONE}],'isAtAll':false}"
        DINGTALK_MESSAGE_CONTENT="## ${DINGTALK_MESSAGE_TITLE}\n>#### - Jenkins執(zhí)行參數(shù):\n>###### · URL:${JENKINS_URL}\n>###### · 任務(wù)名:${JECKINS_BRANCH_NAME}\n>###### · 執(zhí)行人:${JECKINS_BUILD_USER_NAME}\n>###### · 版本號:${BUNDLE_VERSION}\n>###### · Build:${BUNDLE_BUILD_VERSION}\n>###### · 環(huá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
        #發(fā)送釘釘消息
        DINGTALK_MESSAGE_TITLE="fir-iOS內(nèi)測應(yīng)用更新成功"
        DING_TALK_NOTIFY_USERS_INFO="{'atMobiles':[${DING_TALK_NOTIFY_USER_PHONE}],'isAtAll':false}"
        DINGTALK_MESSAGE_CONTENT="## ${DINGTALK_MESSAGE_TITLE}\n>#### - Jenkins執(zhí)行參數(shù):\n>###### · URL:${JENKINS_URL}\n>###### · 任務(wù)名:${JECKINS_BRANCH_NAME}\n>###### · 執(zhí)行人:${JECKINS_BUILD_USER_NAME}\n>###### · 版本號:${BUNDLE_VERSION}\n>###### · Build:${BUNDLE_BUILD_VERSION}\n>###### · 環(huá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 "http:/// ipa上傳fir失敗!"
      echo '/// ----------'
      echo ''
      echo "http:/// 正在上傳ipa到OSS..."
      echo ''

      #上傳ipa文件到OSS
      IPA_DOWNLOAD_URL=`uploadFileToOSS $IPA_FILE_PATH "${IPA_FILE_NAME_WITH_OSS}.ipa"`

      #發(fā)送DingTalk消息
      DINGTALK_MESSAGE_TITLE='fir-iOS內(nèi)測應(yīng)用更新失敗'
      DING_TALK_NOTIFY_USERS_INFO="{'atMobiles':[${DING_TALK_NOTIFY_USER_PHONE}],'isAtAll':false}"
      DINGTALK_MESSAGE_CONTENT="## ${DINGTALK_MESSAGE_TITLE}\n>#### - Jenkins執(zhí)行參數(shù):\n>###### · URL:${JENKINS_URL}\n>###### · 任務(wù)名:${JECKINS_BRANCH_NAME}\n>###### · 執(zhí)行人:${JECKINS_BUILD_USER_NAME}\n>###### · 版本號:${BUNDLE_VERSION}\n>###### · Build:${BUNDLE_BUILD_VERSION}\n>###### · 環(huá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 "http:/// 導出release ipa成功!"
      echo '/// ----------'
      echo ''
      echo "http:/// 正在上傳ipa到OSS..."
      echo ''

      #上傳ipa文件到OSS
      IPA_DOWNLOAD_URL=`uploadFileToOSS $IPA_FILE_PATH "${IPA_FILE_NAME_WITH_OSS}.ipa"`

      #發(fā)送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執(zhí)行參數(shù):\n>###### · URL:${JENKINS_URL}\n>###### · 任務(wù)名:${JECKINS_BRANCH_NAME}\n>###### · 執(zhí)行人:${JECKINS_BUILD_USER_NAME}\n>###### · 版本號:${BUNDLE_VERSION}\n>###### · Build:${BUNDLE_BUILD_VERSION}\n>###### · 環(huá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(){
  #根據(jù)分發(fā)方式定義各類路徑名稱
  definePath
  #檢查歸檔文件及ipa包目錄
  checkArchiveIpaDir
  #設(shè)置工程網(wǎng)絡(luò)環(huán)境配置
  setBundleEnvironment
  #清理工程
  clearXcodeProject
  #歸檔工程
  archiveXcodeProject
  #生成符號表文件
  saveSymtabFile
  #編譯ipa包
  buildIpa
  #上傳ipa包
  uploadIpa
}


#解析本地儲存json
analysisBuildSecretJson
#設(shè)置ipa的version、build信息
setBundlePlistInfo
#獲取Unity和Native git信息
getGitInfo

#開始執(zhí)行打包流程
case "${DISTRIBUTION_METHOD}" in
  "AdHoc")
    #打測試分發(fā)包
    buildActive
  ;;
  "AppStore")
    #打AppStore包
    APP_ENVIRONMENT="P"
    buildActive
  ;;
esac

echo ''
echo '/// 自動打包腳本已執(zhí)行完畢'
echo ''

exit 0

打包腳本包含功能:

1、讀取、修改本地配置json文件
2、修改Xcode工程版本、編譯等信息
3、歸檔、導出ipa包
4、上傳fir、App Store
5、保存dSYM文件
6、發(fā)布App Store成功給git打上版本號標簽
7、將Jenkins任務(wù)結(jié)果發(fā)布到釘釘群消息并@執(zhí)行人
8、釘釘消息添加git最后提交的三次git記錄
9、一些容錯處理,比如上傳失敗自動上傳OSS

以上功能分為多個腳本文件,可以給安卓進行自動化構(gòu)建使用。
最后貼上釘釘消息樣式:
DingTalk消息(上傳AppStore成功).jpeg
DingTalk消息(上傳fir成功).jpeg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容