Jenkins iOS 打包并上传至蒲公英

CI/CD with Jenkins 折腾良久用于还是给我搞掂了, 下面就来说说我到底是怎么淌过这些坑的(真心就是不停的淌坑, 简直毫无乐趣可言, 不过淌完后还是很畅快的:-D)

步骤

这里不得不先来说下步骤, 因为每一步都非常重要, 稍不注意都会 GG

  1. 安装 Java
  2. 安装 Jenkins
  3. 配置 ssh key
  4. Xcode 相关配置(这里神坑)
  5. Command 编译, 打包脚本(这里照样坑的一匹)
  6. 上传安装包至蒲公英
  7. 使用 Jenkins 自动化

开搞

再次温馨提示: 请务必按照步骤来

安装 Java

本来这里没什么好说的一个命令搞定的事
但是众所周知 Oracle 开始对 Java 收费, 现在安装 Java 会出现一些麻烦, 不过可以到网上找到一些镜像

注意: 这里最好安装 OracleJava8, 我尝试了 OpenJava12 并不行

安装 Jenkins

Java 安装好后这里基本就没啥好说的了, 到官网下载对应平台的的二进制文件安装, 无脑 next 就行

使用homebrew进行安装

1
2
3
4
5
brew install jenkins

# 启动
cd cd /usr/local/Cellar/jenkins/{version}/libexec
java -jar ./jenkins.war

注意: 按理说二进制安装后Jenkins的服务会自动启动并打开, 但是我遇到了他自己没有启动的情况, 这里就需要自己检查一下端口占用的问题了, 我的情况是8080端口被我安装的Docker给占用了, 这时可以关闭Docker或者更改Jenkins的端口, 更改方式我这里就不给出了, 可以自行搜索

Jenkins 配置

奏是按照提示无脑下一步

第一次进入会告诉你需要输入密码, 按照提示打开改路径下的文件密码就在里面, 填入就行
记住需要使用sudo才能打开, 否则没权限(当然密码在你启动Jenkins的时候其实就已经显示在控制台了, 仔细查看还是能找到的)

1
sudo cat /Users/wsh/.jenkins/secrets/initialAdminPassword

选择安装建议插件, 我这个用到的就只有shellgit

建议创建一个新的账号, 如果你奏是像用root账号登录的话, 那么我告诉你密码就是initialAdminPassword里的那个长串

配置 ssh key

请看我的另一篇Blog: SSH keys 公钥配置与使用

github公钥配置上文中已给出, 其他平台的配置方法大同小异, 这里不赘述,可执行搜索

Xcode 相关配置(这里神坑)

如果是在你自己的开发机上进行编译的话, 那你可能就不会遇到这些问题, 不过最好还是看下以供参考

  • Macos: 10.14.4
  • Xcode: 10.2.1

上面是我的系统和编译环境

证书

查看Xcode 链接真机调试这篇文章中关于证书相关的内容, 安装证书

当然你可以把你开发机上的证书拷贝到你的编译机上去, 同样的我这里不做阐述, 执行搜索

登录 Apple 账号

编译归档(神坑)

为什么说这里是神坑呢, 如果你不用Xcode先进行一次编译归档操作就直接进行命令行打包就会出现找不到provisioning profile文件, 打包失败

点击Product -> Archive等待编译完成后进入归档页面, 此时选择Ad Hoc, 然后无脑下一步
最后点击Export导出, 然后找到导出的问题件夹内的ExportOptions.plist文件保存好, 之后使用命令行编译时需要用到(这里很重要, 网上一大堆资料都没说怎么得到这个文件, 以及这个文件的作用)

网上的资料全部都是选择第一项App Store, 但是我选择使玩这项后, 使用命令行打包出来的ipa并不能成功安装到手机上

Command 编译, 打包脚本(这里照样坑的一匹)

这里把编译先搞清楚, 之后再来部署Jenkins就水到渠成了, 所以我把命令行编译这块单独拿出来解释说明
Jenkins最终要执行的就是这些命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 根据实际情况修改target和scheme名字
# 通常情况下他们的名字都是一样的, 如果你修改的了的话就当我没说
TARGET_NAME="MHDemo"
SCHEME_NAME="MHDemo"
XCARCHIVE_NAME="MHDemo.xcarchive"

# clean 清理编译缓存
xcodebuild clean -target ${TARGET_NAME} \
-scheme ${SCHEME_NAME} \
-configuration Release

rm -rf ./build
rm -rf ./ExportOptions.plist
mkdir -p ./build/Release-iphoneos

# 创建 ExportOptions.plist 文件
# 当然你也可以把它放在本地的某个地方, 但是我出于管理方便所以我把它放在了 shell 脚本中自动生成了
# 这个文件就是上面通过 Xcode 归档后生成的, 我这里剔除了所有不必要的信息, 只保留的核心内容
# Update 2019-10-11: Xcode 11 需要添加: <key>compileBitcode</key><false/>
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?><plist version=\"1.0\"><dict><key>method</key><string>ad-hoc</string><key>compileBitcode</key><false/></dict></plist>" > ExportOptions.plist

# 执行归档操作
xcodebuild -archivePath ./build/Release-iphoneos/${XCARCHIVE_NAME} \
-target ${TARGET_NAME} \
-scheme ${SCHEME_NAME} \
-configuration Release \
archive

# 生成 ipa 安装文件
xcodebuild -exportArchive -archivePath ./build/Release-iphoneos/${XCARCHIVE_NAME}\
-exportPath ./build/ \
-exportOptionsPlist ./ExportOptions.plist \
-allowProvisioningUpdates

如果上述操作都没有问题的话, ipa安装包应该会生成在项目根目录下的build文件夹下

上传安装包至蒲公英

上传到fir.im应该也是大同小异的, 大家执行搜索一下, 我这里只以蒲公英为例子

1
2
3
4
5
6
7
8
9
10
11
12
# 蒲公英上的User Key
uKey="3582ee5da8a51e153d89233389exxxxx"
# 蒲公英上的API Key
apiKey="7eec744cc7509408231e0792594xxxxx"
# 要上传的ipa文件路径
IPA_PATH="./build/${TARGET_NAME}.ipa"
# 密码
PASSWORD="lzq951236"
MSG=`git log -1 --pretty=%B`
# 执行上传至蒲公英的命令
echo "++++++++++++++upload+++++++++++++"
curl -F "file=@${IPA_PATH}" -F "uKey=${uKey}" -F "_api_key=${apiKey}" -F "updateDescription=${MSG}" -F "password=${PASSWORD}" http://www.pgyer.com/apiv1/app/upload

上传成功, 命令行会返回code: 0, 表示成功

如果需要上传到自己的服务器, 其实也是同理, 使用上面脚本的之后一行的curl命令就好, 具体可自行搜索curl如何使用

使用 Jenkins 自动化

上面的所有环节都打通了, 使用Jenkins完成自动化, 还会有什么难度吗?

不过我这里还是简单的说一下把, 免得大家看了网上的一些资料后又走上了歪路

新建任务

新建任务 -> 输入任务名称 -> 构建一个自由风格的软件

源码管理

源码管理 -> Git -> Repository URL -> 输入创库地址

添加 clone 创库的凭证

私钥来自之前我们创建的ssh key, 私钥路径~/.ssh/id_rsa 注意: 公钥必须首先配置到了git托管平台, 公钥路径~/.ssh/id_rsa.pub

执行 shell

首先增加构建步骤

拷贝上文的脚本至命令输入框内, 注意替换你实际的项目名称, 人后点击保存, 最后点击立即构建, 开始执行自动化构建
此时大功告成, 如果你想使用构建触发器的话, 请执行查阅资料, 这个比较简单, 这里就不做说明了

关于 Xcode integration 插件

最开始也是使用的这种方式进行的部署, 但是很遗憾无论我怎么折腾都没能完成工作

遇到的问题: userString = "Your session has expired. Please log in.";
网友的说法是, 只要Xcode重新登录就能解决问题了
还有的说法是没有解锁钥匙串, 我个人任务这个说法比较可信, 但是很遗憾按照网友的说法并没能解决问题
如果哪位大佬能看到这篇文章的话, 知道这是怎么回事, 劳烦我说一声, 🙏

参考资料

https://forums.developer.apple.com/thread/70326
https://medium.com/xcblog/xcodebuild-deploy-ios-app-from-command-line-c6defff0d8b8
https://shashikantjagtap.net/full-stack-ios-continuous-delivery-with-xcodebuild-and-exportoptions-plist/
http://oriochan.com/projectManage.html
https://www.jianshu.com/p/91e8f571fc2b
https://www.jianshu.com/p/9cb3d8c8c78d
https://www.jianshu.com/p/ce36997919b4