iOS开发实现每日构建生成ipa包
目标:Xcode的工程实现自动编译并且生成ipa包,上传到公司内部服务器,同时发送邮件给各相关人员,让他们下载安装。
环境:Mac OSX 10.x,Xcode5.x或6.x,Python2.7。代码使用git管理。 支持ssh/ftp上传的服务器,最好开启HTTP服务(下载文件)。
方法:通过shell命令编译生成ipa包,使用Python代码实现ftp上传并且发送出邮件。以下为详细代码。
假设:工程名和工程所在目录都是tastegameapp,ftp服务器192.168.0.0使用的是ssh/sftp协议,邮件发送服务器为QQ邮箱。
shell命令dailybuild.sh
#先checkout代码到一个地方然后执行脚本 #定义 varProj="tastegameapp" #工程名,XCode编译target名。一般是一样的。 varProjDir="tastegameapp" varFile=`date '+%Y-%m-%d'` #此处最外层符号`会将date解释为当前的时间 #进人工程所在目录 cd ../$varProjDir #删除以前编译生成的文件 rm -rf build/"$varProj".build/Debug-iphoneos/"$varProj".build rm -rf build/Debug-iphoneos/"$varProj".app rm -rf build/Debug-iphoneos/"$varProj".app.dSYM #开始编译 xcodebuild -configuration Debug -target "$varProj" >../ci/"$varProj"-log-$varFile.txt cd ../ci mkdir -p ipa/Payload #删除旧文件 rm -rf ipa/Payload/"$varProj".app rm -rf ipa/Payload/"$varProj".app.dSYM #将编译出的程序和符号拷贝到Payload目录下 cp -r ../"$varProjDir"/build/Debug-iphoneos/"$varProj".app ./ipa/Payload/ cp -r ../"$varProjDir"/build/Debug-iphoneos/"$varProj".app.dSYM ./ipa/Payload/ cd ipa #输出ipa文件,名字带有当日日期 zip -r "$varProj""$varFile".ipa Payload cd .. echo '正在上传文件' python ftpupload.py echo '正在发送邮件' python sendemail.py
ftp上传,ftpupload.py
#!/usr/bin/python #-*-coding=utf-8-*- import sys import paramiko import time import os import getpass import socket from datetime import date, timedelta #当天的时间 workdate=time.strftime('%Y-%m-%d') #open an SSH transport host = "192.168.0.0" port = 22 transport = paramiko.Transport((host, port)) #authenticate password = "密码" #用户名密码记得替换 username = "用户名" transport.connect(username = username, password = password) #transport.set_missing_host_key_policy(paramiko.AutoAddPolicy()) #start the SFTP client filename = "tastegameapp"+ workdate +".ipa" localfile = "ipa/"+filename remotefile = "/var/www/html/debug-ipa/"+filename sftp = paramiko.SFTPClient.from_transport(transport) sftp.put(localfile,remotefile) logfile = "tastegameapp-log-"+workdate+".txt" remotelog = "/var/www/html/debug-ipa/"+logfile sftp.put(logfile,remotelog) print "命令执行成功,文件已经上传" #close the SFTP connection and the transport sftp.close() transport.close()
发送邮件,sendemail.py
#!/usr/bin/python #coding=utf-8 import email import mimetypes from email.MIMEMultipart import MIMEMultipart from email.MIMEText import MIMEText from email.MIMEImage import MIMEImage import smtplib import logging import sys import os import time reload(sys) sys.setdefaultencoding('utf8') mailDict = {} #邮件配置信息 ################### #日志辅助类 ################# class Logger: LOG_RELEASE= "releae" LOG_RELEASE_FILE = "/tmp/pyMail.log" def __init__(self, log_type): self._logger = logging.getLogger(log_type) if log_type == Logger.LOG_RELEASE: self._logFile = Logger.LOG_RELEASE_FILE handler = logging.FileHandler(self._logFile) if log_type == Logger.LOG_RELEASE: formatter = logging.Formatter('%(asctime)s ********* %(message)s') else: formatter = logging.Formatter('%(message)s') handler.setFormatter(formatter) self._logger.addHandler(handler) self._logger.setLevel(logging.INFO) def log(self, msg): if self._logger is not None: self._logger.info(msg) MyLogger = Logger(Logger.LOG_RELEASE) #Logger def initMailConf():#初始化邮件配置信息 global mailDict timestr = time.strftime('%Y-%m-%d %A %X %Z', time.localtime()) mailDict['server'] = "smtp.exmail.qq.com" mailDict['port'] = '465' mailDict['user'] = "#邮箱用户名#" #用户名密码请替换为自己的 mailDict['password'] = "#密码#" mailDict["from"] = "" #显示在邮件里的发件人 mailDict["to"] = "" #收件人 mailDict["subject"] = "tastegameapp Daily Build " + timestr mailDict["text"] = "现在tastegameapp项目已经做了每日构建,每天都可以生成daily build文件\r\n安装文件可以在公司内网下载。地址下载地址\r\n"+"http://192.168.0.0/debug-ipa/tastegameapp" + time.strftime('%Y-%m-%d', time.localtime()) + ".ipa \r\n如果需要查看输出日志,详情请看附件。" def sendMail(paramMap):#发送邮件 smtp = smtplib.SMTP_SSL() msgRoot = MIMEMultipart('related') msgAlternative = MIMEMultipart('alternative') if paramMap.has_key("server") and paramMap.has_key("user") and paramMap.has_key("password"): try: smtp.set_debuglevel(1) smtp.connect(paramMap["server"], paramMap["port"]) smtp.login(paramMap["user"], paramMap["password"]) except Exception, e: MyLogger.log("smtp login exception!") return False else: MyLogger.log("Parameters incomplete!") return False if paramMap.has_key("subject") == False or paramMap.has_key("from")== False or paramMap.has_key("to") == False: MyLogger.log("Parameters incomplete!") return False msgRoot['subject'] = paramMap["subject"] msgRoot['from'] = paramMap["from"] if paramMap.has_key("cc"): msgRoot['cc'] = paramMap["cc"] msgRoot['to'] = paramMap["to"] msgRoot.preamble = 'This is a multi-part message in MIME format.' msgRoot.attach(msgAlternative) TempAddTo = paramMap["to"] if paramMap.has_key("text"): msgText = MIMEText(paramMap["text"], 'plain', 'utf-8') msgAlternative.attach(msgText) if paramMap.has_key("html"): msgText = MIMEText(paramMap["html"], 'html', 'utf-8') msgAlternative.attach(msgText) if paramMap.has_key("image"): fp = open(paramMap["image"], 'rb') msgImage = MIMEImage(fp.read()) fp.close() msgImage.add_header('Content-ID', '<image>' ) msgRoot.attach(msgImage) if paramMap.has_key("cc"): TempAddTo = paramMap["to"] + "," + paramMap["cc"] if TempAddTo.find(",") != -1: FinallyAdd = TempAddTo.split(",") else: FinallyAdd = TempAddTo #构造附件 fileName = "tastegameapp-log-"+time.strftime('%Y-%m-%d', time.localtime())+".txt" basename = os.path.basename(fileName) if os.path.exists(fileName): #数据文件存在 data = open(fileName, 'rb') att = MIMEText(data.read(), 'base64', 'utf8') att["Content-Type"] = 'application/octet-stream' att["Content-Disposition"] = 'attachment; filename="%s"' % basename msgRoot.attach(att) smtp.sendmail(paramMap["from"], FinallyAdd, msgRoot.as_string()) smtp.quit() return True def process(): global mailDict initMailConf() sendMail(mailDict) if __name__ == "__main__": process()
本文章为原创,引用请保留链接 http://ccimage.cn/2014-11/ios-dev-dailybuild-ipa.html
发表评论