作为iOS开发,每次打包都特别麻烦,需要耗费不少时间。于是我们可以采用Jenkins来做持续化集成,自动打包。
这里采用的是在Mac上安装Jenkins环境,拉取Git上的代码,通过参数化配置,编写shell脚本,打包Xcode工程iOS代码,自动发布到蒲公英上,同时通过钉钉来推送打包的状态
一、Jenkins环境的安装配置
首先我们需要安装Jenkins的运行环境,安装Java 8。
配置好Java环境后,我们再进行安装Jenkins,这里我们采用的是war包安装的方式。
- 我们需要从Jenkins官网下载war包
- 将war包拷贝相应的目录,这里我放在了用户目录下,然后执行安装命令
java -jar jenkins.war
- 安装完成后,会显示如下界面,其中有一串Jenkins的登录密码,然后打开http://localhost:8080即可显示Jenkins页面
期间我们可能需要稍等一会儿,首次启动Jenkins会进行一些相关配置。
然后我们就可以看到如下界面。
另外如果你有装tomcat,你也可以将Jenkins.war包放在tomcat的webapps目录下,然后启动tomcat服务器:sudo sh startup.sh
(如果你没有在.bash_profile环境变量下配置tomcat的启动路径,那么你需要到tomcat的bin目录下执行该命令)
当看到tomcat启动完成后,在浏览器输入http://localhost:8080/jenkins,即可看到Jenkins启动页。
关闭tomcat的命令是:sh ./shutdown.sh
-
将刚刚看到的密码复制到启动页的管理员密码处,就解锁了Jenkins
然后进入下一步,选择安装推荐的插件,接着会自动安装相关插件。
- 接着我们创建一个管理员用户
- 配置Jenkins的地址,就完成了Jenkins的安装配置
二、配置
接下来我们就开始配置自动打包Xcode工程
1.首先我们创建一个新的构建任务
点击新建Item,输入任务名称,选择FreeStyle project,即可完成创建构建任务。
创建完成后如上图所示,这里我建了一个叫newProject的任务。
2. 安装相关插件
回到Jenkins首页,选择进入Jenkins的管理配置页
选择Manager Plugins,管理插件,在可选插件页搜索并安装
1)DingTalk插件,这是为了来做构建后钉钉通知的
2)GitLab Plugin和Gitlab Hook Plugin,用GitLab管理源代码的
3)Xcode integration,用来使用Xcode命令打包工程的
4)Git parameter,用来进行参数化构建的
安装完钉钉插件后对钉钉做一些相关配置
先在钉钉上建一个群,然后在群里添加一个自定义的webhook机器人,拿到webHook地址和加密的字串
然后进入到Jenkins的配置页,对钉钉做一些配置,填入上面的webhook地址和加密字串,id是系统自动生成的,选择通知时机。然后测试一下,看到群里收到钉钉消息就成功了。保存退出
3.然后进入到构建任务的设置界面
1)General
首先我们可以看到一个钉钉配置,这里我们勾选上钉钉机器人即可,另外我们还可以自定定义通知人和消息内容,到这里,我们就完成了钉钉的消息推送配置。
接着我们进行参数化构建,可以根据自己需求选择是否需要参数化构建,这里参数化构建指的我们可以在构建打包工程之前通过这里配置的参数,来打不同的包,这里我们可以设置Jenkins的内置参数,也可以自定义参数,自定义的参数可以通过脚本修改Xcode工程中的配置文件,从而达到工程读取不同的配置文件内容展现不同的功能,这里两种方式都有演示。
这里我配置了一个Jenkins的参数和一个自定义参数,其中iOS_Branch_Tag可以用来区分构建不同分支上的代码,iOS_Code_Params是用来演示配置文件的参数,后面会讲到
2)源码管理
我们这里是采用的git方式管理代码,因此我们选择Git,然后配置好URL和身份信息,没有身份信息点击添加,填写用户名和密码即可。
然后选择我们进行构建的分支,由于我们是采用参数化配置构建分支的,因此这里我们填入上面配置的参数。
3)构建触发器
这里可以根据自己的需求进行配置:可以选择当有Git操作时就构建,也可以自己设置定时任务等。。。,这里我选择当有Git操作就执行打包任务.
4)构建环境
这里我们没有什么需要进行配置的
5)构建
这里我们选择使用shell脚本进行构建,直接执行脚本就可以。这里建了一个shell脚本文件,用来执行
这一步是最重要也是最复杂的一步
我们需要编写构建的脚本代码,在这之前我先列举一下常用的环境变量
Jenkins常用内置参数:
echo $HOME:MAC下用户目录。例如:$HOME表示:/Users/用户名
echo $WORKSPACE:Jenkins的工作目录。例如你创建了一个newProject的工作空间,那么对应的路径就是: /Users/用户名/.jenkins/workspace/newProject
echo $JOB_NAME:Jenkins的工作目录名称。例如你创建了一个newProject的工作空间,那么对应的名称为:newProject
echo $BUILD_NUMBER:Jenkins的构建版本号。例如:43
echo $HUDSON_URL/ echo $JENKINS_URL:jenkins的url。例如:http://localhost:8080/
echo $BUILD_URL:build的url。例如:[http://localhost:8080/job/newProject/43/](http://localhost:8080/job/newProject/43/)
echo $JOB_URL:job的url。例如:[http://localhost:8080/job/newProject/](http://localhost:8080/job/newProject/)
echo $BUILD_DISPLAY_NAME:当前版本的显示名称,默认为“#153”。例如:#43
echo $BUILD_TAG:“jenkins- $ {JOB_NAME} - $ {BUILD_NUMBER} ”的字符串。JOB_NAME中的所有正斜杠(/)都会用破折号( - )替换。方便放入资源文件,jar文件等,以方便识别。例如:jenkins-newProject-43
echo $EXECUTOR_NUMBER:识别执行此构建的当前执行程序(在同一台计算机的执行程序中)的唯一编号。这是您在“构建执行者状态”中看到的数字,但数字从0开始,而不是1。例如:1
echo $NODE_NAME:代理的名称,如果构建是代理,或者“主”,如果在主机上运行。例如:master
echo $NODE_LABELS:空格分隔的节点分配的标签列表。例如:master
echo $JENKINS_HOME:Jenkins在硬盘上存储路径。例如:/Users/meme/.jenkins
下面使我们的打包脚本
# 设置mac的keychain的开机密码
security unlock-keychain -p "开机密码" $HOME/Library/Keychains/login.keychain-db
# 更新pod
pod install
# 删除之前构建的数据
rm -rf $WORKSPACE/exportPath
rm -rf $WORKSPACE/dist
# 修改本地参数配置文件, 根据Jenkins配置修改工程配置文件
# 采用sed语法
JENKINS_CONFIG_FILE=$WORKSPACE/NewLive/Jenkins/jenkins_config.json
PATTERN1="iOS_Code_Params.*"
PATTERN2="iOS_Code_Params\":params1,"
sed -ig 's/'$PATTERN1'/'$PATTERN2'/g' $JENKINS_CONFIG_FILE
if [ "params1" = "$iOS_Code_Params" ];then
PATTERN2="iOS_Code_Params\":params1,"
sed -ig 's/'$PATTERN1'/'$PATTERN2'/g' $JENKINS_CONFIG_FILE
else
PATTERN2="iOS_Code_Params\":params2,"
sed -ig 's/'$PATTERN1'/'$PATTERN2'/g' $JENKINS_CONFIG_FILE
fi
# 利用xcodebuild 生成 .xcarchive 文件
xcodebuild -archivePath NewLive/NewLive.xcarchive -workspace $WORKSPACE/NewLive/NewLive.xcworkspace -sdk iphoneos -scheme "NewLive" -configuration "Debug" archive
# 生成 ipa 文件
xcodebuild -exportArchive -archivePath NewLive/"NewLive.xcarchive" -exportOptionsPlist $WORKSPACE/JenkinsConfig/NewMeme.plist -exportPath "exportPath"
#
# 将编译后的文件复制到jenkins对应的结构目录里面
#
mkdir -p $WORKSPACE/dist/$JOB_NAME
mv $WORKSPACE/NewLive/NewLive.xcarchive $WORKSPACE/dist/$JOB_NAME/$JOB_NAME-$BUILD_NUMBER.xcarchive
mv $WORKSPACE/exportPath/NewLive.ipa $WORKSPACE/dist/$JOB_NAME/$JOB_NAME-$BUILD_NUMBER.ipa
# 上传蒲公英
#蒲公英上的User Key
uKey="7506db9b52d4c572ce0594c67fb633f2"
#蒲公英上的API Key
apiKey="8e217b9ab23df1ee940ae31a8577378c"
#要上传的ipa文件路径
IPA_PATH="$WORKSPACE/dist/$JOB_NAME/$JOB_NAME-$BUILD_NUMBER.ipa"
#执行上传至蒲公英的命令,这句不需要修改
curl -F "file=@${IPA_PATH}" -F "uKey=${uKey}" -F "_api_key=${apiKey}" https://www.pgyer.com/apiv1/app/upload
# 生成bugly用的符号表, 手动上传至Bugly符号表管理,可以设置Xcode Run Script 自动上传至Bugly符号表管理
#if [ "Debug" = "$Configuration" ];then
#echo "测试模式下没有bugly的包"
#else
#Java -jar /Users/meme/bin/buglySymboliOS.jar -i $WORKSPACE/dist/$JOB_NAME/$JOB_NAME-$BUILD_NUMBER.xcarchive/dSYMs/么么直播.app.dSYM -o $WORKSPACE/dist/$JOB_NAME/$JOB_NAME-$BUILD_NUMBER.dSYMs.bugly.zip
#fi
对于以上脚本做几点解释:
- 由于我们是独立的打包机,可能会锁屏,所以需要输入开机密码
- 我们的工程有用到pod,所以打包之前需要更新下pod库
- 接着是删除之前构建的文件,防止存储空间不够,不过如果你要作为发布版本打包的话,你需要将打包文件存下来,后面可能需要代码的符号表。你也可以自己做个配置处理
-
接着是为了处理参数化构建,我们上面在General中定义了一个自定义参数iOS_Code_Params,这里预设了两个选项param1和param2,同时我们在工程的Jenkins目录下见了一个jenkins_config.json的配置文件。
这段代码就是根据Jenkins构建前选择的配置修改工程中的配置文件。
然后我们代码里读取响应的配置文件,如下:
override func viewDidLoad() {
super.viewDidLoad()
presentAlert(getJenkinsParams())
}
func getJenkinsParams() -> String {
// false 使用hybrid_link 测试使用的
// true 使用dev_hybrid_link 开发使用的
var params = ""
do {
let filePath = Bundle.main.path(forResource: "jenkins_config", ofType: "json")
if FileManager.default.fileExists(atPath: filePath ?? "") {
var configDic: [AnyHashable : Any]? = nil
if let data = NSData(contentsOfFile: filePath ?? "") {
configDic = try! JSONSerialization.jsonObject(with: data as Data, options: .mutableContainers) as? [AnyHashable : Any]
}
if let param = configDic?["iOS_Code_Params"] as? String {
params = param
}
}
} catch {
}
return params
}
func presentAlert(_ message: String, okTitle: String = "确定", finished: NLFinishedBlock? = nil) {
guard !message.isEmpty else {
return
}
let alertView = UIAlertController(title: message, message: "", preferredStyle: .alert)
alertView.addAction(UIAlertAction(title: okTitle, style: .default) { _ in
finished?()
})
UIViewController.current()?.present(alertView, animated: true, completion: nil)
}
这里简单处理 下,就是读取配置文件然后弹出来。
根据自己需求设置参数和文件位置,另外这里采用的是sed语法,有兴趣可以自己了解一下。
- 接下来我们通过xcodebuild命令进行打包,这个命令做过iOS应该都比较熟悉了,首先生成.xcarchive文件,然后根据.xcarchive文件生成.ipa文件。这里注意要设置对代码文件的位置,以及.xcarchive文件和.ipa文件的输出路径,这里我放在了工程目录下。
- 我们这里打包采用的手动配置证书,Xocde证书要配置好,在执行xcodebuild命令之前,我们需要准备一个.plist文件,文件里包含有打包的环境(debug还是release),证书,pp文件名称。。。,这些我们可以根据以前手动打包生成的.ipa文件时,有一个.plist文件,改一下.plist文件内容即可。或者觉得不太清楚的话,先手动打个包,将打包好的.plist文件拷贝过来即可,注意要设置好路径。
7.这里使用脚本就是为了用户在Jenkins配置里填一堆乱七八糟的东西,还要下载各种插件等等,比较麻烦,脚本的话一下就搞定了,后面配置其他工程也方便。
8.如果不喜欢使用xcodebuild命令的话,也可以使用fastlane进行打包,这个还更方便点.
9.我这里做了移动文件的操作,你们可以按需来
10.上传到蒲公英上,需要自己进蒲公英注册个应用拿到ukey和api key,最后上传即可
11.这里还加了一段生成Bugly符号表的操作,其实我们可以直接在Xcode的Run Script中加入,可以自动生成符号表并上传到Bugly后台。
6)构建后操作
这里加了一个归档成品,就是读取到打包出来的.ipa文件,可以在Jenkins的工作控件页面看到.ipa文件直接下载。这两个路径是上面脚本中最终将.ipa拷贝到的路径位置。
到这里,关于项目的Jenkins配置就完成了。
我们回到项目首页,配置相关参数进行构建即可
当开始构建、构建成功、构建失败,都会有消息推送到钉钉群里
构建成功后,你可以在Jenkins页面上看到打包出来的.ipa文件,以及蒲公英上传的.ipa文件,同时还可以看到Bugly后台的符号表文件(前提是在Xcode工程中配置过了)
相关截图:
- 相关构建参数选择,选择完后,进行开始构建
- 构建过程中我们可以点控制台输出查看构建日志
- 构建成功后,会在任务界面上显示包文件,点击可以直接下载
4.钉钉群消息
5.还有蒲公英和Bugly的就不截图了
总结:
我们采用Jenkins在Mac上对Xcode工程做了自动打包操作,涉及到有自定义构建参数,Git代码,shell脚本打包,蒲公英自动上传,钉钉推送打包状态。
其中注意的是编写shell脚本时各个目录结构,证书、PP文件的配置。
对于参数化构建,打包方式(xcodebuild、Fastlane)、蒲公英自动上传和钉钉通知可以按各自需求