什么是自动化?
通过简单的一条命令, 去自动执行一组固定操作
自动化的使用场景?
测试
打包上传审核
分发
自动化方案?
fastlane(快速航道):Fastlane是一个ruby脚本集合
关于Fastlane的概念
- lane:航道
- Action机制:
Action是Fastlane自动化流程中的最小执行单元,体现在Fastfile脚本中的一个个命令
比如:cocoapods, git_add等等,而这些命令背后都对应一个用Ruby编写的脚本。
-
目前所有的Action:
常用action:
- produce 创建可用于 iTunes Connect 和 Apple Developer Portal 的 iOS app。
- cert 自动创建和维护 iOS 代码签名证书。
- sigh 创建、更新、下载和修复 provisioning profiles。
- snapshot 自动将 App 屏幕截图本地化到每种设备上。
- frameit 将屏幕截图适配到适当的设备屏幕大小。
- gym 创建和打包 iOS app。
- deliver 上传屏幕截图、元数据和 App 到 App 商店。
- PEM 自动创建和更新 Push 通知的 profile。
fastlane安装(有近200M)
// 安装命令
sudo gem install -n /usr/local/bin fastlane
// 注意:-n /usr/local/bin 不能少,
// 否则会报文件夹权限错误:` While executing gem ... (Gem::FilePermissionError)
You don't have write permissions for the /usr/bin directory` .
如果要求Ruby版本最新:brew update
fastlane使用
1.进入根目录
2.fastlane init:如果不需要上传等操作,
3.在Fastfile文件中, 描述不同的"航道"
4.在项目根目录下, 执行某个"航道"
实践操作
- 选一个组件来操作LFRemotePlayer
- 创建本地库,pod lib create LFRemotePlayer,拖入代码
- 创建纯净远程库
- 修改LFRemotePlayer的描述文件
- 添加远程关联,cd LFRemotePlayer,git remote add origin https://git.oschina.net/lovell123/LFRemotePlayer.git
- 以上只需做一次,以下每次都要做,用fastlane
- fastlane init :
fastlane init 后 LFRemotePlayer文件夹内多出两个文件夹:fastlane文件夹
和LFRemotePlayer同一层级的build文件夹
,如下图。
以下中括号内的暂不需要:
【然后要填入付费的苹果开发者账号和密码,会在账号对应的Dev Center和iTunes connect创建一个新的APP,最后会在本地生成截屏信息、各种文件夹,这是后期做打包、测试、分发时候要用到的东西。但目前我们要做的是维护一个本地的私有库,还不需要那些东西,最重要的是我没有付费的开发者账号!】
所以fastlane init 无法最终完成,control + z,终止。手动操作一波:删掉build文件夹,删掉fastlane文件夹里面的Appfile。
- 进入fastlane文件夹,touch Fastfile,Fastfile是类似Podfile的一种文件。Fastfile是用于描述航道的。
- 编写航道:Fastfile里面的路径都是相对根目录来写,比如podfile的路径,是从Fastfile位置到根目录再到podfile的位置:
# 1. pod install
cocoapods(
clean: true,
podfile: "./Example/Podfile"
)
Fastfile文件:
# 描述:
desc '使用 ManagerLib 这个航道, 可以快速的对自己的私有库, 进行升级维护'
# 本航道名:ManagerLib
lane :ManagerLib do |options|
# options:传进来的参数,后面的tag和target是对应的字段
tagName = options[:tag]
targetName = options[:target]
# 具体这个巷道上面执行哪些行为
# 1. pod install
cocoapods(
clean: true,
podfile: "./Example/Podfile"
)
# 2. git add .
git_add(path: ".")
# git commit -m 'xxx'
git_commit(path: ".", message: "版本升级维护")
# git push origin master
push_to_git_remote
# 验证tag是否存在,如果存在, 应该删除本地标签和远程标签
#if 判断标签是否存在
# 执行删除本地/远程标签
#end
if git_tag_exists(tag: tagName)
UI.message("发现tag:#{tagName} 已经存在, 即将执行, 删除动作 🚀")
remove_tag(tag: tagName)
else
UI.message("tag:#{tagName} 不存在, 开始提交 🚀")
end
# 3. git tag 标签名称
add_git_tag(
tag: tagName
)
# git push --tags
push_git_tags
# 4. pod spec lint (注意要添加公、私仓库)
pod_lib_lint(allow_warnings: true, sources: ["https://gitee.com/LFCoding/xxxSpecs","https://github.com/CocoaPods/Specs"])
# pod repo push XXXX xxx.podspec (注意要添加公、私仓库)
pod_push(path: "#{targetName}.podspec", repo: "xxxSpec", allow_warnings: true, sources: ["https://gitee.com/LFCoding/xxxSpecs","https://github.com/CocoaPods/Specs"])
remove_tag.rb文件:
module Fastlane
module Actions
module SharedValues
REMOVE_TAG_CUSTOM_VALUE = :REMOVE_TAG_CUSTOM_VALUE
end
class RemoveTagAction < Action
# 1、运行action执行的动作
def self.run(params)
tagName = params[:tag]
isRemoveLocalTag = params[:rL]
isRemoveRemoteTag = params[:rR]
# 1. 先定义一个数组, 用来存储所有需要执行的命令
cmds = []
# 2. 往数组里面, 添加相应的命令
# 删除本地标签
# git tag -d 标签名称
if isRemoveLocalTag
cmds << "git tag -d #{tagName} "
end
# 删除远程标签
# git push origin :标签名称
if isRemoveRemoteTag
cmds << " git push origin :#{tagName}"
end
#3. 执行数组里面的所有命令(用&连接,类似git add . & git commit -m这样执行也是可以的)
result = Actions.sh(cmds.join('&'));
return result
end
# 2、描述整个action有什么用
def self.description
"牛逼的action"
end
# 3、详细的描述
def self.details
# Optional:
# this is your chance to provide a more detailed description of this action
"此牛逼action,可以删除本地和远程的某一个标签"
end
# 4、可用选项,传参数
def self.available_options
# Define all options your action supports.
# 对传进来的三个参数 tag、rL、rR 进行描述。
[
# key:参数名称,tag、rL、rR 。
# description:描述key对应的是参数tag的是干嘛的。
# optional:该tag参数是否可选,true表示该参数可以不传,false表示一定要传。
# is_string:是指传给key的值是否字符串。
# default_value:缺省值
FastlaneCore::ConfigItem.new(key: :tag,
description: "需要被删除的标签名词",
optional:false,
is_string: true),
FastlaneCore::ConfigItem.new(key: :rL,
description: "是否需要删除本地标签",
optional:true,
is_string: false,
default_value:true),# 默认值,表示没值就默认rL为true
FastlaneCore::ConfigItem.new(key: :rR,
description: "是否需要删除远程标签",
optional:true,
is_string: false,
default_value:true)# 默认值,表示没值就默认rR为true
]
end
#5、输出,暂时清空
def self.output
end
# 返回值,暂时写nil
def self.return_value
nil
end
# 作者的名字
def self.authors
# So no one will ever forget your contribution to fastlane :) You are awesome btw!
["luo feng"]
end
#平台的描述
def self.is_supported?(platform)
# you can do things like
#
# true
#
# platform == :ios
#
# [:ios, :mac].include?(platform)
#
platform == :ios
end
end
end
end
-
cd 回到根目录,
fastlane lanes
,检验是否有语法错误,如下图表示没错,但不代表逻辑没错。
使用fastlane:
fastlane ManagerLib tag:0.1.0 target:LFRemotePlayer
,
格式:fastlane ManagerLib tag:标签 target:组件名(podspec文件名)
-
检索
pod search LFRemotePlayer
,报错如下。解决:1、pod cache clean --all
清缓存,2、删索引缓存search_index.json(位置:/Users/fengluo/Library/Caches/CocoaPods/search_index.json
),3、再搜索,即可。
宿主工程使用。
宿主podfile中引入source,pod 'repo name',pod install,随便导入库某一个头文件,编译成功即可。
遇到的问题
- 如果在spec文件夹里面用 pod repo add <repo name>,会添加失败,退到repos文件夹。
- 注意忽略文件加上.DS_Store
- spec描述文件验证、推送加上allow_warnings
- 刚提交完spec描述文件,pod search 搜索不到,这时候清缓存pod cache clean --all,删搜索缓存文件search_index.json,再次搜索即可成功。
- fastlane init需要付费的账号才能成功,有好些功能:打包、测试、分发等,若是没有,则control+z停止,在fastlane文件夹中touch Fastfile,我们只需要维护一个本地私有库。