当项目达到一定规模后,为了便于管理,我们都会引入自动化构建。本篇主要是讲述如果通过jenkins和fastlane实现iOS的打包。

关于jenkins的搭建就不多说了,大家可以按照网上的文章去配置,基本都是傻瓜式一键安装。

本文将要解决的问题是如何在jenkins搭建iOS的自动编译job。

构建iOS的包只能在Mac机器上进行,如果Jenkins搭建在Linux或者非Mac机器上,需要在Jenkins中配置slave节点连接到Mac电脑。

1. 准备工作

Q:为何是通过fastlane来构建iOS,而不是通过Jenkins的Xcode插件来构建呢? A:Xcode插件方式不仅配置麻烦,而且配置完成后还需要大量的调试工作才能正确编译。而fastlane只需要配置一次,简单方便。

既然是通过fastlane来构建,那么我们首先得需要配置好fastlane相关的东西。

1.1 安装fastlane

在Mac编译机上需要配置好fastlane

打包iOS我们需要保证xcode命令行已经正确安装

xcode-select --install  //命令行输入,如果未安装会弹出对话框提示安装,否则会提示已经安装

可以通过两种方式来安装fastlane 方式一:

[sudo] gem install fastlane -NV

方式二:

brew cask install fastlane

1.2 项目中配置fastlane

给我们需要自动化编译的iOS工程配置fastlane

假如我们现在有一个BlocklySample的工程,我们需要在项目根目录下执行命令行

fastlane init

会有如下图这样的提示,需要我们选择哪种任务,这里我们可以选2或者3。选择这两个选择后会提示让你输入iOS开发者的账号密码,这样会自动给你生成团队信息、bid和基本编译脚本等等。

执行完成后在项目根目录下会自动新建一个fastlane的目录

修改fastlane目录下的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
# update_fastlane

default_platform(:ios)

platform :ios do
  desc "Push a new release build to the App Store"
  lane :release_appstore do
    increment_build_number(xcodeproj: "xxx.xcodeproj")
    update_project_provisioning(
        # 之前有sigh下载的描述文件存储路径
        profile:"fastlane/provision/xxx.mobileprovision",
        # 打包配置,Debug,Release
        build_configuration:"Release"
    )
    automatic_code_signing(
        # 工程文件所在路径
        path:"xxx.xcodeproj",
        # 是否使用自动签名,这里如果是打包的话应该一般都为false吧,默认也是false
        use_automatic_signing:false,
        # 这个就不用说了,需要修改的targets
        targets:"xxx",
        # 用哪种方式打包“iPhone Develop”还是“iPhone Distribution”
        code_sign_identity:"iPhone Distribution",
        # 描述文件名称, 也就是使用哪个描述文件打包
        profile_name:"xxx"
    )
    scheme_name = 'xxx'
    configuration = 'AppStore'
    version = get_info_plist_value(path: "./#{scheme_name}/Info.plist", key: "CFBundleShortVersionString")
    build = get_info_plist_value(path: "./#{scheme_name}/Info.plist", key: "CFBundleVersion")
    output_directory = File.expand_path("..", Dir.pwd) + File::Separator + 'build'
    output_name = "#{scheme_name}_#{configuration}_#{version}_#{build}_#{Time.now.strftime('%Y%m%d%H%M%S')}.ipa"
    build_app(workspace: "xxx.xcworkspace", scheme: "xxx", export_method: "app-store", output_directory: output_directory,
      output_name: output_name)
    upload_to_app_store
  end
  desc "Push a new release build to the Testflight"
  lane :release_testflight do
    update_project_provisioning(
        # 之前有sigh下载的描述文件存储路径
        profile:"fastlane/provision/xxx.mobileprovision",
        # 打包配置,Debug,Release
        build_configuration:"Release"
    )
    automatic_code_signing(
        # 工程文件所在路径
        path:"xxx.xcodeproj",
        # 是否使用自动签名,这里如果是打包的话应该一般都为false吧,默认也是false
        use_automatic_signing:false,
        # 这个就不用说了,需要修改的targets
        targets:"xxx",
        # 用哪种方式打包“iPhone Develop”还是“iPhone Distribution”
        code_sign_identity:"iPhone Distribution",
        # 描述文件名称, 也就是使用哪个描述文件打包
        profile_name:"xxx"
    )
    scheme_name = 'xxx'
    configuration = 'AppStore'
    version = get_info_plist_value(path: "./#{scheme_name}/Info.plist", key: "CFBundleShortVersionString")
    build = get_info_plist_value(path: "./#{scheme_name}/Info.plist", key: "CFBundleVersion")
    output_directory = File.expand_path("..", Dir.pwd) + File::Separator + 'build'
    output_name = "#{scheme_name}_#{configuration}_#{version}_#{build}_#{Time.now.strftime('%Y%m%d%H%M%S')}.ipa"
    build_app(workspace: "xxx.xcworkspace", scheme: "xxx", export_method: "app-store", output_directory: output_directory,
      output_name: output_name)
    upload_to_testflight
  end
  desc "Push a new release build to the Ad Hoc"
  lane :release_adhoc do |option|
  	# cocoapods
  	#根据传入参数version设置app的版本号
	# increment_version_number(version_number: option[:version]) 
	#自动增加build号
	#increment_build_number
  	update_project_provisioning(
        # 之前有sigh下载的描述文件存储路径
        profile:"fastlane/provision/xxx.mobileprovision",
        # 打包配置,Debug,Release
        build_configuration:"Release"
    )
  	automatic_code_signing(
        # 工程文件所在路径
        path:"xxx.xcodeproj",
        # 是否使用自动签名,这里如果是打包的话应该一般都为false吧,默认也是false
        use_automatic_signing:false,
        # 打包的team ID, 也就是打包使用的证书中的team ID,这个如果不知道是什么的话可以在xCode中设置好签名用的描述文件后到xcodeproj下的pbxproj文件中搜索“DEVELOPMENT_TEAM”,它的值就是了
        team_id:"RRRRR5555",
        # 这个就不用说了,需要修改的targets
        targets:"xxx",
        # 用哪种方式打包“iPhone Develop”还是“iPhone Distribution”
        code_sign_identity:"iPhone Distribution",
        # 描述文件名称, 也就是使用哪个描述文件打包
        profile_name:"xxx"
    )
    #证书签名
    # sigh
    #编译打包
    scheme_name = 'xxx'
    configuration = 'Release'
    version = get_info_plist_value(path: "./#{scheme_name}/Info.plist", key: "CFBundleShortVersionString")
    build = get_info_plist_value(path: "./#{scheme_name}/Info.plist", key: "CFBundleVersion")
    output_directory = File.expand_path("..", Dir.pwd) + File::Separator + 'build'
    output_name = "#{scheme_name}_#{configuration}_#{version}_#{build}_#{Time.now.strftime('%Y%m%d%H%M%S')}.ipa"
    gym(
    	scheme: scheme_name, 
    	clean: true, 
    	silent:true,
    	export_method:'ad-hoc', 
    	export_options: {
      	  provisioningProfiles: { 
      	  #前面的是bundle id,后面的是对应用到的mobileprovision,只需要名字,不需要后缀
          "me.ithome.xxx" => "xxx"
        }},
        configuration: configuration, 
        output_directory: output_directory, 
        output_name: output_name, 
        # 签名证书的名称,去钥匙串-登录-证书里面复制
        codesigning_identity:'iPhone Distribution: xxx (Rxxx47)',
        export_xcargs: '-allowProvisioningUpdates')
        # 上传到蒲公英,需要安装pgyer插件
        #pgyer(api_key: "aaaa", user_key: "bbbb")
  end
end
  • 上述脚本中有部分xxx之类的东西,需要自行替换成自己项目的。
  • 所有脚本中用到的xxx.mobileprovision都需要双击安装一次,否者会提示找不到。
  • 需要安装好p12证书文件。

修改完成后我们就有了三个命令,用来分别打包上传到appstore、testflight和蒲公英。 fastlane release_appstore fastlane release_testflight fastlane release_adhoc

我们可以运行fastlane release_adhoc来打个adhoc包测试下是否全部配置成功。 如果一些都配置无误,运行后应该会提示

ipa文件已经打包出来了。

此时环境配置已经完成。接下来我们来配置如何通过Jenkins来实现自动化打包。

2. 新建一个自由风格的软件项目

因为需要分别打包appstore、testflight和adhoc,所以我们需要构建参数

也许还需要配置下git代码分支

如果是通过slave连接的Mac,还需要配置下(jenkins架设在Mac上的请无视)

配置源码地址

顺便配置个job名吧

配置构建命令

最后,文件归档

如果上传到了蒲公英,还能做一些获取二维码的操作,请自行研究。

好了,配置完成后的构建界面如下:

收工。

也许你会遇到执行fastlane打包命令发现打包失败的问题,请仔细阅读失败的错误提示,一般都能找出问题所在。