使用 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 打包,但是这次需要注意的我们的需求是:
rightProvision
了解的不够透彻?解决:把三种证书都从开发那里要过来,然后将自己的 APPLE ID 升级到开发者Admin
状态,就具有了三种证书的使用权限,然后跟开发一一对接,对每个包分别对应的证书了解并整理,打包的时候一一对应上就好。这个过程中,收获的是对 xcodebuild 的 method 参数有更深的了解,其实 inhouse,adhoce,appstore 分别对应的打包方式是enterprise
,ad-hoc
,app-store
。
解决:之前想通过是打包的时候指向不同的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)
但是需要注意的是像素和尺寸需要保持一致,设计同学的帮忙很必要。
解决:其实我觉得 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)
然后构造请求,发送即可,详细不表。
sed -i '' 's/ProvisioningStyle = Automatic;/ProvisioningStyle = Manual;/g'
"$project_path/project.pbxproj"
若是 pod 问题,可以通过升级 gem 解决。
sudo gem update --system
sudo gem install -n /usr/local/bin cocoapods
我知道我写的可能并不好,排版可能也不漂亮,但是是我们已经落地在用的工程,后续再加上持续集成 jenkins 中遇到的问题,请大家轻拍。谢谢。
再附上我们推送的截图。