iOS自动化打包 Jenkins+fastlane+蒲公英+钉钉

一、Homebrew

Homebrew是一款Mac OS平台下的软件包管理工具

  1. 安装Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
  1. 检测Homebrew是否安装成功
brew -v
Homebrew版本
  1. 更新Homebrew
brew update

注意
1、Homebrew的命令是以brew开头
2、Homebrew的默认安装目录为 /usr/local/Homebrew
3、通过brew 安装的程序都会默认安装到 /usr/local/Cellar/程序名/版本号/ 目录下

二、Java

  1. Jenkins需要依赖java环境,当我们用最新的Homebrew来安装Jenkins时会默认先安装 java11,但是我们最好使用java8,Java8比较稳定,而且后面流水线要用bugly,bugly不支持Java11。
  2. brew安装Java8
brew install --cask homebrew/cask-versions/adoptopenjdk8
  1. 检测Java是否安装成功
java -version

注意
1、JAVA的默认安装目录为 /Library/Java,如果你安装多个版本,/Library/Java/JavaVirtualMachines里面就可以看到多个版本文件夹

二、Jenkins

Jenkins是开源软件项目,基于Java开发的持续集成工具,用于监控持续重复的工作

  1. brew安装Jenkins
brew install jenkins
  1. 检测Jenkins是否安装成功
jenkins --version
  1. 启动jenkins
jenkins

jenkins是在前台启动关闭终端,jenkins就关闭了

  1. 设置jenkins后台启动、开机启动
设置开机自启动:sudo launchctl load -w /Library/LaunchDaemons/org.jenkins-ci.plist
取消开机自启动:sudo launchctl unload -w /Library/LaunchDaemons/org.jenkins-ci.plist
后台启动(默认端口):nohup java -jar jenkins.war &
后台启动(指定端口):nohup java -jar jenkins.war -httpPort=88 &
后台启动(HTTPS):nohup java -jar jenkins.war -httpsPort=88 &
  1. 根据提示输入,安装推荐的插件,注册账户
  2. 你可以把所有的插件都安装了,常用的有git相关Branch API Plugin、 Build With Parameters之类

三、流水线

  1. 创建新的流水线任务,名字你自己取


  2. 配置Discard old builds选项,就是多久释放旧的构建


  3. 勾选This project is parameterized,选择Choice Parameter,这边的environment名字和内容,其实你都可以按需配置,只要和下面脚本里对的上就可以。这边就是选择对应的环境,开发、测试、生产


  4. 选择Git Parameter,就是可以选择对应的Git分支


  5. Git源码管理,填入你的源码地址,我这边用的是https的,点这个添加,输入你的git账号和密码就可以了。



  6. 如果你是SSH,你就选择SSH Username with private key,把ssh私钥填进去
    6.1 前往文件夹 ~/.ssh 可以看到本机是否已经生成过,有的话可以直接用,也可以生成新的
    6.2 ssh-keygen -t rsa -C "youremail@example.com" 生成秘钥;不需要更名称和不需要密码的话直接敲回车就行了。
    6.3 生成成功之后,前往 ~/.ssh,里面三个文件id_rsa(私钥)、id_rsa.pub(公钥)、known_hosts

    6.4 将id_rsa.pub(公钥)配置到git,将id_rsa(私钥)配置到jenkins里。

  7. 构建->增加构建步骤->Execute shell
  8. 在填脚本,我们先把钉钉弄一下
    8.1 钉钉和测试拉个群
    8.2 群设置->智能群助手->添加自定义机器人


    8.3 安全设置,必须要选一个,我选择了关键词 比较简单一点,这个关键词就是你机器人自动发的文字里必须要有这个关键词才会发,例如发布。复制Webhook备用
  9. 查看蒲公英的apikey,在个人设置
  10. 因为xcodebuild打包需要ExportOptions.plist文件。所以前往文件夹~/.jenkins/workspace,在这个目录下创建文件夹ExportOptions。
  11. 先手动导出你的IPA包,类型的话你就选ad-hoc,导出的文件里有个ExportOptions.plist,把它copy出来,放到刚刚的文件夹里,再复制一份然后修改里面的method属性为development,把这个文件重命名为ExportOptions_dev.plist



  12. 因为我签名是自动的,所以我不需要配证书什么的,比较方便,直接用了jenkins的脚本,如果你是手动的。还是用fastlane比较方便
  13. 输入脚本,把脚本复制出来,你全局搜一下****,有****的地方就是你需要自己替换的
echo -e $(pwd)
## !/bin/sh
## 项目名
TARGET_NAME=****
## Scheme名
SCHEME=****

echo -e "============Pod Install============"

cd ${TARGET_NAME}
echo -e $(pwd)
pod install

##=======================
## 编译类型
if [[ "${environment}" == "生产环境" ]]; then
# 生产环境
BUILD_TYPE=Release
## ExportOptions.plist文件的存放路径,该文件要存放在这个路径下内容如下
EXPORTOPTIONSPLIST=${JENKINS_HOME}/workspace/ExportOptions/ExportOptions.plist
else
# 测试环境
BUILD_TYPE=Debug
## ExportOptions.plist文件的存放路径,该文件要存放在这个路径下内容如下
EXPORTOPTIONSPLIST=${JENKINS_HOME}/workspace/ExportOptions/ExportOptions_dev.plist
fi

## 当前目录
SORCEPATH=${WORKSPACE}
## workspace名
SPACE=${WORKSPACE}/${TARGET_NAME}/${TARGET_NAME}.xcworkspace
##xcarchive文件的存放路径
ARCHIVEPATH=$SORCEPATH/build/$SCHEME.xcarchive
## ipa文件的存放路径
EXPORTPATH=$SORCEPATH/build/$SCHEME
## 导出后的ipa路径
EXPORTPATHIPA=$SORCEPATH/build/${TARGET_NAME}/****.ipa



echo -e "============First Build Clean============"
## 清理缓存
## 如果工程使用的是cocoapods,则'-project %s.xcodeproj'替换为'-workspace %s.xcworkspace'
xcodebuild clean -workspace $SPACE -scheme ${SCHEME} -configuration ${BUILD_TYPE}

DELETEIPAFILE=$SORCEPATH/build/$SCHEME/****.ipa
rm -f ${DELETEIPAFILE}

echo -e "============Build Clean============"

## 输出关键信息
echo -e "  TARGET_NAME    : ${TARGET_NAME}"
echo -e "  BUILD_TYPE    : ${BUILD_TYPE}"
echo -e "  SORCEPATH    : ${SORCEPATH}"
echo -e "  ARCHIVEPATH    : ${ARCHIVEPATH}"
echo -e "  EXPORTPATH    : ${EXPORTPATH}"
echo -e "  EXPORTOPTIONSPLIST    : ${EXPORTOPTIONSPLIST}"
echo -e "============Build Archive============"

## 导出archive包
xcodebuild archive -workspace ${SPACE} -scheme ${SCHEME} -configuration ${BUILD_TYPE} -quiet -archivePath $ARCHIVEPATH
echo -e "============Build Archive Success============"

echo -e "============Export IPA============"
## 导出IPA包
xcodebuild -exportArchive -archivePath $ARCHIVEPATH -quiet -exportPath ${EXPORTPATH} -exportOptionsPlist ${EXPORTOPTIONSPLIST}
echo -e "============Export IPA SUCCESS============"

## 编译完成时间
BUILD_DATE="$(date +'%Y%m%d_%H%M')"

## 上传蒲公英
## apiKey和userKey需要在蒲公英的账号设置中查找https://www.pgyer.com/account/api
apiKey="****"
MSG=`git log -1 --pretty=%B`

#蒲公英打包
result=$(curl -F "file=@${EXPORTPATHIPA}" \
-F "_api_key=${apiKey}" \
-F "buildUpdateDescription=${environment};${MSG}" \
https://www.pgyer.com/apiv2/app/upload)

code=`echo $result | jq '.code'`

if [ $code = 0 ];then
    echo "蒲公英打包 Success"
    data=`echo $result | jq '.data'`
    #APP名 需要带上-r 要不然数据会有""
    buildName=`echo $data | jq -r '.buildName'` 
    #APP版本号
    buildVersion=`echo $data | jq -r '.buildVersion'` 
    #APP下载二维码
    buildQRCodeURL=`echo $data | jq -r '.buildQRCodeURL'` 
    #钉钉通知
    message="#### 【iOS${buildName}】${environment};V${buildVersion} 发布成功 \n 更新说明:${MSG} \n>扫描二维码安装:![screenshot](${buildQRCodeURL}) \n #### @****钉钉群里你需要at的人的手机号码 请注意查收"
    MSG_JSON='{"msgtype":"markdown","markdown":{"title":"'${buildName}'App发布通知","text":"'${message}'"},"at":{"atMobiles":["****钉钉群里你需要at的人的手机号码"]}}'

    curl 'https://oapi.dingtalk.com/robot/send?access_token=****钉钉机器人webhook' \
        -H  'Content-Type:application/json' \
        -d  "${MSG_JSON}"
else
    echo "蒲公英打包 Failed"
fi
  1. 构建任务



  2. 如果你需要在git push的时候自动执行,那就设置构建触发器,然后将这个GitLab webhook URL复制到你的项目设置里,一般叫网络回调钩子


四、分配角色权限

因为要给后端和测试同学使用,需要配置一下权限,给他们指定某些任务可以操作,具体的操作也只能是运行和取消。

  1. 安装插件Role-based Authorization Strategy
  2. Manage Jenkins->Manage Users->新增用户test




  3. Manage Jenkins->Configure Global Security->勾选Role-Based Strategy ,保存(如果你没有安装Role-based Authorization Strategy插件是没有这个选项的)


  4. Manage Jenkins->Manage and Assign Roles 进入角色管理
    4.1 选择Manage Roles,这边我的理解是用户组的意思,你输入一个用户组的名字,选择读权限

    4.2 输入4.1你输的用户组名,然后在Pattern输入对应的任务名字,进行绑定,选择对应的权限。相当于你这个组下的用户只能操作这个任务

    4.3 选择Assign Roles,给对应的用户组,分配用户

    4.4 绑定用户组和用户,拉到最下面有个保存
  5. 登录test账号,发现只能看到那一个任务,也只有运行和停止的操作 就OK了


五、外网映射

  1. 因为测试同学不一定和咱们处于同一个区域网,咱们需要给个外网地址给他们,那我们需要用到一个工具 花生壳 ,自行搜索下载。花生壳默认是开机自启的,这个软件有时候后端在测支付的时候 也是可以用它的。
  2. 添加映射


    3-1.png
  3. 输入你本机的IP地址(按住option,去点击你的WiFi图标,可以看到你的IP),端口是8080,保存


    3-2.png
  4. 将生成的访问地址,发给测试他们试试吧


六、Fastlane的使用

fastlane可以简化我们的操作,之前的shell脚本那么长 很不方便。在集成fastlane之前,咱们先创建一个新的jenkins任务,里面把上面讲的git等相关的东西先弄好。

  1. 安装fastlane
brew install fastlane
  1. 查看fastlane版本
fastlane --version
  1. 进入你的工程目录下,初始化,选择4 然后下一步确认键就可以了
fastlane init

  1. 成功后会生成fastlane文件夹,里面有Appfile、Fastfile两个文件
  2. Appfile主要是填写你的app_identifier和apple_id账号的, Fastfile就是你的操作文件了,里面包含了多个lane ,每个lane你就可以想成是个任务或者方法。
  3. 进入你的工程目录下,添加蒲公英插件,然后会多Gemfile Gemfile.lock Pluginfile文件
fastlane add_plugin pgyer

  1. 填写Appfile账号信息
app_identifier "****"
apple_id "****"
  1. 编写fastlane任务,gym(clean:true,scheme:"XMHealth",configuration:"Release",export_method:"ad-hoc"),configuration有release和debug,export_method即导出参数有app-store, package, ad-hoc, enterprise, development, 和developer-iddevelopment。你搜一下里面有****的做一下替换。至于lane传参数,你可以看一下官网传参的介绍
default_platform(:ios)
platform :ios do

  desc "build adhoc ipa"
  lane :XMHealth_adhoc do
     gym(clean:true,scheme:"****",configuration:"Release",export_method:"ad-hoc")
  end

  desc "build dev ipa"
  lane :XMHealth_dev do
     gym(clean:true,scheme:"****",configuration:"Debug",export_method:"development")
  end

  desc "upload to pgyer"
  lane :uploadToPgyer do |options|
     pgyer(api_key: "****", user_key: "****", update_description: options[:msg])
  end

  desc "upload to dingdingTalk"
  lane :dingdingTalk do |options|
     updatemsg = options[:msg]
     buildName = get_info_plist_value(path: "./XMHealth/Other/Info.plist", key: 'CFBundleDisplayName')
     puts buildName
     curl = %Q{
        curl 'https://oapi.dingtalk.com/robot/send?access_token=****' \
        -H 'Content-Type:application/json' \
        -d '{
          "msgtype":"markdown",
          "markdown":{
            "title":"iOS#{buildName}App发布通知🚀🚀🚀",
            "text":"#### 🚀🚀🚀iOS#{buildName}App发布成功\n说明:#{updatemsg}\n###### 扫码安装↓↓↓\n![screenshot](https://www.pgyer.com/app/qrcode/****)\n#### @**** @**** 请注意查收"
          },
          "at":{
            "atMobiles":["****","****"]
          }
      }'
    }
    system curl
  end

  desc "release"
  lane :release do |options|
    if options[:submit]
      XMHealth_adhoc() 
      uploadToPgyer(msg:options[:msg])
      dingdingTalk(msg:options[:msg])
      puts "生产ad-hoc流水线成功"
    else
      XMHealth_dev() 
      uploadToPgyer(msg:options[:msg])
      dingdingTalk(msg:options[:msg])
      puts "测试dev流水线成功"
    end
  end
end
  1. jenkins里execute shell
## 项目名
TARGET_NAME=****
GITMSG=`git log -1 --pretty=%B`
MSG="${environment}、${GITMSG}"
cd ${TARGET_NAME}
pod install

## 编译类型
if [[ "${environment}" == "生产环境" ]]; then
# 生产环境
fastlane release submit:true msg:${MSG}
else
# 测试环境
fastlane release submit:false msg:${MSG}
fi
  1. 专门搞一台闲置的Mac天天开着,在上面部署好,然后用花生壳,开放给测试、后台他们使用

常见问题

  1. 如果有Java相关的报错,记得检查你本地的环境变量还有安装的Java,JAVA的默认安装目录为 /Library/Java,看看里面是不是安装了多个,建议使用java8,jenkins默认是Java11的,
    1.1 检查. zshrc文件的里的环境变量JAVA_HOME,前往->文件夹-> ~/. zshrc
    1.2 如果有缺JAVA_HOME,请添加你对应的Java地址
    1.3 命令行里source .zshrc,保存一下
export JAVA_HOME="/Library/Java/JavaVirtualMachines/jdk1.8.0_311.jdk/Contents/Home"
  1. 输出里看到如下错误
DVTPortal: Error:
Error Domain=DVTPortalServiceErrorDomain Code=1100 "Your session has expired. Please log in."

解决: Xcode —>Preference—> Accounts 重新登录,注意如果有多个账号,要确保所有的账号都是登录状态。

  1. 在jenkins里执行xcodebuild -exportArchive 导出IPA命令的时候,会报错
error: exportArchive: The data couldn’t be read because it isn’t in the correct format.

Error Domain=NSCocoaErrorDomain Code=3840 "No value." UserInfo={NSDebugDescription=No value., NSFilePath=/var/folders/qx/qs4cc3pn0sgddxqjh7dj_k300000gn/T/ipatool-json-filepath-~~~FH2VEz}

** EXPORT FAILED **

Build step 'Execute shell' marked build as failure
Finished: FAILURE

解决: 将对应打包的证书ExportOptions.plist文件的compileBitcode内容由 true 改为 false 就可以

1、Could not find action, lane or variable 'pgyer'. Check out the documentation for more details: https://docs.fastlane.tools/actions

找不到蒲公英插件,原来是安装目录错了,应该在工程目录下安装:fastlane add_plugin pgyer

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,302评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,563评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,433评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,628评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,467评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,354评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,777评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,419评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,725评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,768评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,543评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,387评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,794评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,032评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,305评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,741评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,946评论 2 336

推荐阅读更多精彩内容