jenkins CI - 脚本

1,149 阅读5分钟

ps: 脚本在文末

在开发一款APP的时候,一般需要构建ios端和android端以及两端APP的后台配置管理系统(web端)。在开发以及后续维护它们的过程中,避免不了要持续地测试发布

如果项目每添加或修复一个功能时,都去手动构建出来安装包(web就是build后发布到测试服务器)给测试同事。先不说费时吧,起码逼格就降下来了。站在测试同事(部门)的角度考虑这样一个情景:两端准备上线一个植树节活动,活动的一些信息是通过后台被运营部门设定的。在测试这个功能的时候,测试同事... 啊,这个,由于我不是测试确实编不出来了,我不编了,我摊牌了,知道jenkins CI天下第一,牛逼,就行了。

jenkins 部署环境

-OS系统 Mac和虚拟机都可以,因为一直需要处于开机状态构建所以建议是用windows机器装虚拟机配置好后把显示器卸掉,一直放在那里就可以了。当然是要开启一下远程的,方便控制。在你用局域网去访问这台机器或者这台机器上的服务时,建议将ip地址固定。

-Android SDK gradle -Xcode CocoaPods node Git

安装jenkins

配置jenkins

注意:以下的配置基于macOS Catalina 10.15.2

三个项目都使用git做版本控制,托管在云端。

一般构建流程先clone => 安装项目依赖 => 本地环境构建 => 上传构建产物 => (线上部署) => 结果通知

在这个过程中jenkins几乎可以帮我们完成所有的工作,我将按照这个流程来配置jenkins。

clone

每当有提交时,clone代码到本地要用jenkins自动完成这个步骤,在本地我不知道托管服务器怎么hook我的jenkins,所以我折中了一下每五分钟去看下有没有新的提交,有就clone

IOS
Android
web

-源码管理

这里我使用的是gitee托管,在jenkins安装Gitee Plugin

在系统配置中配置gitee,可以参考这里

新建freestyle project后,设置源码管理项:

安装依赖

IOS
export LANGUAGE=en_US.UTF-8

export LC_ALL=en_US.UTF-8

#最后一次git commit信息
MSG=`git log -1 --pretty=%B`
#提交信息中出现这个字符代表不构建ios
#PASSSTR="IC pass build ios"
#result=$(echo $MSG | grep "${PASSSTR}")
#if [[ "$result" != "" ]]
#then
#  exit 0
#fi

cd /Users/johndiamond

source .bash_profile

cd /Users/johndiamond/.jenkins/workspace/iOS_glh-dev/ios

/usr/local/bin/pod install
Android

Android的依赖和构建可以用一个命令

#工程绝对路径
project_path=/Users/johndiamond/.jenkins/workspace/Android_glh-dev

#工程名 
project_name=app

#打包模式 Debug/Release
development_mode=debug

#最后一次git commit信息
MSG=`git log -1 --pretty=%B`

#提交信息中出现这个字符代表不构建ios
#PASSSTR="IC pass build android"
#result=$(echo $MSG | grep "${PASSSTR}")
#if [[ "$result" != "" ]]
#then
#  exit 0
#fi

cd /Users/johndiamond
source .bash_profile
cd $project_path/android
#gradle clean
gradle assembleDebug
web
cd /Users/johndiamond/.jenkins/workspace/glh-admin
npm install

本地构建

用最开始配置的环境去构建

IOS

ios构建之前还需要配置Keychains and Provisioning Profiles Management具体查看这里

配置好就是这样

export LANGUAGE=en_US.UTF-8

export LC_ALL=en_US.UTF-8

#最后一次git commit信息
MSG=`git log -1 --pretty=%B`
#提交信息中出现这个字符代表不构建ios
#PASSSTR="IC pass build ios"
#result=$(echo $MSG | grep "${PASSSTR}")
#if [[ "$result" != "" ]]
#then
#  exit 0
#fi

cd /Users/johndiamond

source .bash_profile

cd /Users/johndiamond/.jenkins/workspace/iOS_glh-dev

flutter pub get

cd /Users/johndiamond/.jenkins/workspace/iOS_glh-dev/ios

/usr/local/bin/pod install

#工程绝对路径
project_path=/Users/johndiamond/.jenkins/workspace/iOS_glh-dev/ios
#工程名 
project_name=Runner

#scheme名
scheme_name=Runner

#打包模式 Debug/Release
development_mode=Release

#build文件夹路径
build_path=${project_path}/build

#plist文件所在路径
exportOptionsPlistPath=/Users/johndiamond/.jenkins/workspace/ExportOptions.plist

#导出.ipa文件所在路径
exportIpaPath=${project_path}/ipa/${development_mode}

      echo '///-----------'
      echo '/// 正在清理工程'
      echo '///-----------'
      #xcodebuild \
      #clean -configuration ${development_mode} -quiet  || exit
      xcodebuild -workspace ${project_path}/${scheme_name}.xcworkspace -scheme ${project_name} -configuration ${development_mode} clean
      
      echo '///--------'
      echo '/// 清理完成'
      echo '///--------'
      echo ''
      echo '///-----------'
      echo '/// 正在编译工程:'${development_mode}
      echo '///-----------'
      xcodebuild \
      archive -workspace ${project_path}/${project_name}.xcworkspace \
      -scheme ${scheme_name} \
      -configuration ${development_mode} \
      -archivePath ${build_path}/${project_name}.xcarchive  -quiet  || exit
      
      echo '///--------'
      echo '/// 编译完成'
      echo '///--------'
      echo ''

    echo '///----------'
    echo '/// 开始ipa打包'
    echo '///----------'
    xcodebuild -exportArchive -archivePath ${build_path}/${project_name}.xcarchive \
    -configuration ${development_mode} \
    -exportPath ${exportIpaPath} \
    -exportOptionsPlist ${exportOptionsPlistPath} \
    -quiet || exit
    
    if [ -e $exportIpaPath/$scheme_name.ipa ]; then
    echo '///----------'
    echo '/// ipa包已导出'
    echo '///----------'
    open $exportIpaPath
    else
    echo '///-------------'
    echo '/// ipa包导出失败 '
    echo '///-------------'
    fi
    echo '///------------'
    echo '/// 打包ipa完成  '
    echo '///-----------='
    echo ''
   
#打印信息,以供匹配(?<=is)(.+?)(?=end)
echo "MSGis${MSG}end"
Android
#就是【安装依赖】的脚本
web
npm run build:prod

上传构建产物

这里上传到蒲公英,文档可以看这里,firm也是可以的。

IOS

#上传到蒲公英
#蒲公英aipKey
MY_PGY_API_K=这里填写aipKey
PASSWORD=这里填写安装密码apiV2必填

#打印信息,以供匹配(?<=is)(.+?)(?=end)
echo "MSGis${MSG}end"

curl -F "file=@${exportIpaPath}/${scheme_name}.ipa" -F buildInstallType=2 -F "buildPassword=${PASSWORD}" -F "_api_key=${MY_PGY_API_K}" https://www.pgyer.com/apiv2/app/upload
Android
echo "开始上传到蒲公英"
#蒲公英aipKey
MY_PGY_API_K=这里填写aipKey
#蒲公英安装密码
PASSWORD=你的密码

#打印信息,以供匹配(?<=is)(.+?)(?=end)
echo "MSGis${MSG}end"

curl -F "file=@${project_path}/build/app/outputs/apk/debug/${project_name}-${development_mode}.apk" -F buildInstallType=2 -F "buildPassword=${PASSWORD}" -F "_api_key=${MY_PGY_API_K}" https://www.pgyer.com/apiv2/app/upload
web

配置Publish Over SSH

(线上部署)

web

构建结果通知

我这里是在钉钉上用自定义的hook机器人通知,配置方法请看这里

IOS
DINGDING_URL=https://oapi.dingtalk.com/robot/send?access_token=这里填写你的机器人hook-token

curl $DINGDING_URL \
      -H 'Content-Type: application/json' \
   -d '{
   			"msgtype": "link",
            "link": {
         		"text": "'"$MSG"'",
            	"title": "'"glh-IOS_${development_mode} 安装密码:******"'",
            	"picUrl": "https://www.pgyer.com/app/qrcode/tkq6?sign=&auSign=&code=",
            	"messageUrl": "https://www.pgyer.com/tkq6"
            },
         	"at": {
        		"atMobiles": [
            		"15697481731"
        		], 
         		"isAtAll": false
    		},
    
      }'

Android
echo "开始通知钉钉"
DINGDING_URL=https://oapi.dingtalk.com/robot/send?access_token=这里填写你的机器人hook-token
curl $DINGDING_URL \
      -H 'Content-Type: application/json' \
   -d '{
   			"msgtype": "link",
            "link": {
         		"text": "'"$MSG"'",
            	"title": "'"glh-Android_${development_mode} 安装密码:******"'",
            	"picUrl": "https://www.pgyer.com/app/qrcode/sQXt",
            	"messageUrl": "https://www.pgyer.com/sQXt"
            },
         	"at": {
        		"atMobiles": [
            		"15697481731"
        		], 
         		"isAtAll": false
    		},
    
      }'
web

类似的方法,我这里没有进行通知

附上脚本

IOS

export LANGUAGE=en_US.UTF-8

export LC_ALL=en_US.UTF-8

#最后一次git commit信息
MSG=`git log -1 --pretty=%B`
#提交信息中出现这个字符代表不构建ios
#PASSSTR="IC pass build ios"
#result=$(echo $MSG | grep "${PASSSTR}")
#if [[ "$result" != "" ]]
#then
#  exit 0
#fi

cd /Users/johndiamond

source .bash_profile

cd /Users/johndiamond/.jenkins/workspace/iOS_glh-dev

flutter pub get

cd /Users/johndiamond/.jenkins/workspace/iOS_glh-dev/ios

/usr/local/bin/pod install



#工程绝对路径
project_path=/Users/johndiamond/.jenkins/workspace/iOS_glh-dev/ios
#工程名 
project_name=Runner

#scheme名
scheme_name=Runner

#打包模式 Debug/Release
development_mode=Release

#build文件夹路径
build_path=${project_path}/build

#plist文件所在路径
exportOptionsPlistPath=/Users/johndiamond/.jenkins/workspace/ExportOptions.plist

#导出.ipa文件所在路径
exportIpaPath=${project_path}/ipa/${development_mode}


#echo "Place enter the number you want to export ? [ 1:app-store 2:ad-hoc] "

##
#read number
#while([[ $number != 1 ]] && [[ $number != 2 ]])
#do
#echo "Error! Should enter 1 or 2"
#echo "Place enter the number you want to export ? [ 1:app-store 2:ad-hoc] "
#read number
#done

#if [ $number == 1 ];then
#development_mode=Release
#exportOptionsPlistPath=${project_path}/exportTest.plist
#else
#development_mode=Debug
#exportOptionsPlistPath=${project_path}/exportTest.plist
#fi


      echo '///-----------'
      echo '/// 正在清理工程'
      echo '///-----------'
      #xcodebuild \
      #clean -configuration ${development_mode} -quiet  || exit
      xcodebuild -workspace ${project_path}/${scheme_name}.xcworkspace -scheme ${project_name} -configuration ${development_mode} clean
      
      echo '///--------'
      echo '/// 清理完成'
      echo '///--------'
      echo ''
      echo '///-----------'
      echo '/// 正在编译工程:'${development_mode}
      echo '///-----------'
      xcodebuild \
      archive -workspace ${project_path}/${project_name}.xcworkspace \
      -scheme ${scheme_name} \
      -configuration ${development_mode} \
      -archivePath ${build_path}/${project_name}.xcarchive  -quiet  || exit
      
      echo '///--------'
      echo '/// 编译完成'
      echo '///--------'
      echo ''

    echo '///----------'
    echo '/// 开始ipa打包'
    echo '///----------'
    xcodebuild -exportArchive -archivePath ${build_path}/${project_name}.xcarchive \
    -configuration ${development_mode} \
    -exportPath ${exportIpaPath} \
    -exportOptionsPlist ${exportOptionsPlistPath} \
    -quiet || exit
    
    if [ -e $exportIpaPath/$scheme_name.ipa ]; then
    echo '///----------'
    echo '/// ipa包已导出'
    echo '///----------'
    open $exportIpaPath
    else
    echo '///-------------'
    echo '/// ipa包导出失败 '
    echo '///-------------'
    fi
    echo '///------------'
    echo '/// 打包ipa完成  '
    echo '///-----------='
    echo ''
    
    echo "开始上传到蒲公英"
#上传到蒲公英
#蒲公英aipKey
MY_PGY_API_K=你的key

PASSWORD=你的密码
#打印信息,以供匹配(?<=is)(.+?)(?=end)
echo "MSGis${MSG}end"

curl -F "file=@${exportIpaPath}/${scheme_name}.ipa" -F buildInstallType=2 -F "buildPassword=${PASSWORD}" -F "_api_key=${MY_PGY_API_K}" https://www.pgyer.com/apiv2/app/upload

DINGDING_URL=https://oapi.dingtalk.com/robot/send?access_token=你的token

curl $DINGDING_URL \
      -H 'Content-Type: application/json' \
   -d '{
   			"msgtype": "link",
            "link": {
         		"text": "'"$MSG"'",
            	"title": "'"glh-IOS_${development_mode} 安装密码:****"'",
            	"picUrl": "https://www.pgyer.com/app/qrcode/tkq6?sign=&auSign=&code=",
            	"messageUrl": "https://www.pgyer.com/tkq6"
            },
         	"at": {
        		"atMobiles": [
            		"15697481731"
        		], 
         		"isAtAll": false
    		},
    
      }'

Android

#工程绝对路径
project_path=/Users/johndiamond/.jenkins/workspace/Android_glh-dev
#工程名 
project_name=app
#打包模式 Debug/Release
development_mode=debug

#最后一次git commit信息
MSG=`git log -1 --pretty=%B`
#提交信息中出现这个字符代表不构建ios
#PASSSTR="IC pass build android"
#result=$(echo $MSG | grep "${PASSSTR}")
#if [[ "$result" != "" ]]
#then
#  exit 0
#fi

cd /Users/johndiamond

source .bash_profile

cd $project_path
flutter pub get
cd $project_path/android
#gradle clean
gradle assembleDebug

echo "开始上传到蒲公英"
#蒲公英aipKey
MY_PGY_API_K=你的key
#蒲公英安装密码
PASSWORD=你的密码

#打印信息,以供匹配(?<=is)(.+?)(?=end)
echo "MSGis${MSG}end"

curl -F "file=@${project_path}/build/app/outputs/apk/debug/${project_name}-${development_mode}.apk" -F buildInstallType=2 -F "buildPassword=${PASSWORD}" -F "_api_key=${MY_PGY_API_K}" https://www.pgyer.com/apiv2/app/upload
echo "开始通知钉钉"
DINGDING_URL=https://oapi.dingtalk.com/robot/send?access_token=你的token
curl $DINGDING_URL \
      -H 'Content-Type: application/json' \
   -d '{
   			"msgtype": "link",
            "link": {
         		"text": "'"$MSG"'",
            	"title": "'"glh-Android_${development_mode} 安装密码:****"'",
            	"picUrl": "https://www.pgyer.com/app/qrcode/sQXt",
            	"messageUrl": "https://www.pgyer.com/sQXt"
            },
         	"at": {
        		"atMobiles": [
            		"15697481731"
        		], 
         		"isAtAll": false
    		},
    
      }'