美文网首页
Python的iOS自动化打包实例代码

Python的iOS自动化打包实例代码

作者: kakaLP | 来源:发表于2019-07-14 18:21 被阅读0次

        这段时间刚刚学习了一段时间的Python,加上自己是做iOS开发的,就想着用Python来做一个自动化打包,可以自动完成打包,上传到蒲公英,并且发送邮箱给测试人员,一是可以减少打包功夫,二来可以练练手,结合自己的工作来输出一点东西.废话不多说,直接上代码...


原理:就是使用xcodebuild来控制Xcode进行一系列的操作,从而完成打包的操作.

思路:找到对应的项目->clean项目->archive项目->export IPA->上传蒲公英->发送邮件->收工。

运行环境:Python, Xcode 这些需要大家直接去搭建好环境...

准备工作:下载安装pycharm(这只是我开发Python的工具而已,大家可以根据自己喜欢的来选择)->注册并认证蒲公英(不认证的话,是不能上传的)

->邮箱开启POP3/SMTP服务(我使用的是QQ邮箱),记录下16位授权码->一个ExportOptions.plist文件, 这个下面会解释为什么需要还有怎么生成!->

一份iOS项目代码→_→


完整代码

#参考文章https://juejin.im/post/5bed3657518825604e0e4289
#引入requests会报错https://blog.csdn.net/dongdong9223/article/details/81517182
import os
import webbrowser
import subprocess
import time
import smtplib
import requests

from email.mime.text import MIMEText
from email import encoders
from email.header import Header
from email.utils import parseaddr, formataddr

# 项目名称
project_name = 'JDReader'

# 项目路径
archive_workspace_path = "/Users/liping5/Desktop/JDReader"

#输出的文件夹
export_directory = "archive"

#蒲公英的APP地址
ipa_download_url = "https://www.pgyer.com/5PJl"

#蒲公英账号USER_KEY,
USER_KEY = '0ee08c7c0f56e0e3888a68892f41a745'

#蒲公英账号API_KEY
API_KEY = '0e4505a4b02ae0e26c615dc5173be43c'


# 发送人的地址
#from_address = '1169440180@qq.com'
from_address = '774428436@qq.com'

# 邮箱密码换成他提供的16位授权码,qq邮箱获取方法:https://jingyan.baidu.com/article/fedf0737af2b4035ac8977ea.html
#password = 'lclhontgpudyigih'
password = 'axpdicnmogmcbbeg'

# 收件人地址,可以是多个的
to_address = '1169440180@qq.com;liping5@jd.com;zhangxiliang@jd.com;mengzhaohe@jd.com;wuge@jd.com'

# 因为我是使用QQ邮箱..
smtp_server = 'smtp.qq.com'



class AutoArchive(object):
    """自动打包并上传到蒲公英,发邮件通知"""

    def __init__(self):
        pass

    def clean(self):
        print("\n\n===========开始clean操作===========")
        start = time.time()
        clean_command = 'xcodebuild clean -workspace %s/%s.xcworkspace -scheme %s -configuration Release' % (
            archive_workspace_path, project_name, project_name)
        clean_command_run = subprocess.Popen(clean_command, shell=True)
        clean_command_run.wait()
        end = time.time()
        # Code码
        clean_result_code = clean_command_run.returncode
        if clean_result_code != 0:
            print("=======clean失败,用时:%.2f秒=======" % (end - start))
        else:
            print("=======clean成功,用时:%.2f秒=======" % (end - start))
            self.archive()


    def archive(self):
        print("\n\n===========开始archive操作===========")

        # 删除之前的文件
        subprocess.call(['rm', '-rf', '%s/%s' % (archive_workspace_path, export_directory)])
        time.sleep(1)
        # 创建文件夹存放打包文件
        subprocess.call(['mkdir', '-p', '%s/%s' % (archive_workspace_path, export_directory)])
        time.sleep(1)

        start = time.time()
        archive_command = 'xcodebuild archive -workspace %s/%s.xcworkspace -scheme %s -configuration Release -archivePath %s/%s' % (
            archive_workspace_path, project_name, project_name, archive_workspace_path, export_directory)
        archive_command_run = subprocess.Popen(archive_command, shell=True)
        archive_command_run.wait()
        end = time.time()
        # Code码
        archive_result_code = archive_command_run.returncode
        if archive_result_code != 0:
            print("=======archive失败,用时:%.2f秒=======" % (end - start))
        else:
            print("=======archive成功,用时:%.2f秒=======" % (end - start))
            # 导出IPA
            self.export()


    def export(self):
        print("\n\n===========开始export操作===========")
        print("\n\n==========请你耐心等待一会~===========")
        start = time.time()
        # export_command = 'xcodebuild -exportArchive -archivePath /Users/liangk/Desktop/TestArchive/myArchivePath.xcarchive -exportPath /Users/liangk/Desktop/TestArchive/out -exportOptionsPlist /Users/liangk/Desktop/TestArchive/ExportOptions.plist'
        export_command = 'xcodebuild -exportArchive -archivePath %s/%s.xcarchive -exportPath %s/%s -exportOptionsPlist %s/ExportOptions.plist' % (
            archive_workspace_path, export_directory, archive_workspace_path, export_directory, archive_workspace_path)
        export_command_run = subprocess.Popen(export_command, shell=True)
        export_command_run.wait()
        end = time.time()
        # Code码
        export_result_code = export_command_run.returncode
        if export_result_code != 0:
            print("=======导出IPA失败,用时:%.2f秒=======" % (end - start))
        else:
            print("=======导出IPA成功,用时:%.2f秒=======" % (end - start))
            # 删除archive.xcarchive文件
            subprocess.call(['rm', '-rf', '%s/%s.xcarchive' % (archive_workspace_path, export_directory)])
            self.upload('%s/%s/%s.ipa' % (archive_workspace_path, export_directory, project_name))


    def upload(self, ipa_path):
        print("\n\n===========开始上传蒲公英操作===========")
        if ipa_path:
            # https://www.pgyer.com/doc/api 具体参数大家可以进去里面查看,
            url = 'http://www.pgyer.com/apiv1/app/upload'
            data = {
                'uKey': USER_KEY,
                '_api_key': API_KEY,
                'installType': '1',
                'updateDescription': description
            }
            files = {'file': open(ipa_path, 'rb')}
            r = requests.post(url, data=data, files=files)
            if r.status_code == 200:
                # 是否需要打开浏览器
                # self.open_browser(self)
                self.send_email()
        else:
            print("\n\n===========没有找到对应的ipa===========")
        return

    @staticmethod
    def open_browser(self):
        webbrowser.open(ipa_download_url, new=1, autoraise=True)

    @staticmethod
    def _format_address(self, s):
        name, address = parseaddr(s)
        return formataddr((Header(name, 'utf-8').encode(), address))


    def send_email(self):
        # https://www.pgyer.com/XXX app地址
        # 只是单纯的发了一个文本邮箱,具体的发附件和图片大家可以自己去补充
        msg = MIMEText('<html><body><h1>Hello</h1>' +
                   '<p>╮(╯_╰)╭<a href='+ipa_download_url+'>京东读书版本已更新,请下载测试</a>╮(╯_╰)╭</p>' +
                   '<p>蒲公英的更新会有延迟,具体版本时间以邮件时间为准</p>' +
                   '</body></html>', 'html', 'utf-8')
        msg['From'] = self._format_address(self, 'iOS开发团队 <%s>' % from_address)
        msg['Subject'] = Header('来自iOS开发团队的问候……', 'utf-8').encode()
        server = smtplib.SMTP(smtp_server, 25)  # SMTP协议默认端口是25
        server.set_debuglevel(1)
        server.login(from_address, password)
        server.sendmail(from_address, to_address.split(';'), msg.as_string())
        server.quit()
        print("===========邮件发送成功===========")


if __name__ == '__main__':
    description = input("请输入内容:")
    archive = AutoArchive()
    archive.clean()


关于ExportOptions.plist文件:因为 Xcode 9+ 默认不允许访问钥匙串的内容,必须要设置 allowProvisioningUpdates 才会允许,Python的Xcode插件目前无法支持此项完成打包流程。

解决步骤如下:

1、手动Xcode10打包,导出ExportOptions.plist文件;

2、编辑ExportOptions.plist文件,配置 provisioningProfiles 对应填入Bundle identifier及证书关联配置文件(打包时自动匹配或手动填入证书,provisioningProfiles需配置的必填信息可自动生成);

3、提供ExportOptions.plist文件路径供Python脚本调用(详请参看Python脚本代码)。


<?xmlversion="1.0"encoding="UTF-8"?>

http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plistversion="1.0">

<dict>

<key>compileBitcode</key>//是否编译bitcode

<true/>

<key>method</key>

<string>ad-hoc</string>/

<key>provisioningProfiles</key>

<dict>

<key>文件bundle id</key>

<string>Adhoc_ID</string>

</dict>

<key>signingCertificate</key>//证书签名

<string>这里填证书签名</string>

<key>signingStyle</key>

<string>manual</string>

<key>stripSwiftSymbols</key>

<true/>

<key>teamID</key>

<string>AANCCUK4M3</string>//TeamID

<key>thinning</key>

<string><none></string>

</dict>

</plist>


4、分析 xcodebuild archive -workspace XXX.xcworkspace -scheme XXX -configuration

Release -archivePath XXX CONFIGURATION_BUILD_DIR ./dir

ODE_SIGN_IDENTITY=证书 PROVISIONING_PROFILE=描述文件UUID

总结:以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

相关文章

网友评论

      本文标题:Python的iOS自动化打包实例代码

      本文链接:https://www.haomeiwen.com/subject/nzrokctx.html