美文网首页
自动化打包实战 — Fastlane

自动化打包实战 — Fastlane

作者: 地上的 | 来源:发表于2018-10-18 15:32 被阅读0次

    刚到一个新公司,项目框架处于初步阶段,于是鄙人准备做一些事情,把这个项目该完善的模块尽量都一一完善。
    第一步便是从自动化打包开始,自动化打包属于一个多人协作开发、测试流程中不可或缺的东西,不仅节约开发者不必要的打包时间,也可免除来自打包过程中的意外(证书配置错误、接口问题等低级错误)。实际来说,作为一个开发者应该有懒得去做重复耗时的事的心态,所以自动化打包、持续集成(CI)等应运而生。
    后面我也会写一篇Jenkins的集成实战。
    2018年11月12日更新,已完成:自动化打包实战 — Jenkins

    一、安装Fastlane

    使用命令行安装,有两种。
    1、使用 gem 安装:sudo gem install fastlane
    2、使用 homebrew 安装:brew cask install fastlane(需先安装homebrew,这个应该是开发者标配了吧...)
    我这里使用 gem 安装的是2.107.0版本(2018年10月17日最新)。

    二、开始使用Fastlane

    初始化Fastlane

    1、cd 到你的项目根目录
    2、执行fastlane init命令

    image.png
    3、这个时候会有4个选项可供选择,这里我选择的是3,会让你输入你的Apple ID和密码,输入完成会让你选择是否下载metadata之类的,输入Y同意即可。
    Fastlane目录结构
    在上面步骤初始化完毕之后,会在你的项目根目录下多出一个fastlane文件夹,文件夹下有以下文件: image.png

    其中metadata和screenshots分别对应App元数据和商店应用截图。

    Appfile主要存放App的apple_id team_id app_identifier等信息。 image.png Deliverfile中为发布的配置信息,一般情况用不到。

    Fastfile是我们最应该考虑的文件,里面的内容决定了我们执行什么操作。
    (懒人直接去复制粘贴文件内容吧☺)

    以下为FastFile示例文件,差不多满足基本需求
    # This file contains the fastlane.tools configuration
    # You can find the documentation at https://docs.fastlane.tools
    #
    # For a list of all available actions, check out
    #
    #     https://docs.fastlane.tools/actions
    #
    # For a list of all available plugins, check out
    #
    #     https://docs.fastlane.tools/plugins/available-plugins
    #
    
    # Uncomment the line if you want fastlane to automatically update itself
    # update_fastlane
    
    default_platform(:ios)
    
    platform :ios do
      ipapath = './fastlane/ipa/'
      scheme = '你的工程名称'
      bundleId = "工程的bundleId"
    
      desc "Push a new release build to the App Store"
    
    #打包
    #编译一个adhoc ipa包
      lane :build_adhoc_ipa do 
        #sync_code_signing(
         # type: 'adhoc',
          #readonly: true
          #)
        build_app(
          clean: true,
          configuration: "Release",
          export_method: "ad-hoc", 
          output_directory: ipapath,
          output_name: scheme + "_adhoc.ipa",
          export_options: {
            #指定描述文件
            provisioningProfiles: {
              bundleId => "iOSDistributionAdHoc(这是我的描述文件名称,你自己选你自己的)"
            }
          }
          )
      end
    
    #编译一个dev的包
      lane :build_development_ipa do
        #sync_code_signing(
          #type: development,
          #readonly: true
          #)
        build_app(
          clean: true,
          configuration: "debug",
          export_method: "development", 
          output_directory: ipapath,
          output_name: scheme + "_development.ipa",
          export_options: {
            #指定描述文件
            provisioningProfiles: {
              bundleId => "iOS_wildcard_development(这是我的描述文件名称,你自己选你自己的"
            }
          }
          )
      end
    
      #编译一个appstore的包
      lane :build_appstore_ipa do
        #sync_code_signing(
          #type: appstore,
          #readonly: true
          #)
        build_app(
          clean: true,
          configuration: "release",
          export_method: "app-store", 
          output_directory: ipapath,
          output_name: scheme + "_appstore.ipa",
          export_options: {
            #指定描述文件
            provisioningProfiles: {
              bundleId => "iOSDistribution20180930(这是我的描述文件名称,你自己选你自己的"
            }
          }
          )
      end
    
    
      #上传指定路径的包到蒲公英
      lane :uploadToPgyer do |op|
          #蒲公英取本地文件路径上传
          path = op[:path]
            pgyer(api_key: "你的蒲公英账号的appkey", user_key: "你的蒲公英账号的userkey", ipa: path, password:"想设置密码就加这个键值对", install_type:"2", update_description:"update by fastlane test(更新描述)")
      end
    
      #上传已存在的adhoc包到蒲公英
      lane :upload_exist_adhoc_ToPgyer do
        uploadToPgyer(path: ipapath + scheme + '_adhoc.ipa')
      end
    
    
      #编译一个adhoc 包并上传蒲公英
      lane :build_adhoc_uploadToPgyer do
        build_adhoc_ipa
        uploadToPgyer(path: ipapath + scheme + '_adhoc.ipa')
      end
    
    #编译一个beta包并上传TestFlight
    #upload_to_testflight
    
      #编译一个AppStore包并上传到ITC
      lane :build_appstroe_uploadToITC do
        build_appstore_ipa
        upload_to_app_store(
          ipa: ipapath + "/" + scheme + "_appstore.ipa"
          )
      end
    end
    
    注意点:

    这里我没有使用xcode的自动证书管理,因为如果使用自动管理会有坑,有时会自动选择错证书,需要去额外设置解决,既然麻烦那就直接手动管理好了。

    Fastlane的使用

    cd到项目根目录之后,执行命令fastlane action,这个action就是上面FastFile里面每个lane xxxxxxx doxxxxxxx,比如我想打一个adhoc的包,就执行fastlane build_adhoc_ipa即可。
    fastlane还有很多其他的操作,例如'fastlane actions'查看所有的操作。
    另外在FastFile中还有match等相关操作,match是一种全新的证书同步管理机制,例如

      lane :match_appstore do 
        match(type: "appstore", force_for_new_devices: true)
      end
    
      lane :match_adhoc do 
        match(type: "adhoc", force_for_new_devices: true)
      end  
    
      lane :match_development do 
        match(type: "development", force_for_new_devices: true)
      end
    

    这里就不展开讲了,有兴趣的可以去官网看看。

    最后贴一张Fastlane的整个信息图,开始你的挖坑之旅吧。 fastlanePDF.png

    如果有遇到问题报错之类的,一般错误信息后面都会带有GitHub的issue链接,可以进去看看,也可以在文章地下评论,我会及时回复。
    fastlane的集成使用相对比较简单,之后会再补上一篇Jenkins的集成。

    更新:--------应测试需求,新增自动打包结束后发送邮件通知他们-----------

    思路

    Fastlane目前好像还没有一键发邮件的功能,于是只能自己写脚本,然后通过Fastlane运行该脚本来达到发送邮件目的。
    首先我们需要登录自己的邮箱,然后再给对方发送邮件;登录自己的邮箱需要设置SMTP或者EXCHANGE服务(当然还有其他,这两个主流),于是开始撸Py脚本。

    SMTP服务的邮箱

    话不多说,直接先上脚本代码,这里以126邮箱为例(163、QQ等都一样)。

    #coding:utf-8
    import sys
    reload(sys)
    sys.setdefaultencoding('utf8')
    import smtplib
    from smtplib import SMTP
    from email.mime.text import MIMEText
    from email.header import Header
     
    #构造纯文本邮件内容
    msg = MIMEText('Fastlane自动打包成功\n\n下载地址:http://www.pgyer.com/xxxxxx  \n\n密码:xxxxxxx  \n\n使用iPhone扫描二维码即可下载\n\n\n\n有问题随时联系开发','plain','utf-8')
    msg['From'] = 'wodeyouxaing@126.com'
    msg['To'] = '测试组'
    subject = 'iOS自动打包成功'
    msg['Subject'] = Header(subject,'utf-8')
    
    #发送者邮箱
    sender = 'wodeyouxiang@126.com'
     
    #发送者的登陆用户名和密码
    user = 'wodeyouxiang@126.com'
    password = 'wodemima'#记住,这里不是你的登录密码,而是你在126邮箱那里设置中开通SMTP服务后,自己设置的授权码!!!(qq会自动生成一段授权码,126邮箱会让你自己设置一个)
     
    #发送者邮箱的SMTP服务器地址
    smtpserver = 'smtp.126.com'
     
    #接收者的邮箱地址
    receiver = ['wodeqq@qq.com']
     
    smtp = smtplib.SMTP() #实例化SMTP对象
    smtp.connect(smtpserver,25) #端口25
    smtp.login(user,password) #登陆smtp服务器
    smtp.sendmail(sender,receiver,msg.as_string())
    
    smtp.quit()
    
    

    以上脚本写好之后,直接先打开终端自己本地跑一遍,执行python xxxxx.py

    常见报错:

    1smtplib.SMTPDataError: (554, b'DT:SPM 163 smtp10,DsCowAA3h9_QbgZXI9_fCQ--.713S2 1460039376,please see http://mail.163.com/help/help_
    参照126官网的错误提示可知原因是:•554 DT:SPM 发送的邮件内容包含了未被许可的信息,或被系统识别为垃圾邮件。请检查是否有用户发送病毒或者垃圾邮件。
    翻译过来就是你的主题中不能包含test等字眼,另外msg['From'] = 'wodeyouxaing@126.com'这里面的值需要和你的sender = 'wodeyouxiang@126.com'保持一致,否则一样会报错554,参考链接:https://blog.csdn.net/wangming520liwei/article/details/53900269

    2、出现各种Timeout,此时要考虑
    (1)SMTP地址是否和你的邮箱对应好,比如'smtp.126.com'对应的是126邮箱,'smtp.qq.com'对应的是QQ邮箱等。
    (2)你的邮箱是否已经开启了SMTP服务。

    SMTP设置.png

    3、出现smtplib.SMTPAuthenticationError: (535, '5.7.3 Authentication unsuccessful'),说明账户密码不对,慢慢重试吧。

    Exchange服务的邮箱

    为什么还要玩Exchange邮箱呢?因为我司的工作邮箱不支持SMTP服务,不让用....那没办法,只能开撸Exchange服务,后来发现,利用exchangelib去发邮件简直不能太简单了。。。来吧,开干!
    先上exchangelib的官网:https://pypi.org/project/exchangelib/

    前提

    安装exchangelib,在终端中执行pip install exchangelib,有的人会出现找不到pip指令,pip是python的包管理工具,在Python2.7的安装包中,easy_install.py是默认安装的,而pip需要我们手动安装,
    那就先执行sudo easy_install pip安装上pip,后再执行前面的exchangelib的安装吧。
    在安装exchangelib的时候有的人会遇到报错:Could not install packages due to an EnvironmentError: [Errno 13] Permission denied: '/Library/Python/2.7/site-packages/lxml-4.2.5.dist-info' Consider using the --user option or check the permissions.
    原因可能是Python版本的问题,而不是sudo权限,所以用homebrew执行brew install python3之后,再安装pip,再安装exchangelib。
    这里涉及到如何把系统的python2.7换成默认使用你自己用brew安装的python3.7,参考链接:https://blog.csdn.net/NancyLiu0/article/details/81781809,同理,pip也需要软指向到/user/local/bin下,具体可Google。

    image.png
    使用exchangelib
    from exchangelib import DELEGATE, Account, Credentials, Message, Mailbox, HTMLBody
    
    def Email(to, subject, body):
        creds = Credentials(
            username='nidezhanghao',
            password='nidemima'
        )
        account = Account(
            primary_smtp_address='nideyouxaing@xxx.com',
            credentials=creds,
            autodiscover=True,
            access_type=DELEGATE
        )
        m = Message(
            account=account,
            subject=subject,
            body=HTMLBody(body),
            to_recipients = [Mailbox(email_address=to)]
        )
        m.send()
    
    Email("目的地邮箱@qq.com", "abc", "def")
    
    常见错误:

    1exchangelib.errors.AutoDiscoverFailed: All steps in the autodiscover protocol failed,这个是因为你本机的exchangelib版本和你的服务器exchangelib的版本不一致导致的,用pip search exchangelib查询本机的版本号,然后再去问问你们的IT支持吧,找他要服务器的版本相关信息。

    Fastlane配置自动发送邮件

    执行脚本成功之后,需要在Fastlane里面去做这个 自动执行脚本 操作,于是来到我们熟悉的Fastfile.
    1、把写好的py脚本文件copy到以下目录:你的项目/fastlane
    2、在Fastfile中添加以下代码块:

    # 发送邮件提醒下载测试
      lane :sendEmail_SMTPToTest do
        path =  Dir::pwd + '/sendEmailPY_SMTP.py'#这里是你的脚本文件名
        cmd = 'python ' + path 
        sh cmd
      end
    

    然后在之前写过的编译adhoc包并且发送蒲公英那个lane里面,加上这个新写的发送邮件的lane就大功告成啦!

    
      #编译一个adhoc 包并上传蒲公英 并且给测试人员发送邮件
      lane :build_adhoc_uploadToPgyer_SendEmail do
        build_adhoc_ipa
        uploadToPgyer(path: ipapath + scheme + '_adhoc.ipa')
        sendEmail_SMTPToTest
      end
    

    相关文章

      网友评论

          本文标题:自动化打包实战 — Fastlane

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