美文网首页PHP自动化集成测试脚本安装
iOS App自动化打包发布(Jenkins + Fastlan

iOS App自动化打包发布(Jenkins + Fastlan

作者: 没梦想的咸鱼2 | 来源:发表于2017-05-02 22:42 被阅读3421次

    ============2018.5.15 updte=================
    xcode 9 需要在gym action加入 export_xcargs: "-allowProvisioningUpdates",
    参考: https://www.jianshu.com/p/e0c51ab314f7
    =========================================

    目标

    搭建一个自动化打包发布的平台。无论是App Store的发布,是开发期间持续化集成,都需要一个自动化的方案,代替人工来处理那些繁琐的打包发布流程。
    本文采用的方案:jenkins + fastlane + svn + firim

    Jenkins

    关于搭建jenkins 看这篇文集就可以了 -> 手把手教你利用Jenkins持续集成iOS项目
    只需要按步骤完成安装、新建job、源码管理就可以了,构建环境暂时不需要设置。

    • 不要使用Xcode构建,因为在导出ipa的时候,jenkins会使用到PackageApplication,这个玩意在xcode 8.3已经被删除了 (当然你可以从旧版本的Xcode拷贝一个过来
    • 多安装一个插件 Message Injector Plugin 用来配置环境变量

    FastLane

    fastlane 就是一个自动化发布的命令行工具-> 小团队的自动化发布-Fastlane带来的全自动化发布 或者 fastlane github && fastlane doc

    安装命令 跟上述文章略有不同

        [sudo] gem install fastlane -n /usr/local/bin
    

    加上 -n /usr/local/bin是因为Mac OS X 10.11 已经禁止修改/usr/bin目录了,那就换个目录安装

    Firim

        [sudo] gem install firim -n /usr/local/bin
    

    还需要到fir.im注册个账号,上传ipa需要一个token。

    脚本

    在工程目录下 完成 fastlane init之后,会生成fastlane文件夹,里面有三个文件需要修改

    • Fastfile => 用来定义所有的lane任务Fastfile帮助
    • Appfile => 是用来存储一些公共信息的,比如app_identifier,apple_id,team_id,itc_team_id等。Appfile帮助
    • Deliverfile => deliver的配置文件Deliverfile帮助

    安装帮助文档应该可以轻松完成脚本编写,然而你的工程如果有多个Tareget,你可能还需要在fastlane目录下定义一个env配置文件。

        touch .env.TargetName
    

    .env.TargetName文件内容:

        APP_IDENTIFIER = "com.xxx.xxxxx"
    
        #苹果开发者账号
        APPLE_ID = "xxxxxxxxxx@xxx.cn"
        FASTLANE_PASSWORD = "xxxxxxx"
        
        TEAM_ID = "xxxxxxxxxx"
    
        SCHEME_NAME = "TargetName"
    
        #App 元数据及截图存放路径
        METADATA_PATH = "./metadata/XXXXXXXX"
        SCREENSHOTS_PATH = "./screenshots/XXXXXXXXX"
    
        #App 元数据及截图下载时 直接覆盖 不询问
        DELIER_FORCE_OVERWRITE= true
    
        #版本号 如果不使用,就按照Xcode配置
        #APP_VERSION = 1.0.1
    
        #证书
        CODESIGNING_IDENTITY_TO_FIRIM = "iPhone Developer: XXXXX (XXXXXXX)"
        CODESIGNING_IDENTITY_TO_APPSTORE = "iPhone Distribution: XXXXX (XXXXXXXXX)"
    

    Appfile文件:ENV[‘xxxx’] 就是读取.env文件里面的配置

        app_identifier ENV['APP_IDENTIFIER'] # The bundle identifier of your app
        apple_id ENV['APPLE_ID'] # Your Apple email address
    
        team_id ENV['TEAM_ID'] # Developer Portal Team ID
    
        # you can even provide different app identifiers, Apple IDs and team names per lane:
        # More information: https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Appfile.md
    

    Deliverfile文件:如果你想使用deliver上传元数据截图以及完成提交,就需要根据帮助文档完善后续的参数

        ###################### More Options ######################
        # If you want to have even more control, check out the documentation
        # https://github.com/fastlane/fastlane/blob/master/deliver/Deliverfile.md
    
    
        ###################### Automatically generated ######################
        # Feel free to remove the following line if you use fastlane (which you should)
    
        # The bundle identifier of your app
        app_identifier ENV['APP_IDENTIFIER'] 
    
        # your Apple ID user
        username ENV['APPLE_ID'] 
    
        # 元数据的路径
        metadata_path ENV['METADATA_PATH']
        screenshots_path ENV['SCREENSHOTS_PATH']
    
        #App store 中待发布的 App 版本,若每个 target 的版本号不同,可以通过.env 文件来分别定义
        app_version ENV['APP_VERSION']
    
        #下载 metadata 及 screenshots 时直接覆盖,不询问
        force true
    

    可以使用以下命令 从iTC上下载 元数据和截图

        fastlane deliver download_metadata -a  com.xxx.xxxxx -m ./metadata/XXXXXXXX -u  xxxxxxxxxx@xxx.cn
        fastlane deliver download_screenshots -a com.xxx.xxxxx -m ./screenshots/XXXXXXXX -u  xxxxxxxxxx@xxx.cn
    

    接下来就是重头戏 fastfile文件:

       fastlane_version "2.28.3"
    
       default_platform :ios
    
       platform :ios do
    
       desc "Submit one more new Beta Build to Fir.im"
       lane :to_firim_multi do | options |
          schemes = options[:'schemes']
          schemes = schemes[1..-2]
          schemes = schemes.split(",")
          schemes.each do |i| 
            puts "do fastlane to_firim --env " + i.to_str
            sh "fastlane to_firim --env " + i.to_str
         end
       end
    
       desc "Submit one more new Release Build to AppStore"
       lane :to_appStore_multi do | options |
          schemes = options[:'schemes']
          schemes = schemes[1..-2]
          schemes = schemes.split(",")
          schemes.each do |i| 
             puts "do fastlane to_appStore --env " + i.to_str
             sh "fastlane to_appStore --env " + i.to_str
          end
       end
    
       desc "Submit a new Beta Build to Fir.im"
       lane :to_firim do | options |
       buildScheme = ENV['SCHEME_NAME']#options[:buildScheme]
       # 如果你用 pod install
       # cocoapods
       # 以下两个action来自fastlane-plugin-versioning,
       # 第一个递增 Build,第二个设定Version。
       # 如果你有多个target,就必须指定target的值,否则它会直接找找到的第一个plist修改
       # 在这里我建议每一个打的包的Build都要不一样,这样crash了拿到日志,可以对应到ipa上
       increment_build_number_in_plist(target: buildScheme)
       # increment_version_number_in_plist(
       #   target: buildScheme,
       #   version_number: ENV['APP_VERSION']
       #   )
    
       # gym用来编译ipa
       outputDir = "~/firim/ipa/#{Time.now.strftime('%y%m%d')}"
       outputName = "#{buildScheme}-#{Time.now.strftime("%Y-%m-%d %H:%M:%S")}"
       gym(
          scheme: buildScheme,
          workspace: "xxxxxxx.xcworkspace",
          configuration: "Release",
          output_directory: outputDir,
          output_name: outputName,
          include_bitcode: false,
          include_symbols: true,
          codesigning_identity: ENV["CODESIGNING_IDENTITY_TO_FIRIM"],
          silent: true,
          export_options: {
            method: "development", 
            thinning: "<none>"
          }
      )
       # 上传ipa到fir.im服务器,在fir.im获取firim_api_token
       firim(firim_api_token: "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
       end
    
        desc "Submit a new Release Build to AppStore"
        lane :to_appStore do | options |
        buildScheme = ENV['SCHEME_NAME']#options[:buildScheme]
        # 如果你用 pod install
        # cocoapods
    
        # 以下两个action来自fastlane-plugin-versioning,
        # 第一个递增 Build,第二个设定Version。
        # 如果你有多个target,就必须指定target的值,否则它会直接找找到的第一个plist修改
        # 在这里我建议每一个打的包的Build都要不一样,这样crash了拿到日志,可以对应到ipa上
        increment_build_number_in_plist(target: buildScheme)
        # increment_version_number_in_plist(
        #   target: buildScheme,
        #   version_number: ENV['APP_VERSION']
        #   )
        # gym用来编译ipa
        outputDir = "~/AppStore/ipa/#{Time.now.strftime('%y%m%d')}"
        outputName = "#{buildScheme}-#{Time.now.strftime("%Y-%m-%d %H:%M:%S")}"
        gym(
          scheme: buildScheme,
          workspace: "xxxxxxx.xcworkspace",
          configuration: "Distribution",
          output_directory: outputDir,
          output_name: outputName,
          include_bitcode: false,
          include_symbols: true,
          codesigning_identity: ENV["CODESIGNING_IDENTITY_TO_APPSTORE"],
          silent: true,
          export_options: {
            method: "app-store", 
            thinning: "<none>"
          }
          )
         # 上传appstore 只传ipa包
        deliver(
          skip_screenshots: true,
          skip_metadata: true,
          force: true
         )
         end
    

    完成配置文件的编写就可以使用脚本来自动打包发布

        #完成打包后,自动上传firim,用于开发测试 
        fastlane to_frim_multi schemes:[Target1,Target2,Target3,...] 
    
        #完成打包后,自动上传AppStore,用于正式发布 
        fastlane to_appStore_multi schemes:[Target1,Target2,Target3,...] 
    

    证书 profile之类的配置都在Xcode中完成,要确保使用Xcode可以正常编译签名

    最后一步

    在jenkins新增两个构建步骤

    屏幕快照

    第一步导入一个环境变量
    第二步就是执行fastlane命令
    最后要做的就是提交到svn,执行jenkins的job就可以自动完成打包发布啦
    总的来说,程序员的懒,一定程度上推动了技术的进步~

    参考资料

    1. 24. 自动化工具Fastlane笔记一: 安装, 打包,上传(testFlight,app store)
    2. 使用 fastlane 实现对 iOS Multi-Target 的一键打包部署

    相关文章

      网友评论

      • 草原烈鹰:你好,有没有遇到:上传钥匙串的时候,选取不到,隐藏文件夹“资源库”里面的login.keychain的情况?
        没梦想的咸鱼2:@睿画智清 @睿画智清 不太记得了,我当时好像没用上传钥匙串,用的是开发者账号在打包机器上登陆下载证书、导入p12等等
      • ChenJZ:你好,每次要上传到appkestore上,都要在jinkens手动创建一个项目吗?
        没梦想的咸鱼2:不必啊,创建好了,可以重复使用
        jenkins只是一个环境,主要完成源码更新和执行脚本
      • HZJ军:你好 我最近在研究Jenkins + Fastlane 自动打包 但是我在设置FASTLANE_PASSWORD的时候 发现现在登录密码需要两步验证 请问你是怎么解决的吗
        HZJ军:我现在单独使用Fastlane 完全没有问题 但是加到Jenkins上面就会出上面的错
        HZJ军:@施孝达 我通过FASTLANE_SESSION已经解决了验证问题, 请问你有遇到提示没有默认keychain的问题吗?
        security: SecPolicySetValue: One or more parameters passed to a function were not valid.
        security: cert import failed: A default keychain could not be found.
        security: problem decoding
        没梦想的咸鱼2:貌似没有遇到过,终端上遇到两步验证吗?
        可以尝试下在打包的机器的safari正常登录一次,完成两步验证

      本文标题:iOS App自动化打包发布(Jenkins + Fastlan

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