iOS自动化发布--Fastlane本地构建IPA并分发

此篇文章相关代码已经上传至GitHub,相关代码请移步build_ios_app

iOS自动化发布测试包到fir.im,以及自动打包上传AppStore并提交审核...

公司项目都是在Jenkins上部署的,打包分发一键完成,可有时候Jenkins出问题,这就不好玩了,要排查问题还是挺费劲的,各种问题(公司产品线比较多,各个产品使用的Xcode版本不一致,有的是自动签名,有的需要profile,打包成功但上传失败),总之,最后的结果都是failure

尽管测试已经掌握打包秘籍,不再需要麻烦开发,但鉴于这种失败failure情况下,测试人员,跑过来还是会打扰开发的,还有就是另一种情况,开发人员已经解决了这个(多个)问题之后,想立即让测试验证,这个时候,就需要在终端terminal敲上一段代码./fastlane/build_app.sh,喝口水,去趟卫生间,搞定~

废话不多说~

环境配置

官网安装有两种方式gem,brew

首先必须确认已经安装xcode命令行工具,如果没有,使用以下命令

xcode-select --install

接下来,就是安装fastlane,使用下面的命令

[sudo] gem install fastlane -NV

或者使用homebrew,个人推荐使用

brew cask install fastlane

设置fastlane,体验自动化打包上传App Store

在你的工程目录下,切记一定是和*.xcodeproj同级目录下,
ruby使用fastlane init
swift 使用fastlane init swift

接下来会让你选择需要的功能模板

1. 📸  Automate screenshots 自动截屏
2. 👩‍✈️  Automate beta distribution to TestFlight 自动分发beta至TestFlight
3. 🚀  Automate App Store distribution 自动上传IPA到App Store
4. 🛠  Manual setup - manually setup your project to automate your tasks 不使用模板,自己去写自动打包脚本

作者先使用第三个模板 ,接下来也是选择,就直接最后结果吧,完成后,如下面的文件结构


直接使用命令fastlane release,接下来会自动打包,如果项目工程配置没有问题,就成功了


ok~ 使用模板当然不能满足我的需求的

本文的重点

  • 对Xcode项目,编写一个脚本实现自动打包ipa文件
  • 上传到fir.im,以供测试人员下载安装
  • 上传itunesconnect提交审核

1. 准备工作

前面我们xcode-selectfastlane这两个工具都已经安装完成,接下来还需要安装fir-cli

gem install fir-cli

安装完成后,我们开始编写脚本,这里需要注意的是,本脚本是基于fastlanefir-cli,来完成任务的

fastlane 本身自带打包ipa、上传App Store提交审核、上传
fir-cli这个主要是将fastlane打包的测试ipa,上传到fir.im供测试下载安装

2. 脚本编写

这个fastlane文件夹是在执行fastlane init后自动生成的,作者在此基础上进行修改,其中build_app.shrepublish.shappstore.envcommon.envdev.env这几个文件是作者自己添加的

└── fastlane
    ├── Appfile           // Appfile用来存放app_identifier,apple_id和team_id
    ├── Deliverfile       // 配置应用在 ITC 中的各种信息,和 ICC 中的数据是一一对应的
    ├── Fastfile          // fastlane 所执行的任务lane文件(核心)
    ├── Gymfile           // fastlane 编译打包ipa的配置文件
    ├── README.md
    ├── appstore.env      // 上传至App Store的环境配置文件
    ├── build_app.sh      // 脚本执行命令 ./build_app.sh
    ├── common.env        // 通用环境配置文件
    ├── dev.env           // 编译测试版本ipa的环境配置文件
    ├── ipa_build         // ipa输出文件夹(自动生成)
            └──// 编译好的ipa文件
    ├── metadata          // 执行fastlane deliver init 后自动从itunseconnet上获取
            └──// 提交App Store审核的一些元数据信息,包含应用在 ITC 中的各种信息
    ├── report.xml
    ├── republish.sh      // 针对于build_app.sh上传fir.im失败情况,再次上传ipa至fir.im
    └── screenshots       // 执行fastlane deliver init 后自动从itunseconnet上获取
            └──// 提交App Store审核的app宣传截图数据

下面我们来说说这几个文件里面的内容
代码已经上传至GitHub,如果使用请移步build_ios_app,如果觉着对你帮助,那就顺手给个star吧😄

Appfile

Appfile用来存放app_identifier,apple_id和team_id,这个文件按照你的app信息配置好久没问题

app_identifier "com.xxx.xxx" # app的bundle identifier
apple_id "xxx@xxx.com" # 你的Apple ID
 
itc_team_id "XXXXXXXXXX" # iTunes Connect Team ID
team_id "XXXXXXXXXX" # Team ID
···

Fastfile

配置管理 lane任务

#默认使用平台是 ios,也就是说文件可以定义多个平台
default_platform(:ios)

platform :ios do
    before_all do
        # 设置代码签名:自动
        enable_automatic_code_signing
        # 跟新构建版本号
        increment_build_number(
            build_number: ENV["build_number"]
        )
    end

    desc "build a test App "
    lane :beta do
         # 调用 gym 打测试包
         gym(
            configuration:"Debug",
            export_method:"development"
         )
    end

    desc "build a release App  "
    lane :release do

     # 调用 gym 打发布包
     gym(
        configuration:"Release",
        export_method:"app-store"
        )

     # 上传至 iTunes Connect
     deliver(
        #注意:submit_for_review这个true是提交审核,false不提交
        # skip_binary_upload: true,
        submit_for_review: true,
        )
    end
    
    after_all do |lane|
    end

    error do |lane, exception|
    end
end

Gymfile

Gymfile 配置打包ipa信息,详细更多参数列表参照gym/parameters

scheme("xxx")
sdk("iphoneos")  
output_name("xxx.ipa") 
output_directory("./fastlane/ipa_build")
clean(true) 
include_bitcode(false) 
include_symbols(true) 
export_xcargs("allowProvisioningUpdates") 

Deliver

Deliverfile 配置上传ITC信息,上传下载元数据信息,上传二进制ipa以及提交审核,详细更多参照deliver/parameters

Deliver可以完全管理与iTC的交互。其中包括:

上传和下载多语言截图
上传和下载多语言元数据
上传二进制文件

PS:

  • 如果Deliverfile文件,screenshotsmetadata目录没被创建,可以运行deliver init来创建;
  • 如果你不想修改metadata某些项的信息,直接把对应的文件删除即可,或者删除整个目录,将需要修改的内容放在Deliverfile
  • 如果不想更改截图,可以把整个截图目录删除;
  • 如果Deliverfile内配置了screenshotsmetadata相关信息,则会忽略掉screenshotsmetadata目录下对应的信息;
  • 所有这些表单项也可以在Deliverfile中指定,Deliverfile中指定的项优先级比文件高
# 如果选择提交审核,请认真对照以下参数选项,根据自家App实际情况配置,如果配置错误,将不能提交成功
submission_information({
export_compliance_available_on_french_store: false,
export_compliance_contains_proprietary_cryptography: false,
export_compliance_contains_third_party_cryptography: false,
export_compliance_is_exempt: false,
export_compliance_uses_encryption: false,
export_compliance_app_type: nil,
export_compliance_encryption_updated: false,
export_compliance_compliance_required: false,
export_compliance_platform: "ios",
content_rights_contains_third_party_content: false,
content_rights_has_rights: false,
add_id_info_limits_tracking: true,
add_id_info_serves_ads: true,
add_id_info_tracks_action: false,
add_id_info_tracks_install: false,
add_id_info_uses_idfa: true
});

shell脚本

  • build_app.sh 自动化构建分发的命令执行文件
  • republish.sh 上传fir.im失败情况,再次上传ipa至fir.im命令
  • common.env 脚本通用环境变量配置文件
  • appstore.env 上传至App Store的环境配置文件
  • dev.env 编译测试版本ipa的环境配置文件

build_app.sh

#!/bin/bash

### 参数传递
## $1 : beta=开发测试包, release=App Store 发版
## 如果未指定参数,缺省为开发测试包

export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
export LC_ALL=en_US.UTF-8

## 环境初始化
if [ -z $1 ]; then
    AppENV="beta"
else
    AppENV=$1
fi

## 进入当前.sh所在目录
cd `dirname $0`

# 导入.env文件
if [ $AppENV == "beta" ]; then
    source ./common.env
    # source ./dev.env
else
    source ./common.env
    # source ./appstore.env
fi

# 删除之前的IPA
rm -r ${app_ipa_file}

# 打包APP
build_app() { 
    echo "+-------------------+-------------------+"
    echo "  building... <${AppENV}> ipa"
    echo "+-------------------+-------------------+"
    echo "  build number      | ${build_number}"
    echo "  ipa file          | ${app_ipa_file}"
    echo "+-------------------+-------------------+"

    fastlane ${AppENV}
}

# 上传到fir.im
publish_to_firim(){ 
    echo "+---------------------+------------------+"
    echo "  上传测试包到 fir.im"
    echo "+---------------------+------------------+"
    echo "  ipa file            | ${app_ipa_file}"
    echo "+---------------------+------------------+"

    fir login $firim_token
    # fir publish $app_ipa_file --changelog=${git_changelog_file} --short=${firim_short} --qrcode
    fir publish $app_ipa_file  --short=${firim_short} --qrcode
}

if [ $AppENV == "beta" ]; then
    build_app
    publish_to_firim
    open $app_ipa_qrfile
else
    build_app
fi

build_app.sh

#!/bin/bash

### fir.im 上传失败后 执行

export LANG=en_US.UTF-8
export LANGUAGE=en_US.UTF-8
export LC_ALL=en_US.UTF-8

## 进入当前.sh所在目录
cd `dirname $0`

# 导入.env文件
source ./common.env
source ./dev.env

echo "+---------------------+------------------+"
echo "  重新上传测试包到 fir.im"
echo "+---------------------+------------------+"
echo "  ipa file            | ${app_ipa_file}"
echo "+---------------------+------------------+"

fir login $firim_token
fir publish $app_ipa_file  --short=${firim_short} --qrcode

common.env

### 通用环境变量
### 可以根据项目实际情况进行修改

# Git 修订记录日志文件
git_changelog_file="./change_log.txt"

# 以日期+时间作为构建版本号,最终格式为: 月份日期小时分钟,全部均为两位数字,如 12 月 18 日 17:30 打包,则会是 12181730。
export build_number=`date +%m%d%H%M`

# 测试包托管平台的 TOKEN,为 fir.im 
firim_token="xxxx" 

# firim 专用的短网址中的短码
# 设置此短码将帮助更好的记测试包二维码网址
firim_short="firim_short"

# 打出的 IPA 包文件保存路径
app_ipa_file="ipa_build/xxx.ipa"
# 打出的 IPA 包二维码路径
app_ipa_qrfile="ipa_build/fir-xxx.png"

appstore.env

### 特定环境变量
### 可以根据项目实际情况进行修改

# Provisioning Profile 文件名称
# 如果开发者帐户里有多个项目,则需要指定。
# 开发者帐户里仅有一个项目,则可以为空,sigh 会自动匹配。
app_profilename=""

# 指定是否为开发/测试 Provisioning Profile
# 如果打包发布到 App Store,则需要为空。
app_profiledev=""

dev.env

### 特定环境变量
### 可以根据项目实际情况进行修改

# Provisioning Profile 文件名称
# 如果开发者帐户里有多个项目,则需要指定。
# 开发者帐户里仅有一个项目,则可以为空,sigh 会自动匹配。
app_profilename="xxx_development"

# 指定是否为开发/测试 Provisioning Profile
# 如果打包发布到 App Store,则需要为空。
app_profiledev="--development"

以上是所有的代码,使用也是很简单,下载 代码,将fastlane文件拖入工程根目录下,根据自己实际情况,配置好相关信息,然后在根目录下终端上执行命令:

构建分发测试包

./fastlane/build_app.sh

如果第一次上传fir.im失败,尝试以下命令

./fastlane/republish.sh

打包上传AppStore

./fastlane/republish.sh release


以上是本次分享的所有内容,如果有疑问,请在下面留言,看到后,我会第一时间回复,如果文章中有不正确的地方,请指出来,我会及时更正~

代码已经上传至GitHub,如果使用请移步build_ios_app,如果觉着对你帮助,那就顺手给个star吧😄

Refer

最后:谢谢你愿意花费时间来阅读此篇文章~,希望会对你有所帮助!

推荐阅读更多精彩内容