设为首页 收藏本站
查看: 1006|回复: 0

[经验分享] 一步一步构建iOS持续集成:Jenkins+GitLab+蒲公英+FTP

[复制链接]

尚未签到

发表于 2018-1-11 16:33:11 | 显示全部楼层 |阅读模式
什么是持续集成

  持续集成是一种软件开发实践,即团队开发成员经常集成它们的工作,通过每个成员每天至少集成一次,也就意味着每天可能会发生多次集成。每次集成都通过自动化的构建(包括编译,发布,自动化测试)来验证,从而尽早地发现集成错误。


为什么使用持续集成

  1.减少风险
  2.减少重复过程
  3.任何时间、任何地点生成可部署的软件
  4.增强项目的可见性


常用的持续集成工具


  • Jenkins CI
  • Travis CI
  • Hudson CI
  • Circle CI
  市面上的持续集成工具有很多,考虑到Jenkins的稳定性,我们还是选择以Jenkins来开始iOS的持续集成。
  好吧,接下来就正式开始搭建iOS持续集成平台了。

Jenkins的安装
  在Mac环境下,我们需要先安装JDK,然后在Jenkins的官网下载最新的war包。
  下载完成后,打开终端,进入到war包所在目录,执行以下命令:
  java -jar jenkins.war --httpPort=8888
  httpPort指的就是Jenkins所使用的http端口,这里指定8888,可根据具体情况来修改。待Jenkins启动后,在浏览器页面输入以下地址:
  http://localhost:8888
  这样就打开Jenkins管理页面了。

Jenkins的配置


  •   安装GitLab插件
      因为我们用的是GitLab来管理源代码,Jenkins本身并没有自带GitLab插件,所以我们需要依次选择 系统管理->管理插件,在“可选插件”中选中“GitLab Plugin”和“Gitlab Hook Plugin”这两项,然后安装。

  •   安装Xcode插件
      同安装GitLab插件的步骤一样,我们依次选择系统管理->管理插件,在“可选插件”中选中“Xcode integration”安装。

  •   安装签名证书管理插件
      iOS打包内测版时,需要发布证书及相关签名文件,因此这两个插件对于管理iOS证书非常方便。还是在系统管理->管理插件,在“可选插件”中选中“Credentials Plugin”和“Keychains and Provisioning Profiles Management”安装。

  •   安装FTP插件
      在系统管理->管理插件,在“可选插件”中选中“Publish over FTP”安装。

  •   安装脚本插件
      这个插件的功能主要是用于在build后执行相关脚本。在系统管理->管理插件,在“可选插件”中选中“Post-Build Script Plug-in”安装。

  好了,插件安装完,可以正式开始自动化构建了!!!

自动化构建
  在Jenkins中,所有的任务都是以“item”为单位的。接下来我们就新建一个iOS的项目来开始自动化构建。点击“新建”,输入item的名称,选择“构建一个自由风格的软件项目”,然后点击“OK”。

DSC0000.png   然后按下图设置构建信息,

DSC0001.png   源码管理:
  这里用到的是GitLab,先需要配置SSH,我们可以在Jenkins的证书管理中添加SSH。在Jenkins管理页面,选择“Credentials”,然后选择“Global credentials (unrestricted)”,点击“Add Credentials”,如下图所示,我们填写自己的SSH信息,然后点击“Save”,这样就把SSH添加到Jenkins的全局域中去了。

DSC0002.png   接下来,我们再回到刚刚新建的任务中,在源码管理中,选择Git,按下图填好相关信息。PS:Credentials不需要选择。

DSC0003.png   构建触发器设置
  因为此教程不涉及自动测试这块的流程,所以不需要设置触发器。(以后会有另外的自动测试教程^_^)
  构建环境设置
  iOS打包需要签名文件和证书,所以这部分我们勾选“Keychains and Code Signing>”和“Mobile Provisioning Profiles”。
  这里我们又需要用到Jenkins的插件,在系统管理页面,选择“Keychains and Provisioning Profiles Management”。

DSC0004.png   进入Keychains and Provisioning Profiles Management页面,点击“浏览”按钮,分别上传自己的keychain和证书。
  上传成功后,我们再为keychain指明签名文件的名称。点击“Add Code Signing>”,最后添加成功后如下图所示:

DSC0005.png   这样我们的Adhoc证书和签名文件就已经在Jenkins中配置好了,接下来我们只需要在item设置中指定相关文件即可。
  回到我们新建的item,找到构建环境,按下图选好自己的相关证书和签名文件。

DSC0006.png   Xcode配置
  点击“增加构建步骤”,选择“Xcode”。
  依次按下图填写项目信息:

DSC0007.png
DSC0008.png
DSC0009.png   脚本设置
  我们没有勾选“Pack application and build.ipa”的原因是,Jenkins的Xcode插件不支持Mac10.10以上的打包了。所以,我们需要用脚本来自己实现iOS打包。
  仍然是点击“增加构建步骤”,选择“Execute Shell”。
  输入下列脚本:
  if [ -d "${WORKSPACE}/builds" ]; then rm -rf ${WORKSPACE}/builds; fi;
mkdir ${WORKSPACE}/builds;
if [ -d "${WORKSPACE}/builds/${BUILD_NUMBER}" ]; then rm -rf ${WORKSPACE}/builds/${BUILD_NUMBER}; fi;
mkdir ${WORKSPACE}/builds/${BUILD_NUMBER};
xcodebuild -project ${WORKSPACE}/testForiOS/testForiOS.xcodeproj -scheme "testForiOS" -sdk iphoneos archive -archivePath ${WORKSPACE}/builds/${BUILD_NUMBER}/archive CODE_SIGN_IDENTITY="iPhone Distribution: xxxxxxx"
xcodebuild -exportArchive -exportFormat IPA -archivePath ${WORKSPACE}/builds/${BUILD_NUMBER}/archive.xcarchive -exportPath ${WORKSPACE}/builds/${BUILD_NUMBER}/${JOB_NAME}_${BUILD_NUMBER}.ipa -exportProvisioningProfile "XC Ad Hoc: com.xxxxx.xxx"
  这样我们就简单的实现了自动打包的所有配置了。
  不过,当iOS应用打包好后,我们还想发给其他相关人员安装,包括公司内部的,外网的,都需要。这时我们还需配置OTA服务和内网FTP。
  外网安装App我们需要用到现在市面上比较流行的免费平台,蒲公英。在上面蒲公英官网设置相关信息后,我们可以写一个简单的脚本,来实现App打包后,上传到蒲公英和公司内网以及邮件提醒相关人员这一系列操作。
  我们先用Jenkins的插件配置FTP信息。进入系统管理页面,选择系统设置,找到“Publish over FTP”,按下图填好相关信息:

DSC00010.png   回到任务配置页面,点击“增加构建后操作步骤”,然后选择“Send build artifacts over FTP”,填写:

DSC00011.png   这样FTP服务就配置好了。
  接下来我们再点击“增加构建后操作步骤”,选择“Execute a set of scripts”,如下图所示:

DSC00012.png   所以配置都已经设置好,点击“保存”,好了,我们可以试试点击“立即构建”按钮了。
  SUCCESS!!!
  以上就是iOS持续集成的简单内容,教程中暂未涉及到自动测试,以后会推出自动测试的内容,未完待续。。。。
  

附(脚本内容):  
#coding
=utf-8  
import time
  
import urllib2
  
import time
  
import json
  
import mimetypes
  
import os
  
import smtplib
  
from email.MIMEText import MIMEText
  
from email.MIMEMultipart import MIMEMultipart
  
import json
  

  
#蒲公英应用上传地址
  
url
= 'http://www.pgyer.com/apiv1/app/upload'  
#蒲公英提供的 用户Key
  
uKey
= 'xxxx'  
#上传文件的文件名(这个可随便取,但一定要以 ipa 结尾)
  
file_name
= 'xxxx.ipa'  
#蒲公英提供的 API Key
  
_api_key
= 'xxxxx'  
#安装应用时需要输入的密码,这个可不填
  
installPassword
= '123456'  

  
# 运行时环境变量字典
  
environsDict
= os.environ  
#此次 jenkins 构建版本号
  
jenkins_build_number
= environsDict['BUILD_NUMBER']  

  
#项目名称,用在拼接 tomcat 文件地址
  
project_name
= 'xxxx'  
#ipa 文件在 tomcat 服务器上的地址
  
ipa_file_tomcat_http_url
= 'ftp://192.168.10.4/jenkins/iOS/' + jenkins_build_number + '/' + project_name +'_' + jenkins_build_number + '.ipa'  

  
#获取 ipa 文件路径
  
def get_ipa_file_path():
  
#工作目录下面的 ipa 文件
  
ipa_file_workspace_path
= '/Users/Shared/Jenkins/Home/jobs/' + project_name + '/workspace/builds/' + jenkins_build_number + '/' + project_name + '_' + jenkins_build_number + '.ipa'  
#tomcat 上的 ipa 文件
  
ipa_file_tomcat_path
= '/usr/local/tomcat/webapps/' + project_name + '/static/' + jenkins_build_number + '/' + jenkins_build_number + '.ipa'  

  
if os.path.exists(ipa_file_workspace_path):
  
return ipa_file_workspace_path
  
elif os.path.exists(ipa_file_tomcat_path):
  
return ipa_file_tomcat_path
  

  
#ipa 文件路径
  
ipa_file_path = get_ipa_file_path()
  
print ipa_file_path
  
#请求字典编码
  
def _encode_multipart(params_dict):
  
boundary = '----------%s' % hex(int(time.time() * 1000))
  
data = []
  
for k, v in params_dict.items():
  
data.append('--%s' % boundary)
  
if hasattr(v, 'read'):
  
filename = getattr(v, 'name', '')
  
content = v.read()
  
decoded_content = content.decode('ISO-8859-1')
  
data.append('Content-Disposition: form-data; name="%s"; filename="SASDKDemo.ipa"' % k)
  
data.append('Content-Type: application/octet-stream\r\n')
  
data.append(decoded_content)
  
else:
  
data.append('Content-Disposition: form-data; name="%s"\r\n' % k)
  
data.append(v if isinstance(v, str) else v.decode('utf-8'))
  
data.append('--%s--\r\n' % boundary)
  
return '\r\n'.join(data), boundary
  

  
#处理蒲公英上传结果
  
def handle_resule(result):
  
json_result = json.loads(result)
  
if json_result['code'] is 0:
  
send_Email(json_result)
  

  
#发送邮件
  
def send_Email(json_result):
  
appName = json_result['data']['appName']
  
appKey = json_result['data']['appKey']
  
appVersion = json_result['data']['appVersion']
  
appBuildVersion = json_result['data']['appBuildVersion']
  
appShortcutUrl = json_result['data']['appShortcutUrl']
  
#邮件接受者
  
mail_receivers = ['xxx@xxx.com', 'xxx@xxx.com']
  
#根据不同邮箱配置 host,user,和pwd
  
mail_host = 'smtp.xxx.com'
  
mail_user = 'xxx@xxx.com'
  
mail_pwd = '123'
  
mail_to = ','.join(mail_receivers)
  
msg = MIMEMultipart()
  

  
environsString = '<h3>移动端iOS安装包</h3><p>'
  
environsString += '<p>内网ipa包下载地址 : ' + ipa_file_tomcat_http_url + '<p>'
  
environsString += '<p>外网在线安装 : ' + 'http://www.pgyer.com/' + str(appShortcutUrl) + '<p>'
  
environsString += '<li><a href="itms-services://?action=download-manifest&url=https://ssl.pgyer.com/app/plist/' + str(appKey) + '">手机直接安装</a></li>'
  
message = environsString
  
body = MIMEText(message, _subtype='html', _charset='utf-8')
  
msg.attach(body)
  
msg['To'] = mail_to
  
msg['from'] = mail_user
  
msg['subject'] = 'iOSxxx版本最新打包文件'
  

  
try:
  
s = smtplib.SMTP()
  
s.connect(mail_host)
  
s.login(mail_user, mail_pwd)
  

  
s.sendmail(mail_user, mail_receivers, msg.as_string())
  
s.close()
  

  
print 'success'
  
except Exception, e:
  
print e
  
#############################################################
  

  
#请求参数字典
  
params = {
  
'uKey': uKey,
  
'_api_key': _api_key,
  
'file': open(ipa_file_path, 'rb'),
  
'publishRange': '2',
  
}
  
coded_params, boundary = _encode_multipart(params)
  
req = urllib2.Request(url, coded_params.encode('ISO-8859-1'))
  
req.add_header('Content-Type', 'multipart/form-data; boundary=%s' % boundary)
  
try:
  
resp = urllib2.urlopen(req)
  
body = resp.read().decode('utf-8')
  
handle_resule(body)
  
except urllib2.HTTPError as e:
  
print(e.fp.read())
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-433964-1-1.html 上篇帖子: GitLab 5.3 升级注意事项 下篇帖子: gitlab安装过程总结
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表