iOS Fastlane --自动化打包上传到蒲公英、fir

参考: iOS使用fastlane实现自动化打包

1. 安装 homebrew

/bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"

  • 查看homebrew版本 brew -v
  • 更新 brew update
  • 本地软件库列表 brew ls

2. 检查 ruby版本,以及是否安装 Xcode 命令行工具

ruby -v 查看是否安装ruby

xcode-select --install 安装Xcode工具

3. 安装 fastlane

sudo gem install fastlane

之后 cd 到项目根目录中
fastlane init 之后会出现如下图的4个选项:

image.png

  • 1)自动截取APP的屏幕
  • 2)发布bate版用于TestFlight
  • 3)发布到appStore
  • 4)自定义任务

肯定是选择4,选择完成后项目目录中多出了这些文件


image.png

4. 文件配置

  • 配置 Appfile (这里填app的bundleId)
  app_identifier("[[xxx]]") # The bundle identifier of your app
  • 配置 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



################## READ  FIRST ##################

######## 使用方法1 自定义version和build #########
###### fastlane iosDebug version:1.0.1  build:1 ######

######## 使用方法2 不写version和build 这时build会根据之前的build+1 #########
###### fastlane iosDebug  ######

###如果需要上传到蒲公英,请运行前先安装插件安装蒲公英的fastlane add_plugin pgyer ###


default_platform(:iOS)   # 设置默认的平台为iOS

############# 需要根据项目自定义设置 ############
APP_NAME = "AiDouVideo"             #输出包时app的名字
APP_SCHEME = "AiDouVideo"   #这个app打开manage schemes下选中的名称
APP_IPA_OUTPUT_DIRECTORY = "/Users/zhousong/Desktop/IPA"    # 打包所保存的文件目录,可以不设置
# 配置蒲公英的apiKey 和 userKey 需要设置 
APP_PGYER_API_KEY = "xxx"
APP_PGYER_USER_KEY = "xxx"
# 配置fir的token
APP_FIR_API_TOKEN = "xx"


######## 不用设置的 #####################
APP_XCODEPROJ = "#{APP_NAME}.xcodeproj"      # app的xcodeproj
APP_WORKSPACE = "#{APP_NAME}.xcworkspace"    # app的xcworkspace
APP_IPA_TIME = Time.now.strftime("%Y-%m-%d_%H:%M")  # 打包的时间
# APP_INFO_PLIST_PATH = './AiDouVideo/AiDouVideo-Info.plist'
APP_ENV_PREFIX = ""   # 打包完成后的包文件名字的前缀 区别release和debug



# 版本 build number++
def prepare_version(options)

    #增加version版本号
    if options[:version]
      increment_version_number(
        version_number: options[:version],
        xcodeproj: "#{APP_XCODEPROJ}",
      )
    else
      # 可以不设置
    end


    #增加build号  只能是整数和浮点数
    if options[:build]
      increment_build_number(
        build_number: options[:build],
        xcodeproj: "#{APP_XCODEPROJ}",
      )
    else
      last_build = get_build_number(xcodeproj: "#{APP_XCODEPROJ}")
      now_build = last_build.to_i + 1
      increment_build_number(
        build_number: now_build,
        xcodeproj: "#{APP_XCODEPROJ}",
      )
    end
end


#统一的打包方法
def generate_ipa(exportMethod,configuration,options)

    # 设置version和build
    prepare_version(options)  
    # 得到最新的version
    app_version = get_version_number(target: "#{APP_SCHEME}")     
    # 最新的build
    app_build = get_build_number(xcodeproj: "#{APP_XCODEPROJ}")         
    # app包名
    app_ipa_name = "#{APP_NAME}_" "#{APP_ENV_PREFIX}" + "#{APP_IPA_TIME}_" + "#{app_version}_" + "#{app_build}"

    #打包
    gym(
      clean: true,       # 打包前clean项目
      silent: true,      # 隐藏没有必要的信息
      scheme: "#{APP_SCHEME}",
      workspace: "#{APP_WORKSPACE}", 
      configuration: "#{configuration}",  # 环境
      export_method: "#{exportMethod}",   # app-store、ad-hoc、development、enterprise
      output_directory: "#{APP_IPA_OUTPUT_DIRECTORY}", #ipa的存放目录
      output_name: "#{app_ipa_name}", # 输出ipa的文件名
      # 生成的ipa文件是否包含symbols,这个文件是内存标记文件,用来定位错误信息的,有了这个安装包大小会变大
      include_symbols: true,
      # 生成的ipa文件是否包含bitcode,在本身项目中也可以配置
      include_bitcode: false,
      # keychain授权 Xcode9不允许访问钥匙串密码,所以我们需要手动开权限
      export_xcargs: "-allowProvisioningUpdates"
      )

end

platform :iOS do
  # before_all就是先于所有lane执行的任务
  before_all do
       # 根据安装路径指定要使用的Xcode 
       xcode_select "/Applications/Xcode.app"
       # 超时失败,默认的timeout是10秒
       ENV["FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT"] = "120"
       # Appfile设置了可以忽略下面的证书设置
       # 这个action很重要cert就是下载和安装匹配的Provision Profile文件,不用你去管那些证书不匹配的事情了
       # cert(
          # Appfile设置了这边就可以不用了
          # username: "xxx@xx.com",
          # team_id: "xxxxxxx",
          # output_path:"#{APP_CERT_OUTPUT_DIRECTORY}"
        # )

       #这一步就是签名了
       # sigh(
         # Appfile设置了这边就可以不用了 
         # app_identifier: ENV["APP_IDENTIFIER"],
         # team_id: ENV['TEAM_ID'],

         # 更新开发证书而不是生产证书
         # development: ???  
         # 因为是根据BundleID下载,导致adhoc和appstore会优先appstore,导致最后导出报错,如果是adhoc包请设置为true
         # adhoc: true, 
         # 设置所生成描述文件的名称,必须包含文件类型后缀.mobileprovision 可以不设置
         # filename: "MyTest.mobileprovision",

        #  force:true,
        #  provisioning_name: 'MyTest AppStore',
        #  ignore_profiles_with_different_name: true,
        #  output_path: "build/sign",
        # )
  end

  # lane  自定义的任务

#debug包 上传到蒲公英平台
#option类似一个字典 option[:version] 取其中value值version
lane :iosDebug_pgy do |options|
  APP_ENV_PREFIX = "ad-hoc"
  generate_ipa("ad-hoc","Release",options)

  #上传至蒲公英 在这之前请安装插件 fastlane add_plugin pgyer
  if APP_PGYER_API_KEY.length > 0 && APP_PGYER_USER_KEY.length > 0
    pgyer(
      api_key: "#{APP_PGYER_API_KEY}",
      user_key: "#{APP_PGYER_USER_KEY}",
    )
  notification(title: "发布成功!", message: "已成功上传到蒲公英平台, 赶快联系测试人员开始测试吧!", open: "https://www.pgyer.com/")
  end
end
 #debug包 上传到fir
  lane :iosRelease_fir do |options|
    APP_ENV_PREFIX = "ad-hoc"
    generate_ipa("ad-hoc","Release",options)

    #上传至fir 在这之前请安装插件 fastlane add_plugin firim
    if APP_FIR_API_TOKEN.length > 0 
      firim(
        firim_api_token: "#{APP_FIR_API_TOKEN}", 
      )
    notification(title: "发布成功!", message: "已成功上传到fir平台, 赶快联系测试人员开始测试吧!", open: "https://fir.im/apps")
    end
  end
# release发布包
lane :  do |options|
  APP_ENV_PREFIX = "appstore_"
  generate_ipa("app-store","Release",options)
  # 上传至app-store
  deliver(
    force: true,              #是否跳过HTML验证报告,默认false
    skip_metadata: true,      #是否跳过上传metadata,默认false
    skip_screenshots: true    #是否跳过上传屏幕截图,默认false
   )
   notification(title: "发布成功!", message: "已成功发布到appstore, 请查验!", open: "https://itunesconnect.apple.com")
end

# testFlight包
lane :iosTestFlight do |options|
  APP_ENV_PREFIX = "adhoc_"
  generate_ipa("ad-hoc","Release",options)
  # 管理TestFlight的测试用户,上传二进制文件
  pilot
  notification(title: "发布成功!", message: "已成功发布到appstore, 请查验!", open: "https://itunesconnect.apple.com")
end



  # 当lane执行完成之后进行哪些操作
  after_all do |lane|
  #发送一个桌面通知
  #notification(title: "execute success", subtitle: "执行成功!", message: "lane已经执行成功了")
  end

  error do |lane, exception|
  puts("#{exception.message}")
  notification(title: "执行#{lane}发生异常!", message: "发生异常, 详情请查看控制台!")
  end

end

注意: APP_PGYER_API_KEYAPP_PGYER_USER_KEYAPP_FIR_API_TOKEN分别要去蒲公英和fir的官网上申请的。
在进行打包前我们还要安装蒲公英和fir的插件
fastlane add_plugin pgyerfastlane add_plugin firimfastlane add_plugin fir_cli

6. 执行任务

Fastfile 配置文件中我们可以看到有四个任务,分别是:iosDebug_pgyiosDebug_firiosTestFlightiosRelease ,每个任务里都有不同的配置,如果想要自行配置可在文件中进行修改,我们只需要在项目根目录下执行 fastline iosDebug_pgyfastlane iosDebug_fir..等对应的任务名即可。这样就成功了

image.png

7. 遇到的问题

当我在打Release包的时候,遇到了下面这些错误

Couldn't find specified configuration 'Release'
[22:29:19]: ▸ ❌  /Users/zhousong/Desktop/DOEX/交易所/AiDouVideo/ThirdPartyFramework/WSocketManager/WebSocketManager.h:3:9: 'SocketRocket/SocketRocket.h' file not found
[22:29:19]: ▸ #import <SocketRocket/SocketRocket.h>
[22:29:19]: ▸         ^
[22:29:19]: ▸ ❌  error: failed to emit precompiled header '/Users/zhousong/Library/Developer/Xcode/DerivedData/AiDouVideo-bxifstjvaotselgzfgzbhliuqvfq/Build/Intermediates.noindex/ArchiveIntermediates/AiDouVideo/PrecompiledHeaders/AiDouVideo-Bridging-Header-swift_1OUSDN8PU827W-clang_1WFO3U4XD3B2D.pch' for bridging header /Users/zhousong/Desktop/DOEX/交易所/AiDouVideo/ConfigurationFiles/Tools/Tool/Iban/AiDouVideo-Bridging-Header.h
[22:29:20]: ▸ ** ARCHIVE FAILED **
[22:29:20]: ▸ The following build commands failed:
[22:29:20]: ▸   PrecompileSwiftBridgingHeader normal arm64
[22:29:20]: ▸   CompileSwiftSources normal arm64 com.apple.xcode.tools.swift.compiler
[22:29:20]: ▸ (2 failures)

看到这些报错我以为是文件导入方式不对,但改了之后也是报错,于是我仔细看了第一句错误Couldn't find specified configuration 'Release',我点开了Edit Shceme,然后我发现Build Configuration 选项中只有Debug没有Release ,在下面添加了Release 模式,重新运行即可打包成功。

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,362评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,330评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,247评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,560评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,580评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,569评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,929评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,587评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,840评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,596评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,678评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,366评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,945评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,929评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,165评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,271评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,403评论 2 342