使用jenkins有将近三四个月了,为了支持iOS打包,网上有开源的工具集fastlane,就简单总结一下,使用的心得和过程中遇到的坑。。。。

一、打包

下载fastlane,就三个命令:

sudo gem update --system
sudo gem install bundler
sudo gem install fastlane

可以查看一下 fastlane -v的版本,我们打包主要用到gym和上传命令pilot,其他工具略有研究,但是未深入,还要提醒,我都是用的命令行格式,未使用官方推荐的Fastfile的方式,主要是我对ruby不够了解,因为我也是个大菜鸟。附上打包命令。

gym打包,需要讲解的不多,DEVELOPMENT_TEAM等等解释,可以详细看这里https://dpogue.ca/articles/cordova-xcode8.html
需要提醒的是 xcpretty_report_josn可以输出oclint需要的xcpretty执行之后的内容,这里可以oclint集成到一起

DEVELOPER_DIR="/Applications/Xcode.app" gym --workspace ${workspace_path} 
--scheme ${scheme} --clean true
--configuration ${configuration}
--xcargs "PRODUCT_BUNDLE_IDENTIFIER='${bundle_id}' DEVELOPMENT_TEAM='${DEVELOPMENT_TEAM}' PROVISIONING_PROFILE_SPECIFIER='${PROVISIONING_PROFILE_SPECIFIER}'"
--export_method ${export_method} --archive_path ${archive_path}
--codesigning_identity "${rightDistributionSign}" --xcpretty_report_json "${json_path}"
--export_options ${ExoptionPlist}
--output_directory ${ipa_path} --output_name ${ipa_name} || exit

二、集成

讲讲其他遇到的坑和解决方案。
由于主要使用fastlane中gym打包,但是这次需要注意的我们的需求是:


1、分别打三种包,对证书和rightProvision了解的不够透彻?

解决:把三种证书都从开发那里要过来,然后将自己的APPLE ID升级到开发者Admin状态,就具有了三种证书的使用权限,然后跟开发一一对接,对每个包分别对应的证书了解并整理,打包的时候一一对应上就好。这个过程中,收获的是对xcodebuild的method参数有更深的了解,其实inhouse,adhoce,appstore分别对应的打包方式是enterprisead-hocapp-store

2、需要更换inhouse的图标?

解决:之前想通过是打包的时候指向不同的target,后来的解决方案是直接替换。

for file in os.listdir(appIconPath):
if ".png" in file:
for appicon in os.listdir(replaceAppIconPath):
if file == appicon:
shutil.copy(replaceAppIconPath+'/'+appicon, appIconPath+'/'+file)

但是需要注意的是像素和尺寸需要保持一致,设计同学的帮忙很必要。

3、和slack对接

解决:其实我觉得slack真的非常好用,因为它提供了各种整合持续集成的api,这里特别佩服我们老大对这块内容的重视,slack和jenkins集成非常方便。
只是网速有点不靠谱。slack api地址:https://api.slack.com/docs/message-guidelines
附上我写的脚本,借助slack web api推送信息到slack,并且可以取出jenkins中执行者的信息:

#coding=utf-8
import sys
import time
import requests
import re
from slacker import Slacker

def send(job_url, job_name, starters, build_timestamp, workspace, build_cause, git_branch, change_log, text, userid):
"""执行结果推送slack,可选个人和channel"""
api_token = "xxxx"
slack = Slacker(api_token, 100)
data = [{
"fallback": "Required plain-text summary of the attachment.",
"color": "#36a64f",
"fields": [
{
"title": "Job name",
"value": job_name,
"short": True
},
{
"title": "Build Trigger",
"value": starters,
"short": True
},
{
"title": "Build Time",
"value": build_timestamp,
"short": True
},
{
"title": "Build Workspace",
"value": workspace,
"short": True
},
{
"title": "Root Build Cause",
"value": build_cause,
"short": True
},
{
"title": "GIT_BRANCH",
"value": git_branch,
"short": True
},
{
"title": "Job url",
"value": job_url,
},
{
"title": "CHANGE_LOG",
"value": change_log,
}

],
"footer": "XX公司",
"ts": time.time()
}
]
try_times = 0
while try_times < 5:
try:
slack.chat.post_message(userid, text=text, attachments=data)
return "push to slack failed"
except Exception as e:
time.sleep(50)
try_times += 1
if try_times >= 5:
raise Exception('push to slack failed')

def get_content(job_url):
"""取出console log全部内容"""
url = job_url + "consoleText/api/json"
headers = {
"Content-Type": "application/json",
"Accept": "application/json"
}
response = requests.get(url, auth=("xx", "xx"))
assert response.status_code == requests.codes.ok
return response.content

def get_trigger(result):
"""取出构建者"""
trigger_user = re.findall(r"Started by", result)
trigger_other = re.findall(r"Triggered by", result)
starters = ""
if len(trigger_user) > 0:
starters = re.findall(r"Started by(.*)", result)[0].lstrip()
elif len(trigger_other) > 0:
starters = re.findall(r"Triggered by(.*)", result)[0].lstrip()
return starters

if __name__ == '__main__':
if len(sys.argv) >= 2:
job_url = sys.argv[1]
job_name = sys.argv[2]
build_timestamp = sys.argv[3]
workspace = sys.argv[4]
build_cause = sys.argv[5]
git_branch = sys.argv[6]
text = sys.argv[7]
userid = sys.argv[8]
change_log = sys.argv[9]
result = get_content(job_url)
starters = get_trigger(result)
result = get_content(job_url)
starters = get_trigger(result)
send_userid = ["#xx", userid]
for i in send_userid:
send(job_url, job_name, starters, build_timestamp, workspace, build_cause, git_branch, change_log, text, i)

然后构造请求,发送即可,详细不表。

4、因为我们app两个平台用的xcode版本不一致,需要升级到xcode8,需要将自动管理改为手动管理证书。
sed -i '' 's/ProvisioningStyle = Automatic;/ProvisioningStyle = Manual;/g' 
"$project_path/project.pbxproj"
5、pod install总是出现问题,分析可能是因为网络或者本机pod安装有问题。

若是pod问题,可以通过升级gem解决。

sudo gem update --system
sudo gem install -n /usr/local/bin cocoapods

最后

我知道我写的可能并不好,排版可能也不漂亮,但是是我们已经落地在用的工程,后续再加上持续集成jenkins中遇到的问题,请大家轻拍。谢谢。
再附上我们推送的截图。


↙↙↙阅读原文可查看相关链接,并与作者交流