Jul 15

用脚本解决iOS开发与持续集成中的痛点

Lrdcq , 2019/07/15 22:22 , 程序 , 閱讀(2167) , Via 本站原創
Fastlane的衍生工具中,有一个叫Spaceship的ruby工具库https://spaceship.airforce/,可以帮助我们用脚本访问Apple Developer Center与App Store Connect API。当然,苹果自己的api已经足够了https://developer.apple.com/documentation/appstoreconnectapi/,当时还是有一些我们在网页上可以直接操作的事儿用api调用贼麻烦。Spaceship是结合api和苹果网页的请求api模拟操作一起使用的,那基本上我们在网页上能干的事情我们都可以做到了。是甚爽。

API:https://www.rubydoc.info/gems/spaceship/Spaceship 基本上是万能的。

脚本是个工具,这个屠龙宝刀面临我们实际工程中的问题时不知道是不是真好使。

场景一:开发过程,开发设备添加与pp更新

中小团队里开发过程中偶尔遇到的场景是给各位的开发者账号添加新的设备以供开发/测试/自动化等使用。虽然每年就遇到100次,但是手工添加还是太繁琐了。编写如下脚本:
#对入参进行验证

if not ARGV[1]
  puts '没有输入设备id与设备名称, 参考 \n ruby add_device_and_update_pp.rb {deviceid} {devicename}'
  exit
end

deviceid = ARGV[0] + ''
devicename = ARGV[1] + ''

require "./script_config_dev.rb"
require "spaceship"

#登录脚本

Spaceship::Portal.login(ScriptConfig::LOGIN_NAME, ScriptConfig::LOGIN_PWD)

Spaceship::Portal.select_team

#添加设备

puts '尝试添加设备id = ' + deviceid + ' 设备name = ' + devicename
begin
  Spaceship::Portal.device.create!(name: devicename, udid: deviceid)
  puts '设备添加成功!!!'
rescue 
    puts '设备添加失败!!!'
ensure 
end 

#操作pp

#要操作的pp名称Array<String>
updatepp_name = ScriptConfig::FOCUS_PP

profiles_devs = Spaceship::Portal.provisioning_profile.development.all

#重新获取所有设备。默认pp会添加上当前可用的所有设备
devices_all = Spaceship::Portal.device.all


for name in updatepp_name do
  profiles = Spaceship::Portal.provisioning_profile.all.find_all do |profile|
    profile.name.eql?(name)
  end
  profile = profiles.first
  
  if not profile
    next
  end
  #以上找到了目标profiles

  puts '开始更新' + name

  profile.devices = devices_all
  #更新profile
  profile = profile.update!

  puts '更新完成,开始下载' + name

  fileName = name + '.mobileprovision'
  File.write(Dir.pwd + "/#{fileName}", profile.download)

  puts name + '下载完成,保存在当前执行目录'
  
  #打开mobileprovision,即安装
  exec 'open ' + Dir.pwd + "/#{fileName}"

end

#最后打开下载目录
exec 'open ' + Dir.pwd

其中有几个涉及到苹果机制,也同时可以方便开发者使用的地方。

1. device.create方法在设备是正常设备并且当前帐号还有设备容量的时候一定会返回成功(包括设备已经存在)。如果不关心设备的实际添加情况的话,可以直接把相关错误trycatch住。

2. profile每次编辑更新后,其实等同于删除重建了一个profile,它的主键会发生改变,因此关注到profile = profile.update!那行其实是重新返回了新的profile。否则profile继续做操作苹果均会报错的。

3. profile.download直接获取profile实际文件二进制流,直接写入文件即可。而在mac里直接调用open ./*.mobileprovision 会直接通过xcode打开profile,也就是正常安装上了profile了。可以作为无感的过程。

场景2:描述文件保活

公司里不管是内测app还是内部工具app,ep发布的app老是遇到因为描述文件过期导致应用无法继续使用的事故。当然,按时检查描述文件的有效性是好习惯,不过如果我们能在构建过程中自动为描述文件做保活,就很方便了。

那么怎么为发布用描述文件续期呢?只要选择的证书时间足够,每次更新描述文件都会将其续期到MAX(一年,证书有效期)。那么结论上,我们构建的时候可以:

1. 无脑续期。
2. 对续期后时间还不够的情况做阻塞。
require "./script_config_dev.rb"
require "spaceship"

Spaceship::Portal.login(ScriptConfig::LOGIN_NAME, ScriptConfig::LOGIN_PWD)

Spaceship::Portal.select_team

profiles_devs = Spaceship::Portal.provisioning_profile.development.all

updatepp_name = ScriptConfig::FOCUS_PP

for name in updatepp_name do
  #找到profile
  profiles = Spaceship::Portal.provisioning_profile.all.find_all do |profile|
    profile.name.eql?(name)
  end
  profile = profiles.first

  #更新profile
  profile = profile.update!
  
  #判断profile过期时间
  if (profile.expires.to_time.to_i - Time.now.to_i) < 30 * 24 * 60 * 60
    puts '证书过期时间不足30天,'
    exit 1
  end

  puts '开始下载' + name

  #直接储存到/Library/MobileDevice/Provisioning Profiles目录中
  fileName = profile.uuid + '.mobileprovision'
  File.write("~/Library/MobileDevice/Provisioning Profiles/#{fileName}", profile.download)

  puts name + '下载完成'
end

其中由于ci环境可能open不好使,因此这里直接把描述文件串成标准的文件名称直接放到目标目录中。

另外ci中,登录流程其实很头疼的,fastlane工具链提供了fastlane spaceauth可以做ci会话。期待相关逻辑迁移到ConnectAPI方案,就可以走Token验证模式了。

场景3:添加testflight测试人员

app在内部release测试时,多半会通过testflight想内测人员发布。如果对外发布灰度的话,我们会建立一套邀请机制。Spaceship官方用法中就直接提供了相关的示范:
require "./script_config_dev.rb"
require "spaceship"

users = ScriptConfig::USERS

for user in users do
  Spaceship::TestFlight::Tester.create_app_level_tester(
        app_id: ScriptConfig::APP_ID,
         email: user.mail,
    first_name: user.first_name,
     last_name: user. last_name
  )
end

就会批量发送邀请出去。不过对于内部测试人员,Spaceship表示无能为力了。关注到其目前已经是调用的苹果公共api。我们关注下苹果提供的能力:

- https://developer.apple.com/documentation/appstoreconnectapi/user_invitations
- Manage users on your App Store Connect team. AppStoreConnect的用户邀请,权限设置能力。

- https://developer.apple.com/documentation/appstoreconnectapi/prerelease_versions_and_beta_testers
- Manage your beta testing program, including beta testers and groups, apps, and builds. 管理testflight的beta(对外)测试的相关项目。

似乎没有我们想到的东西,直到:

- https://developer.apple.com/documentation/appstoreconnectapi/builds
- Manage builds for testers and submit builds for review. 家伙来了。

點擊在新視窗中瀏覽此圖片

看起来Spaceship拓展下就可以使了。

..待续..
关键词:spaceship
logo