The easiest way to build and release mobile apps.
Fastlane是一套使用Ruby写的自动化工具集,用于iOS和Android的自动化打包、发布等工做,能够节省大量的时间。 android![]()
Github开源地址 fastlane官网)ios
iOS一键脚本完成如下步骤: 1 reset_git_repo 移除git中未提交的内容 2 git pull 只拉取最新tag 3 checkout 切换到最新的tag 4 submodule update 更新子模块 5 Pod install 第三方库管理工具 6 Archive、Sign 打包、签名 7 upload fir 上传Fir 8 notification 钉钉机器人git
Android 能够实现一键多渠道打包: 1 reset_git_repo 移除git中未提交的内容 2 git pull 只拉取最新tag 3 checkout 切换到最新的tag 4 submodule update 更新子模块 5 gradle 打包 6 add_channels_to_apk 拷贝apk,修改文件名为渠道名,渠道名写入META-INFO目录 参考连接:Fastlane实战(三):Fastlane在Android平台的应用github
sudo gem install fastlane
fastlane init
fastlane lane_name
# 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
fastlane_version "2.96.1"
default_platform(:ios)
platform :ios do
desc "Push a new beta build to fir"
lane :tofir do
# Deletes the Xcode Derived Data
clear_derived_data
# discarding uncommitted changes
reset_git_repo(
force: true,
skip_clean: true,
disregard_gitignore: false
)
# git pull only the tags, no commits
git_pull(only_tags: true)
# get recent tag
recentTagName = last_git_tag
# (fastlane-plugin-git_switch_branch为插件)check out tag
git_switch_branch(branch: recentTagName)
# submodule init and update
git_submodule_update(
init: true,
recursive: true
)
# pod install
cocoapods
scheme = "ProCloser"
ipa_dir = "./fastlane_build/"+Time.new.strftime('%Y-%m-%d')
ipa_name = recentTagName + "_" + Time.new.strftime('%Y%m%d%H%M')
# gym用来编译 打包 签名
gym(
output_directory: ipa_dir,
output_name: "#{ipa_name}.ipa",
clean: true,
workspace: scheme + ".xcworkspace",
scheme: scheme,
export_xcargs: "-allowProvisioningUpdates",
export_options: {
method: "ad-hoc", # 指定打包方式
teamID: "xxxxxxxxxxx",
thinning: "<none>",
}
)
# (fastlane-plugin-firim为插件)上传ipa到fir.im服务器,在fir.im获取firim_api_token
firim(firim_api_token: "xxxxxxxxxxxxxxx")
desc "Notification 钉钉机器人"
# 钉钉机器人
app_patch = ipa_dir + "/#{ipa_name}.ipa"
app_version = get_ipa_info_plist_value(ipa: app_patch, key: "CFBundleShortVersionString")
app_build_version = get_ipa_info_plist_value(ipa: app_patch, key: "CFBundleVersion")
app_name = get_ipa_info_plist_value(ipa: app_patch, key: "CFBundleDisplayName")
app_url = "xxxxxxxx"
app_icon = "xxxxxxx"
dingTalk_url = "xxxxxxxxx"
dingMessage =
{
msgtype: "link",
link: {
text: "对应git tag为: #{recentTagName}",
title: "iOS #{app_name} #{app_version} (#{app_build_version}) 测试版本",
picUrl: "#{app_icon}",
messageUrl: "#{app_url}"
}
}
uri = URI.parse(dingTalk_url)
https = Net::HTTP.new(uri.host, uri.port)
https.use_ssl = true
request = Net::HTTP::Post.new(uri.request_uri)
request.add_field('Content-Type', 'application/json')
request.body = dingMessage.to_json
response = https.request(request)
puts "--------------- 钉钉机器人已经通知 ✅ ---------------"
puts "Response #{response.code} #{response.message}: #{response.body}"
end
end
复制代码
客户端:shell
# 远程到打包机,运行打包机中的shell脚本。在打包机中配置了ssh信任因此不须要输入密码
ssh tiejin@tiejinios.local '/Users/tiejin/closerToFir.sh'
复制代码
服务器:json
# 解锁mac中的keychain,fastlane打包命令中的证书签名须要用到keychain中记录的帐户和密码。
security unlock-keychain -p 2018 $KEYCHAIN
# 进入指定目录
cd closer
# 设置环境变量,不然fastlane中涉及到/usr/local/bin/命令部分找不到
export PATH=/usr/local/bin/:$PATH
# 执行fastlane
fastlane tofir
复制代码
和 Jenkins 结合一块儿使用api
自定义Actions 0 什么是Action Action 是Fastlane中的最小执行单元,Action中封装了一些shell命令。数组
1 建立自定义Action ,会自动生成xxx.rb文件 fastlane new_action
ruby
2 编辑 xxx.rb 文件,修改具体逻辑。bash
module Fastlane
module Actions
module SharedValues
REMOVE_TAG_CUSTOM_VALUE = :REMOVE_TAG_CUSTOM_VALUE
end
class RemoveTagAction < Action
def self.run(params)
# 最终要执行的东西,在这里执行
# 一、获取全部输入的参数
# tag 的名称 如 0.1.0
tageName = params[:tag]
# 是否须要删除本地标签
isRemoveLocationTag = params[:isRL]
# 是否须要删除远程标签
isRemoveRemoteTag = params[:isRR]
# 二、定义一个数组,准备往数组里面添加相应的命令
cmds = []
# 删除本地的标签
# git tag -d 标签名称
if isRemoveLocationTag
cmds << "git tag -d #{tageName}"
end
# 删除远程标签
# git push origin :标签名称
if isRemoveRemoteTag
cmds << "git push origin :#{tageName}"
end
# 三、执行数组里面的全部的命令
result = Actions.sh(cmds.join('&'))
UI.message("执行完毕 remove_tag的操做 🚀")
return result
end
#####################################################
# @!group Documentation
#####################################################
def self.description
"输入标签,删除标签"
end
def self.details
# Optional:
# this is your chance to provide a more detailed description of this action
"咱们可使用这个标签来删除git远程的标签\n 使用方式是:\n remove_tag(tag:tagName,isRL:true,isRR:true) \n或者 \nremove_tag(tag:tagName)"
end
# 接收相关的参数
def self.available_options
# Define all options your action supports.
# Below a few examples
[
# 传入tag值的参数描述,不能够忽略<必须输入>,字符串类型,没有默认值
FastlaneCore::ConfigItem.new(key: :tag,
description: "tag 号是多少",
optional:false,# 是否是能够省略
is_string: true, # true: 是否是字符串
),
# 是否删除本地标签
FastlaneCore::ConfigItem.new(key: :isRL,
description: "是否删除本地标签",
optional:true,# 是否是能够省略
is_string: false, # true: 是否是字符串
default_value: true), # 默认值是啥
# 是否删除远程标签
FastlaneCore::ConfigItem.new(key: :isRR,
description: "是否删除远程标签",
optional:true,# 是否是能够省略
is_string: false, # true: 是否是字符串
default_value: true) # 默认值是啥
]
end
def self.output
# Define the shared values you are going to provide
# Example
end
def self.return_value
# If your method provides a return value, you can describe here what it does
nil
end
def self.authors
# So no one will ever forget your contribution to fastlane :) You are awesome btw!
["zhangyan"]
end
# 支持平台
def self.is_supported?(platform)
# you can do things like
#
# true
#
# platform == :ios
#
# [:ios, :mac].include?(platform)
#
platform == :ios
end
end
end
end
复制代码
Gemfile 和 Bundle 是什么: Gemfile文件:gem包管理工具,如:管理fastlane、cocoapods Appfile文件:从 Apple Developer Portal 获取和项目相关的信息 Fastlane文件:核心文件,主要用于 cli 调用和处理具体的流程 Deliverfile:从 iTunes Connect 获取和项目相关的信息
Action:对于Fastlane来讲Action的收录是很是严格,而且有很强的通用性才能收录其中,即便接收了,整个发布周期也会比较长,并且之后不管是升级仍是Bug修复,都依赖Fastlane自己的发版,大大下降了灵活性。
Plugin: Plugin就是在Action的基础上作了一层包装,这个包装巧妙的利用了RubyGems这个至关成熟的Ruby库管理系统,因此其能够独立于Fastlane主仓库进行查找,安装,发布和删除。
咱们甚至能够简单的认为:Plugin就是RubyGem封装的Action,咱们能够像管理RubyGems同样来管理Fastlane的Plugin。
fastlane search_plugins [query]
或 查看全部Plugin安装 fastlane add_plugin [plugin_xxx]
安装完成后 会在fastlane文件夹下生成Pluginfile文件实际就是一个Gemfile文件,里面包含了对于Plugin的引用,格式以下:
# Autogenerated by fastlane
#
# Ensure this file is checked in to source control!
# fastlane-plugin-version_from_last_tag 是插件名字
gem 'fastlane-plugin-version_from_last_tag'
复制代码
使用 和Action使用同样。
2 能够到Github / GitLab上 或者 引用本地路径。
gem "fastlane-plugin-version_from_last_tag", git: "https://github.com/jeeftor/fastlane-plugin-version_from_last_tag"
复制代码
发布以前,为了本地调试方便,能够将gem指向本地,在Pluginfile这样声明:
gem "fastlane-plugin-version_from_last_tag", path: "../fastlane-plugin-version_from_last_tag"
复制代码
fastlane action appium
2 Android Monkey 下面咱们看看Android通常运行Monkey测试的步骤:
Git Pull拉最新的代码 执行./gradlew clean命令清理环境 执行./gradlew assembleTest打包测试版本 执行命令安装最新的测试版本: adb shell monkey -p com.wanmeizhensuo.zhensuo -c android.intent.category.LAUNCHER 1
每次调用命令: fastlane do_monkey_test times:3 project:GengmeiAndroid apk_path:./GengmeiAndroid_test.apk ...
Fastlane文件配置以下:
desc "Android monkey test"
lane :do_monkey_test do |options|
times = options[:times]
project = options[:project]
apk_path = options[:apk_path]
package_name = options[:package_name]
hipchat(message: "Start monkey test on #{project}")
git_pull
gradle(task: "clean")
gradle(task: "assembleGmtest")
(1..times.to_i).each do |i|
adb(command: "install -r #{apk_path}")
adb(command: "shell monkey -p #{package_name} -c android.intent.category.LAUNCHER 1")
# 等待30秒,确保闪屏页被Finish后,进入到主页.
sleep(30)
android_monkey(package_name: "#{package_name}", count: '1000', seed: "#{10+i}")
end
hipchat(message: "Execute monkey test on project #{project} successfully")
end
复制代码
自定义的Action android_monkey 封装了 Android Monkey adb
更多Actions和Plugins查阅官网 Actions - fastlane docs Plugins - fastlane docs
before_all do |lane, options|
#git_pull
#cocoapods
end
复制代码
after_all do |lane,options|
slack(message: "fastlane was successful", success: true)
end
复制代码
error do |lane, exception|
slack(message: exception.message, success: false)
end
复制代码
引用机制 远程引用 import_from_git
import_from_git - fastlane docs每次执行fastlane的命令时,首先会从git上将须要的文件clone这个项目到本地的临时文件夹中,而后再执行相关命令。若是某个项目中,你不想使用远端上的某个lane,可在项目中的Fastfile中复写这个lane便可。
更多高级用法查看文档 Advanced - fastlane docs
0. Fastlane - iOS 和 Android 自动化构建工具 Fastlane实战(一):移动开发自动化之道 - 简书 Fastlane实战(二):Action和Plugin机制 - 简书 Fastlane实战(三):Android平台上的应用 - 简书
fastlane install
命令在bundle update 卡住,gem ruby 源有问题,这里建议添加国内源。
ruby镜像 https://gems.ruby-china.org
https://ruby.taobao.org/
替换命令:
$ gem sources --add https://gems.ruby-china.org/ --remove https://rubygems.org/
$ gem sources -l
*** CURRENT SOURCES ***
https://gems.ruby-china.org
# 请确保只有 gems.ruby-china.org
$ gem install rails
复制代码