远端GitLab+Jenkins(CentOS)+本地Mac 做CI自动打包iOS上传到蒲公英

96
疯狂的兜兜
2017.09.24 01:35* 字数 2623

前言

Jenkins是个啥?Jenkins是个非常强大,用于”自动化”编译、打包、分发部署的持续构建的可视化web工具。Jenkins支持各种语言的项目,一般情况下,公司的整个产品线下的各端,我们都可以用Jenkins来创建各个任务并完成自动部署并发布,很好很强大。

构建iOS?一般情况下,为了统一管理整个产品不同端代码的构建,我们会将代码的构建以任务形式放到同一个Jenkins下方便管理,那么问题就来了,我们的服务器大多数情况下都是Linux,然而iOS的打包并不能在Linux下执行,只能在OSX系统下进行,所以引出了我今天的内容。

Jenkins在Linux上的安装过程我就省了,这个在网上到处都有,下面直接进入正题。

一、在Jenkins上创建MacOSX节点

注意:Mac系统上不用安装Jenkins,因为他只用执行远程Jenkins给他的命令,所以只需要安装jdk用来识别远程命令即可,后面讲到的Jenkins均为远程Linux上的,这一点大家先要搞清楚。
首先进入节点管理

image.png

点击新建节点,输入名称,并勾选Permanent Agent

image.png

配置如下图(链接端口在高级按钮里面填):

image.png

下面是你需要填写用来存放远端Linux服务器传给本地Mac用来存证书和keychain的文件的目录,如下图:

image.png

这里解释下每一项的意义:
Name:你节点取个名字,随便填
描述:给予节点的描述,随便填
# of executors:并发任务数(不要超过5)
远程工作目录:是你目标Mac的工作目录,在Mac创建一个目录用于远程Jenkins使用,这里注意这个目录的权限,需要在Mac设为可读写
标签:节点类型,用于后面分组管理
用法:没什么说的,照着选就行了
启动方法:
1.选择Launch slave agents via SSH;
2.Host填Mac的IP或者域名;
注意了,因为我们是远程的Linux连接本地的Mac,那么就涉及到一个内网穿透的问题,那么很多同学会想到“花生壳”,可是Mac上目前是不能用花生壳的,给大家推荐一个Mac上简单好用的内网穿透工具
https://ngrok.cc/ 使用简单,速度还行,最重要的是他是免费的,大家可以注册一个号后根据他的说明文档创建一个基于TCP的隧道,映射到本地SSH端扣(22),这样一来远端的Jenkins就能通过SSH隧道连接到你的Mac了,我配置好后的截图如下(本地Mac还需要用ngrok客户端通过命令行来创建隧道,具体参看ngrok文档说明):

image.png

3.Credentials创建一个以用户名密码登录的方式,并填入用户名和密码,如下图:

image.png

4.Host Key Verification Strategy:在SSH Slave Plugin插件1.16版本后加入了此选项,这里一定注意要选择"Non verifying Verification Strategy",否则SSH链接会报以下错误:

[09/23/17 11:40:34] [SSH] Opening SSH connection to xxx.xxx.xxx.xxx:22
[09/23/17 11:40:34] [SSH] WARNING: No entry currently exists in the Known Hosts file for this host.      Connections will be denied until this new host and its associated key is added to the Known Hosts file.
     Key exchange was not finished, connection is closed.
     java.io.IOException: There was a problem while connecting to xxx.xxx.xxx.xxx:22

此时还需要本地的Mac打开远程访问的权限,在偏好设置-》共享中,配置好如下图:

image.png

配置成功后点击保存,他将会自动开始连接,连接成功后如图所示:

image.png

二、创建任务并配置Mac节点到任务中

节点我们创建好了,接下来需要创建一个任务,在这里我就简单介绍一下(不太熟悉的同学可以完全照着我的配置做),在首页点击新建,填入任务名称,�选择第一个选项,如图:

image.png

因为我这里使用的是GitLab,所以需要添加两个插件“GitLab Plugin”和“Gitlab Hook Plugin”,然后Git需要在全局配置中配置一下:

image.png

点了Add过后选择GitLab API Token,如下图:

image.png

去GitLab把Token拿到,并填在Token栏里,在Setting->Account里面,如图:

image.png

拿到过后就可以ADD再保存,那么在这里就可以看到刚刚添加的Git项了:

image.png

这里勾选“Restrict where this project can be run”,然后填写MacOSX,他会识别为我们刚才创建的Mac节点:

image.png

源码管理选择Git,因为我们是GitLab的环境,这里我填写的是http的Git链接,这样就用不去配置SSH KEY,省去一些麻烦,当然在Credentials选项中对应填写的就是UserName和Password,这个用户名和密码最好是GitLab上的管理员用户,我在下图中标注了一些Tip:

image.png

构建触发器照着勾,身份验证令牌需要用命令行创建创建Token

openssl rand -hex 12
e8924xxxxxxxxxx740790531

创建好后先填在这里,然后把下面“GitHub hook trigger for GITScm polling”打上勾,如下图:

image.png
注意:这里有一个天坑,必须要安装"Build Authorization Token Root Plugin"这个插件,不然我们在做WebHook的时候GitLab会报各种403。

Jenkins的WebHook就设置好了,接下来就来设置GitLab上的WebHook,
首先选择需要被Hook的项目,然后Setting->Edit->Integrations,填入Hook的URL,可以看看这个插件的官方说明https://wiki.jenkins.io/display/JENKINS/Build+Token+Root+Plugin,我总结的具体格式如下(token就是上面我们生成的”身份验证令牌“):

http://Jenkins服务器地址:端口/buildByToken/build?job=job名称&token=token

填写如下图,填写完了直接保存就OK了,保存后点击TEST,如果之前按照我的配置设置的,那应该就可以成功了(任务要先保存才能Test成功):

image.png

接下来构建环境需要先配置证书等相关文件所以必须先配置Keychain和Code Signing Identity具体步骤如下:
1.点击系统管理-》Keychains and Provisioning Profiles Management(如果没有,先装同名插件)

image.png

2.来到这个插件主页面,先把Login.keychain和证书传上去,具体看我的标图:

image.png

3.下方的“Provisioning Profiles Directory Path”需要填写一个远端Linux服务器上有的目录,并且把Login.keychain和证书文件都放到这个目录下,证书文件必须是以下图UUID命名,不然会报错,参看下图:

image.png

好了到此,证书和keychain都配好了,有同学可能会问,P12怎么没地方传,因为Login.keychain里面包含你所有的证书,你只需要提供登录密码个Jenkins,他会自动解锁,获取里面的证书信息,所以上面一张图里会填写证书的常用名称,因为他是通过常用名称来找到对应证书的。
证书相关的做完了,那么下图的配置也就可以做了,ps:Variables是自动生成的:

image.png

下面的配置也一样,选择对应证书就OK了:

image.png

三、项目构建及相关脚本

下面就是构建了,选择“Execute Shell”,为什么用脚本不用"Xcode"选项,明细脚本会方便很多,省了去看很多没用的配置。
我这里直讲使用直接使用xcodebuild的方式,网上以前版本有人写过用“xcodebuild + xcrun命令”,但是如今xcrun已经不能将.app转为.ipa了,所以有些同学用以前网上的脚本编译会出现xcrun命令中“PackageApplication”的错误:

image.png

这个错误是因为新版(8.3以后)的Xcode已经彻底废弃了PackageApplication,所以报错是肯定的,所以.app转.ipa就得用其他方法了,这里废话不多说,我把我最新写出来的打包脚本贴出来,大家自己看看就明白了:

#打包目录
DEBUG_PATH_NAME="Debug-iphoneos"
# 工程名
APP_NAME="yourAppName"
# 证书,上面配置中填写的证书常用名
CODE_SIGN_DISTRIBUTION="iPhone Developer: xxxxxx"
# info.plist路径
project_infoplist_path="./${APP_NAME}/Info.plist"

#取版本号
bundleShortVersion=$(/usr/libexec/PlistBuddy -c "print CFBundleShortVersionString" "${project_infoplist_path}")

#取build值
bundleVersion=$(/usr/libexec/PlistBuddy -c "print CFBundleVersion" "${project_infoplist_path}")

DATE="$(date +%Y%m%d)"
IPANAME="${APP_NAME}_V${bundleShortVersion}_${DATE}.ipa"

#解锁
security unlock-keychain -p 你的开机密码

//下面2行是没有Cocopods的用法
echo "=================clean================="
xcodebuild -target "${APP_NAME}"  -configuration 'Debug' clean

echo "+++++++++++++++++build+++++++++++++++++"
xcodebuild -target "${APP_NAME}" -sdk iphoneos -configuration 'Debug' CODE_SIGN_IDENTITY="${CODE_SIGN_DISTRIBUTION}" SYMROOT='$(PWD)'

#下面2行xcodebuild命令是集成有Cocopods的用法
echo "=================clean================="
xcodebuild -workspace "${APP_NAME}.xcworkspace" -scheme "${APP_NAME}"  -configuration ‘Debug’ clean

echo "+++++++++++++++++build+++++++++++++++++"
xcodebuild -workspace "${APP_NAME}.xcworkspace" -scheme "${APP_NAME}" -sdk iphoneos -configuration 'Debug' CODE_SIGN_IDENTITY="${CODE_SIGN_DISTRIBUTION}" SYMROOT='$(PWD)'

#将.app文件转为.ipa文件,并放到
rm -rf ./${DEBUG_PATH_NAME}/ipaFolder
mkdir ./${DEBUG_PATH_NAME}/ipaFolder
mkdir ./${DEBUG_PATH_NAME}/ipaFolder/Payload
cp -r ./${DEBUG_PATH_NAME}/${APP_NAME}.app ./${DEBUG_PATH_NAME}/ipaFolder/Payload/${APP_NAME}.app
cd ${DEBUG_PATH_NAME}/ipaFolder
zip -r ${IPANAME} Payload iTunesArtwork
rm -rf ./Payload

#上传到蒲公英的API
curl -F "file=@${IPANAME}" -F "uKey=yourKey" -F "_api_key=yourKey" https://qiniu-storage.pgyer.com/apiv1/app/upload

1.上面脚本需要修改为你的工程名字
2.证书要改为上面配置中填写的证书常用名
3.解锁需要把“你的开机密码”替换为你的Mac开机密码,否则会报如下错误:

unknown error -1=ffffffffffffffff Command /usr/bin/codesign failed with exit code 1

如图:

image.png

关于签名最好把证书的权限放开,免得又报签名的错误,具体设置如下:
打开钥匙串访问-》找到对应的描述-》双击-》改为允许所有访问,如图:

image.png

4.有没有CocoaPods是用不同的命令进行编译的,需要二选一
5.蒲公英的上传需要注册一个号,实名认证,然后后台拿取两个对应KEY,填入脚本即可在打包完成后上传

至此任务创建好后,可以手动点击开始任务,任务开始后就如下图:

image.png

总结

因为公司一般会有台xx云服务器,适合用于做CI的总控,然而目前还没有哪个厂商有Mac服务器的镜像,那么如果需统一自动化打包那么iOS就掉链子了,所以我们完全可以用一台公司内网的Mac专门用来自动化打包iOS应用,也可以多创建几个节点灵活使用,反正各种场景就完全看你的需求了。

今天整个实践之路非常坎坷,基本记录下了主要的坑,还有一些坑可能忘记记录了,遇到坑的同学可以给我留言,反正我是各种坑踩了一堆,最后终于算是成功了,经历了43次的失败,最后晒晒成绩单:

image.png

希望我的经历可以给正在路上的你,清空障碍,欢迎各位评论点赞,如果大家喜欢,后面我会陆续上Android、Maven+SpringMVC、Maven+SpringBoot等CI自动化发布的文章,谢谢

iOS
Web note ad 1