【DevOps进行时】iOS应用自动推送的方法研究与实践 | IDCF

IDCF

image.png

摘要

自动推送指通过自动的方式将移动端应用推送至相应的发布平台供客户下载使用。目前研发中心已经完成了开放平台、主机平台以及移动平台等主流开发语言的集中构建,随着移动端应用逐渐成为人们生活中使用最频繁的程序,研发中心移动端应用也呈井喷式的增长,iOS平台作为移动端重要的组成部分之一,由于其本身产品系统的独特性以及移动应用迭代频繁的特点,在实现了集中构建以后,推送至苹果商店这一环节一直处于手工上传的方式。

为了适应项目投产需要与中心构建发布整体发展思路保持一致,在进行了大量项目实践的基础上本文提出了可借鉴的自动构建推送方法,旨在帮助项目实现完全自动化的构建推送,将目标码直接推送至苹果商店,有效管理项目证书和代码的同时,减少不必要的交互,提高投产效率并为后续的测试和自动化部署积累丰富的经验。

关键词:自动推送、TFS、目标码、持续集成

一、研究背景

苹果操作系统主要包括OSX和iOS,其主要的开发语言为Objective-C、Swift以及Javascript,使用LLVM编译器框架系统,前端使用Clang编译器。目前研发中心投产运行的苹果应用主要使用Objective-C和Javascript语言开发,苹果公司为每一个应用都设置了证书以保证信息在互联网中安全传输,分为公司版证书程序和企业版证书程序,这两类证书对程序的发布途径起着至关重要的作用:

  • 公司版证书:属于“组织”类别,功能用途与个人版证书一致,允许多个开发者协作开发,只能用于将应用发布至苹果App Store。
  • 企业版证书:属于“组织”类别,允许多个开发者协作开发,只能用于将应用发布至企业内部使用。

由于iOS应用具有上述特点,证书对于iOS应用的投产和上线起到了至关重要的作用并且与研发中心现有投产体系存在较大差异,目前大多采用手动发布的模式。面对移动端应用投产上线的实际情况,在完成集中构建工作以后,将应用发布至苹果App Store这一环节的自动化方式成为亟待解决的问题。

二、技术术语

2.1 编译

一般来说编译过程主要分为以下四部分:

  • 预处理(Pre-process),把宏替换,删除注释信息,将头文件进行展开,产生.i文件。
  • 编译(Compliling),把.i文件转换成汇编语言产生.s文件。
  • 汇编(Asembly),将.s文件转换成机器编码文件,产生.o文件。
  • 链接(Link),对.o文件中的所提到的的库文件进行引用(包括多个.o文件进行link),生成最后的可执行文件。

2.2 开发语言

iOS开发语言主要包括:C语言基础、Objective-C、Swift以及Javascript编程语言。

  • Objective-C:是扩充C的面向对象编程语言,它是一个用C写成很小的运行库,令应用程序尺寸增加很小,完全兼容C语言,可以使用GCC和Clang运行的系统上进行编译,目前研发中心主要使用该语言进行开发。
  • Swift:于2014年WWDC发布的新开发语言,可与Objective-C共同运行于Mac OS和iOS平台,为了使Swift语言易用性和功能性更加出色,苹果公司也在不断的对编译器进行优化和改进。以目前最新版本Xcode7版本为例,使用LLVM7.1(Xcode7.3)编译器,该编译器是自Xcode5将GCC编译器取消后一直使用的,LLVM编译器的前端是Clang,支持C、C++、Objective-C和Objective-C++等编程语言。
  • JavaScript:该脚本语言是苹果公司在iOS7之后推出的基于JavaScriptCore.framework框架的开发方式,实现Objective-C与Javascript相互调用并传参的方法,使用此框架可以在iOS应用中运行JavaScript脚本,也就是HybirdApp混合模式移动应用,即其中包含原生的结构有内嵌有web组件,这种App不仅性能和用户体验可以达到和原生所差无几的程度,更大的优势在于bug修复快,版本迭代无需重新编译发布,目前研发中心越来越多的项目开始采用此种开发模式。

2.3 iOS构建发布要素

iOS应用从构建到发布应用一般会经历三个阶段:在Xcode(苹果程序开发工具)上运行调试、在设备上运行调试和编译发布。 苹果为了防止非法设备和非开发人员调试和发布应用,需要使用配置概要文件(Provisioning Profiles)控制应用在设备上运行调试和编译发布。配置概要文件由证书(certificates)、项目标识(Identifiers)以及设备(Devices)组成,具体的编译发布流程如下:

image.png

图1

  • 证书(Certificates):苹果官方颁布的证书,分为开发证书和发布证书两种,苹果是发布者,然后安装,这个证书的Mac就是拥有者。苹果就会给电脑授予这个证书所对应的权利,简单来说,证书是iOS应用开发的基础,也是构建的必要组成部分。
  • 项目标识(Identifiers):Identifiers即“标识符”,约等于是项目的身份证,用于区别苹果应用,每个应用都有各自唯一的标识符,项目标识包括:App ID其实就是一个App的身份证,一个App的位置标识。在Project中称为Bundle ID。在Member Center、Project、ITunes Connect都是需要此ID去标识APP的唯一性。Bundle ID在不同环境下的表现关系,如下图所示:

image.png

图2

在创建App ID过程中可以配置该应用的权限,比如是否用到了PassBook,GameCenter,以及更常见的push服务,如果选中了push服务,那么就可以创建生成具有推送服务的App ID,所以,在所有和推送相关的配置中,首先要做的就是先开通支持推送服务的App ID。

  • 设备(Devices):Devices作用为创建测试设备,只有在此列表中的设备才能安装真机调试阶段的苹果应用,未在该列表中的设备则不能安装,一般情况下该列表中设备总数不能超过100个。
  • 配置概要文件(Provisioning Profiles):配置概要文件是很有苹果特点的设置,该文件将证书(Certificates) 、项目标识(Identifiers)、设备(Devices)结合起来,形成一个描述证书、标识符的描述文件。通过Xcode编译的过程将配置概要文件与程序关联起来从而形成待发布苹果App。

三、问题描述

推送是将构建并测试通过的苹果应用发布到应用市场等待审核的过程,对于苹果应用而言,一般分为两部分:

  • 第一部分是将待投产的程序包上传至苹果服务器进行程序及配置文件的自动扫描,主要在代码层面进行检查。
  • 第二部分是在机器扫描通过后进行应用市场发布的最后检测,主要针对程序的功能和性能进行人为测试。

通过前期集中构建情况分析和经验总结,在实现了全行苹果应用集中构建的基础上,如何替代人工上传方式,将待投产程序自动推送至苹果服务器进行审核,成为了影响苹果持续集成效率的关键点,经前期手动推送应用的情况分析和经验总结,对项目症结有了大致的分类和判断,总体来说iOS自动推送主要问题集中在如下几点:

1)推送方式多样

iOS分为两种方式推送方式:

  • 一种是通过开发工具Xcode在手动完成构建后直接通过界面上传至苹果商店。
  • 第二种是通过Xcode中自带的上传工具Application Loader进行上传,虽然界面不同,但其最终上传界面和代码没有本质区别。

2)推送环境特殊

iOS项目开发需在苹果操作系统macOS中进行,开发工具一般采用Xcode,目前研发中心苹果集中构建在内网环境中解决,虽然构建环境统一,但由于两网隔离的制约,推送至苹果商店及相关发布平台方式不尽相同。

3)推送管理工具多样

iOS项目开发大多在苹果笔记本上进行,配置库采用GIT版本控制系统较多,发布结果除了苹果平台以外,没有统一的管理机制,在代码质量、版本稳定性以及版本追溯等方面对项目投产上线产生极大的影响。

4)发布操作复杂人工成本高

苹果公司对每一个发布的iOS应用都采用证书授权机制,通过编译将证书进行注入,起到认证和管理的目的,但由于证书的唯一性,在日常开发过程中是无法使用苹果授权证书进行打包并生成iOS应用的,尤其这对需要进行大规模测试的项目来说影响较大,项目上线则需要将代码拷贝至组织级构建管理员处进行编译后发布。

为了更好的解决iOS项目推送问题,应从推送方式入手,梳理iOS应用推送特点的同时,总结出适用于不同项目情况的推送方法,解决由于发布方式和发布途径不同对苹果应用投产产生的影响,提升整体集成效率,降低投产风险。

四、解决方案

4.1 构建推送日志分析

经过大量的手工编译和推送并对日志进行分析总结得出目前研发中心iOS应用推送一共分为两种情况:

  • 一种是发布至苹果商店对客进行下载,这种项目需要发布至苹果商店供苹果设备客户进行下载。
  • 第二种是企业内部需求直接在企业内部发放使用的应用。

通过查看Build日志可以进一步的了解苹果程序编译推送过程的工作原理提升开发及管理工作效率,在多数情况下Build编译日志隐藏了大量的信息,其中经常会有一些通用的编译命令,以这些命令为基础可以更好的对编译日志进行模块化的解读和研究。

CompileC...:主要用来编译.m和.c文件,在每一个target中被广泛使用,生成中间文件.o,一般出现在Compile步骤的行首位置。

image.png

图3

Libtool...:主要是从目标文件中构建library,即生成.a文件,一般出现在创建.a文件的过程中。

image.png

图4

CreateUniversalBinary...:将上阶段生成.a文件合并为一个通用的二进制文件。

image.png

图5

Ld:与Libtool功能相似是一个linker的工具,被用来构建可执行文件,即生成最终的.ipa文件,该命令一般较长出现在构建目标码阶段。

根据上述命令分析就可以很清晰的了解苹果程序的编译过程,以项目中某一target为例,如下图所示,该target作用是生成可执行文件需要的.a文件,即libDZNEmptyDataSet.a,其中使用了CompileC、Libtool以及CreateUniversalBinary等命令对源码进行处理。

image.png

图6

在编译完成后Xcode自带的Application Loader提供了一整套命令行工具 altool,帮助项目解决项目目标码文件的验证和上传工作。

altool --validate-app -f file -u username [-p password] [--output-format xml]

altool --upload-app -f file -u username [-p password] [--output-format xml]

4.2 自动推送方法研究

通过对上述日志进行逐字逐句分析可以看出iOS项目虽然编译过程比较复杂,编译命令数量繁多,编译方法丰富多样,但总体来说都会遵循一定的规则进行,每一个target之间存在相互的主次关系,通过调用主target就可以实现整个项目构建并生成目标码(.IPA)文件。自动推送当中最为关键的是ExportOptions.plist文件,文件中记录了两个配置概要文件对应规则,在自动推送的过程中,程序直接调用该plist文件就可正确进行匹配,减少手工干预过程,最终实现应用的自动推送。

项目的配置和规则信息都储存于工程文件(.xcodeproj)当中,通过自动构建可以实现生成目标码,但核心问题是,在随后的推送应用过程当中,需要手动对上传目标码进行匹配,上传过程和命令基本不可见,需要对推送过程中使用的命令进行整理和分析才能最终形成自动推送命令行方法。通过对手工过程中所遇到情况进行总结,结合Xcode命令参数,目前形成了两种可以覆盖研发中心现有项目模式的自动推送方案。

1)调用plist文件实现自动推送

这类推送模式相对比较简单,只需要对推送过程中的操作命令进行排列组合并找到项目所对应的plist文件即可实现自动推送过程,目前研发中心主要使用该种方式进行应用的自动推送,经测试和实际使用经验总结,比较常用的命令如下所示:

表1 推送参数解析

image.png

为了更好对iOS推送过程进行解析,将上述命令行带入项目运行可以看出实际效果如下:

project_path=/Users/abc/ipa
project_name=AutoDeployTest
scheme_name=ABCDeploy
development_mode=Release
build_path=${project_path}/build
exportOptionsPlistPath=${project_path}/ExportOptions.plist
exportIpaPath=${project_path}/ABCDir/${development_mode}
altoolPath="/Applications/Xcode.app/Contents/Applications/Application Loader.app/Contents/Frameworks/ITunesSoftwareService.framework/Versions/A/Support/altool"
"$altoolPath" --validate-app -f ${exportIpaPath}/${scheme_name}.ipa -u 123 -p 123 ios --output-format xml
"$altoolPath" --upload-app -f ${exportIpaPath}/${scheme_name}.ipa -u 123 -p 123 ios --output-format xml

在实际调用的plist文件中已经将证书、配置文件、发布方式等参数进行了匹配记录,直接调用即可,减少了很多不必要的交互,实现最简洁的iOS应用的自动发布。

image.png

图7

最后通过参数将上传过程中的信息进行保存并生成xml文件解析其中的key值来判断上传步骤是否成功。key值为success-message即上传成功,key值为product-errors则为上传失败,可继续在xml文件中查看报错信息。

image.png

图8

image.png

图9

2)使用Fastlane实现自动推送

这类自动推送相对复杂,Fastlane是一套使用Ruby编写的自动化工具集,旨在简化Android和iOS的部署过程,自动化工作流,对于Fastlane的安装配置,这里就不过多赘述了,它一套工具的集合,每一个工具叫做action,包括代码签名、构建、打包、推送等功能,由于构建打包功能已经在TFS中实现,这里只会用到Fastlane推送功能。

image.png

图10

image.png

图11

这里我们会使用到deliver这个action当中的上传功能实现自动化将应用上传至App Store当中,由于Fastlane中每一个action都提供了十分强大的命令行功能,这里就不做展开,仅简要进行介绍。

表2 常用action解析

image.png

安装完成后,在进行上传应用前,需要对本次上传的应用信息进行维护,以便在上传过程中对应用的信息进行更新,并保证上传过程不会因为信息错误而导致失败,具体维护方式主要是对安装目录下的Deliverfile文件中的信息进行填写,目的是利用该文件提前维护好ITunes Store需要填写的应用相关信息,保证上传过程的自动化。

# The Deliverfile allows you to store various iTunes Connect metadata
# For more information, check out the docs
# https://docs.fastlane.tools/actions/deliver/
# 根据iTunes Store 信息设置
username "123"  # Apple ID email address
app_identifier("com.abc.test") # bundle identifier
#ipa("/Users/abc/ipa/ABCDeploy.ipa") # 没有这个选项,只有metadata会被上传
copyright("版权信息") #版权信息
#submit_for_review(false) #是否提交审核,true表示立马提交审核
screenshots_path("./fastlane/screenshots") # 截屏图片展示
price_tier 0 #app 出售价格
trade_representative_contact_information(  #iTunes store 信息
  first_name: "yinhang", #名
  last_name: "nongye", #姓
  address_line1: "123", #地址
  address_line2: "",
  address_line3: "",
  city_name: "BeiJing", # 城市
  state: "BeiJing", # 省
  country: "China", #国家
  postal_code: "100000", # 邮编
  phone_number: "+86 13700000000", # 手机
  email_address: "abc.abchina.com", #邮箱
)
app_review_information( # app审核信息
  first_name: "yinhang", # 名
  last_name: "nongye", #姓
  phone_number: "+86 13700000000", #联系信息电话号码
  email_address: "abc.abchina.com", #联系信息邮箱
  demo_user: "123",  #审核测试账号
  demo_password: "123", # 审核测试密码
  notes: "备注信息" # iTunes Store 审核信息备注
)
#提交审核信息:加密, idfa 等
submission_information(
export_compliance_encryption_updated: false,
    export_compliance_uses_encryption: false,
    content_rights_contains_third_party_content: false,
    add_id_info_uses_idfa: false
)
name({
'zh-Hans' => "nongyeyinhang"  # app名称
})
description({ #iTunes Store 中描述信息
  'zh-Hans' => "APP的描述信息,用于APP功能的描述和介绍不能少于10个字符"
})
release_notes({
  'zh-Hans' => "第一个版本测试"
})
keywords( # 收缩关键词
  "zh-Hans" => "农业, 银行"
)
promotional_text( 
  "zh-Hans" => "宣传文本信息介绍",
)
support_url({ # 技术支持网址(URL)
  'zh-Hans' => "http://www.95599.cn"
})
marketing_url({ #营销网址
  'zh-Hans' => "http://www.95599.cn"
})
privacy_url({
  'zh-Hans' => "http://www.95599.cn"
})
app_icon('./fastlane/metadata/AppIcon.png') #应用图标
primary_category("Utilities") 
# primary_first_sub_category "Card"
# primary_second_sub_category "Casino"
# 要设置的次要类别 无
# secondary_category  
# 设置的次要第一个子类别 无
# secondary_first_sub_category  
# 设置的次要第二个子类别 无
# secondary_second_sub_category
automatic_release true #审核过之后自动发布

Deliverfile文件维护完成后,需要对fastlane/metadate/下创建名为itunes_rating_config.json文件,按照ITunes Store要求对应用进行评级供应审核时使用。

{
  "CARTOON_FANTASY_VIOLENCE": 0,#卡通或幻想暴力
  "REALISTIC_VIOLENCE": 0,#现实暴力
  "PROLONGED_GRAPHIC_SADISTIC_REALISTIC_VIOLENCE": 0,#大量露骨或残暴的现实暴力
  "PROFANITY_CRUDE_HUMOR": 0,#低俗笑话
  "MATURE_SUGGESTIVE": 0,#成人/性暗示题材
  "HORROR": 0,#恐怖/惊悚题材
  "MEDICAL_TREATMENT_INFO": 0,#医学/医疗信息
  "ALCOHOL_TOBACCO_DRUGS": 0,#使用或提及烟、酒或毒品
  "GAMBLING": 2,#模拟赌博
  "SEXUAL_CONTENT_NUDITY": 0,#色情或裸露内容
  "GRAPHIC_SEXUAL_CONTENT_NUDITY": 0,#色情及裸体画面
  "UNRESTRICTED_WEB_ACCESS": 0,#无限制的网站访问
  "GAMBLING_CONTESTS": 0#赌博和竞赛
}

上述工作全部完成后,就可以通过Fastlane中的action进行应用的自动上传,实现应用自动构建发布的全流程自动化。

default_platform(:ios)
platform :ios do
desc "上传至 App Store"
   lane :release do
scheme_name="ABCDeploy"  
output_directory="/Users/abc/ipa"
scheme_version="1.0.0"
output_name="#{scheme_name}_#{scheme_version}.ipa"
      gym(
export_method: "app-store",
export_xcargs: "-allowProvisioningUpdates", 
scheme: scheme_name,
clean: true,
output_directory: output_directory,
output_name: output_name,
) 
      deliver(
            Ipa:"output_name"
            submit_for_review: true,
        ignore_language_directory_validation:true,
        force:true
        skip_screenshots:true
             )
      end

五、总结

自动推送可以说是在iOS集中构建完成后急需解决的一个流程贯通环节,以往手动上传需要人工干预较多,效率相对较低,iOS应用实现了标准化构建模式后急需一个自动推送模式进行衔接。

本次研究制定“调用plist文件实现自动推送”以及“使用Fastlane实现自动推送”的推送方法,相比较这两种方法:

  • “调用plist文件实现自动推送”中所使用到的ExportOptions.plist文件是通过集中构建自动生成的,不需要人工干预和维护,对于已经发布过的iOS应用来说十分的便利快捷,目前研发中心项目大多使用该种方式进行应用的自动推送。
  • “使用Fastlane实现自动推送”由于提供了一整套action的工具集,实现的功能比较强大,但所需维护的苹果商店信息比较复杂,初次使用很容易出现信息错误的情况适合多次投产的“老手”使用,并且可以对自动推送进行定制化开发,灵活性较高。

这两种方法主要目的是帮助项目解决iOS应用测试和发布环节效率低下的问题,提升了发布效率,降低了交互时长,提升了工作质量并建立标准化的自动推送流程,是向持续集成,持续部署,持续交付等开发实践又迈出坚实的一步,相信在后续工作开展当中仍能一如既往的披荆斩棘不断深化扩展集中构建成果,积极探索后续开发实践过程,为研发中心DevOps以及持续集成和持续部署等工作提供技术力量支持。

本文作者:系统支持部 霍晓楠
阅读 361
76 声望
11 粉丝
0 条评论
你知道吗?

76 声望
11 粉丝
宣传栏