ykfastlane 0.3.9
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of ykfastlane might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +253 -0
- data/bin/ykfastlane +20 -0
- data/lib/actions/YKFastlaneExecute.rb +87 -0
- data/lib/actions/archive.rb +152 -0
- data/lib/actions/archiveHelper.rb +41 -0
- data/lib/actions/certificate.rb +92 -0
- data/lib/actions/init.rb +84 -0
- data/lib/actions/pod.rb +29 -0
- data/lib/interface.rb +41 -0
- data/lib/ykfastlane/helper.rb +84 -0
- data/lib/ykfastlane/tools.rb +172 -0
- data/lib/ykfastlane/version.rb +6 -0
- metadata +183 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e6937021ba14f5cbf585f0c21e1403526860fb84224d739b276a07c56fdb806f
|
4
|
+
data.tar.gz: 57bb28d001604492e24c002562678a65fe13aa37728df333fceb8a09e0c457e8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f96a4e2be84992b29c4ae26d709208ff4f01e4c9e8504e3e0fc7dca4fe0d23dcebd630fd5531034a24748dd0c14b9c28a2b24048ed840757e4610b845b7d1bc9
|
7
|
+
data.tar.gz: 21ec5f0c11f7ca2a3d4302aa670e8c06e801c448b5f8e78ed1f8dfff531fc3d6ae60d9588a20b3619ed6af0b34c4d592c4e0f3239b53611ad81415c28235323b
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2022 stephen.chen
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,253 @@
|
|
1
|
+
# Ykfastlane
|
2
|
+
|
3
|
+
iOS 通用打包工具的终端门户工具
|
4
|
+
|
5
|
+
- [Ykfastlane](#ykfastlane)
|
6
|
+
- [Installation](#installation)
|
7
|
+
- [Usage](#usage)
|
8
|
+
- [基础配置](#基础配置)
|
9
|
+
- [证书管理](#证书管理)
|
10
|
+
- [打包](#打包)
|
11
|
+
- [异常情况处理](#异常情况处理)
|
12
|
+
- [License](#license)
|
13
|
+
- [建议](#建议)
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
本指令集适用与ruby 2.7.5 ~ 3.0.3
|
18
|
+
|
19
|
+
- 安装ruby
|
20
|
+
|
21
|
+
ruby版本管理有两种方式 rvm 与 rbenv, 建议使用rbenv.
|
22
|
+
安装对应的ruby版本,建议使用2.7.5;并切换ruby版本到满足需求的版本。
|
23
|
+
|
24
|
+
- 安装ykfastlane
|
25
|
+
|
26
|
+
```shell
|
27
|
+
gem install ykfastlane
|
28
|
+
```
|
29
|
+
|
30
|
+
- 做基础配置
|
31
|
+
- 安装fastlane脚本
|
32
|
+
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
安装之后,使用 ykfastlane --help 查看使用说明, 功能分为 通用配置,证书管理,打包三部分。
|
36
|
+
|
37
|
+
### 基础配置
|
38
|
+
|
39
|
+
基础配置帮助指令
|
40
|
+
```shell
|
41
|
+
ykfastlane init --help
|
42
|
+
```
|
43
|
+
- 设置基础配置 -- ykfastlane init config
|
44
|
+
|
45
|
+
本指令集只是一个门户指令,核心打包功能是通过调用fastlane脚本来实现的。
|
46
|
+
|
47
|
+
配置:
|
48
|
+
- 配置fastlane脚本的远程仓库
|
49
|
+
|
50
|
+
此套fastlane脚本是配套脚本;考虑到github的访问问题,可将原始仓库代码迁移到gitlab仓库[^1]。[【原始仓库地址】](https://github.com/stephen5652/ykfastlane_scrip.git)
|
51
|
+
|
52
|
+
- 配置通知机器人
|
53
|
+
|
54
|
+
任务失败时候的,通过企业微信机器人通知开发者[^2]。[【企业微信机器人配置】](https://developer.work.weixin.qq.com/document/path/91770)
|
55
|
+
|
56
|
+
用例:
|
57
|
+
```shell
|
58
|
+
ykfastlane init config -f https://github.com/stephen5652/ykfastlane_scrip.git -t 5ef50d9f-6426-4c4c-94f8-xxxxxxxxxxxx
|
59
|
+
```
|
60
|
+
|
61
|
+
- 显示基础配置 -- ykfastlane init list_config
|
62
|
+
|
63
|
+
在终端打印基础配置的内容
|
64
|
+
|
65
|
+
用例
|
66
|
+
```shell
|
67
|
+
ykfastlane init list_config
|
68
|
+
```
|
69
|
+
|
70
|
+
- 同步fastlane脚本 -- ykfastlane init sync_script
|
71
|
+
|
72
|
+
同步远端fastlane脚本,此处可以通过参数下载固定的fastlan仓库,也可以使用环境配置的仓库来下载。
|
73
|
+
|
74
|
+
用例:
|
75
|
+
```shell
|
76
|
+
ykfastlane init sync_script
|
77
|
+
```
|
78
|
+
|
79
|
+
### 证书管理
|
80
|
+
|
81
|
+
iOS证书管理有多种方案:
|
82
|
+
|
83
|
+
> - 使用app store connect API进行管理;
|
84
|
+
> - 使用fastlane match 管理【适用于单账号】
|
85
|
+
> - 半手动管理
|
86
|
+
|
87
|
+
考虑到此平台是通用打包平台,且适用于多个Apple账号下的app打包,所以使用半自动管理证书的形式。
|
88
|
+
具体实施方案:
|
89
|
+
|
90
|
+
> - 账号管理员创建/维护签名证书和描述文件,并上传至证书仓库;
|
91
|
+
> - 开发者电脑,打包机同步证书仓库,并安装证书和描述文件;
|
92
|
+
> - 各个项目配置手动签名配置;
|
93
|
+
> - 打包平台依据项目签名配置,进行打包。
|
94
|
+
|
95
|
+
操作步骤:
|
96
|
+
|
97
|
+
- 管理员,开发者,打包机电脑配置证书仓库
|
98
|
+
|
99
|
+
指令集通过git仓库来维护证书。
|
100
|
+
|
101
|
+
指令
|
102
|
+
```shell
|
103
|
+
ykfastlane certificate edit_config -r http://xxx.xxx.com/xxx.git
|
104
|
+
```
|
105
|
+
|
106
|
+
指令集支持显示证书仓库配置
|
107
|
+
|
108
|
+
指令:
|
109
|
+
```shell
|
110
|
+
ykfastlane certificate list_config
|
111
|
+
```
|
112
|
+
|
113
|
+
- 管理员更新证书
|
114
|
+
|
115
|
+
使用脚本平台,更新证书,并推送至证书仓库
|
116
|
+
|
117
|
+
指令:
|
118
|
+
|
119
|
+
```shell
|
120
|
+
ykfastlane certificate update_cer -c /Users/xxx/xxx/xxxx.p12 -p xxxx
|
121
|
+
```
|
122
|
+
|
123
|
+
- 管理员更新描述文件
|
124
|
+
|
125
|
+
使用脚本平台,更新描述文件,并推送至证书仓库。
|
126
|
+
|
127
|
+
指令:
|
128
|
+
|
129
|
+
```shell
|
130
|
+
ykfastlane certificate update_profile -p /Users/xxx/xxx/xxx.mobileprovision
|
131
|
+
```
|
132
|
+
|
133
|
+
- 同步证书和描述文件
|
134
|
+
|
135
|
+
开发者,打包机通过平台同步证书仓库。
|
136
|
+
|
137
|
+
指令:
|
138
|
+
|
139
|
+
```shell
|
140
|
+
ykfastlane certificate sync-cer
|
141
|
+
```
|
142
|
+
|
143
|
+
- 显示证书和描述文件
|
144
|
+
|
145
|
+
指令集支持显示证书仓库中的证书和描述文件
|
146
|
+
|
147
|
+
指令:
|
148
|
+
|
149
|
+
```shell
|
150
|
+
ykfastlane certificate list_cers
|
151
|
+
```
|
152
|
+
|
153
|
+
- 缺点
|
154
|
+
|
155
|
+
此种形式的证书管理,也是存在缺点的。
|
156
|
+
|
157
|
+
缺点:
|
158
|
+
|
159
|
+
- 多个Apple账号的证书在同一个git仓库管理;
|
160
|
+
- 每台电脑都安装了所有Apple账号的证书和项目描述文件。
|
161
|
+
|
162
|
+
### 打包
|
163
|
+
|
164
|
+
指令集通过调用fastlane脚本进行打包,依据发不的平台,分为三种打包:fir平台,蒲公英平台,TF
|
165
|
+
|
166
|
+
- fir打包
|
167
|
+
|
168
|
+
- 打包指令帮助:
|
169
|
+
|
170
|
+
```shell
|
171
|
+
ykfastlane archive fire --help
|
172
|
+
```
|
173
|
+
|
174
|
+
- 使用方式
|
175
|
+
|
176
|
+
支持两种打包方式, 在.xcworkspace 路径打包 / 在其他目录打包。
|
177
|
+
|
178
|
+
> 在 .xcworkspace 同级打包
|
179
|
+
> ```shell
|
180
|
+
> ykfastlane archive fire -s XXXX -f xxxx -e enterprise -n "iOS测试包" -w xxxx
|
181
|
+
> ```
|
182
|
+
|
183
|
+
> 在其他目录打包:
|
184
|
+
由于.xcworkspace未必在git仓库根目录,所以可以用参数 -x 指定 .xcworkspace 的相对路径 </br>
|
185
|
+
如果终端工作路径在 .xcworkspace同级目录,则可以不使用参数 -x </br>
|
186
|
+
如果不用专门通知企业微信业务群,可以不指定 -w 参数,会默认使用env中配置的企微机器人。</br>
|
187
|
+
> ```shell
|
188
|
+
> ykfastlane archive fire -s XXXX -x ~/users/xxx/xxx/xxxx.xcworkspace -f xxxx -e enterprise -n "iOS测试包" -w xxxx
|
189
|
+
> ```
|
190
|
+
|
191
|
+
- 蒲公英打包
|
192
|
+
|
193
|
+
使用方式同 fir 打包
|
194
|
+
|
195
|
+
|
196
|
+
- TF打包
|
197
|
+
|
198
|
+
由于TF打包一定是app store包,所以此指令没有 -e 参数,无法指定包类型
|
199
|
+
- 打包指令帮助:
|
200
|
+
```shell
|
201
|
+
ykfastlane archive tf --help
|
202
|
+
```
|
203
|
+
|
204
|
+
- 使用方式
|
205
|
+
|
206
|
+
通用支持两种打包方式, 通过 -x 参数来指定 .xcworkspace 的路径
|
207
|
+
> 此处需要特别说明 -u -p -w -c 参数 </br>
|
208
|
+
-u 开发者的Apple ID </br>
|
209
|
+
-p 开发者Apple ID的App专属密钥[^3]。[【传送门】](https://appleid.apple.com/account/manage) </br>
|
210
|
+
-w 企微机器人,如果不指定,则默认使用env中配置的机器人。 </br>
|
211
|
+
-c 是否需要pod install, 默认不执行。
|
212
|
+
|
213
|
+
指令范例:
|
214
|
+
```shell
|
215
|
+
ykfastlane archive tf -s XXX -u xxxx.@xxx.com -p xxxx-xxxx-xxxx-xxxx -n iOS测试包 -w xxxxx -c 1
|
216
|
+
```
|
217
|
+
|
218
|
+
## 异常情况处理
|
219
|
+
|
220
|
+
- public_suffix 版本冲突
|
221
|
+
|
222
|
+
- 清空gem
|
223
|
+
|
224
|
+
```shell
|
225
|
+
gem clean
|
226
|
+
```
|
227
|
+
|
228
|
+
- 卸载 public_suffix
|
229
|
+
|
230
|
+
```shell
|
231
|
+
gem uninstall public_suffix
|
232
|
+
```
|
233
|
+
|
234
|
+
## License
|
235
|
+
|
236
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
237
|
+
|
238
|
+
[^1]:fastlane脚本原始仓库地址: https://github.com/stephen5652/ykfastlane_scrip.git
|
239
|
+
|
240
|
+
[^2]:企业微信机器人配置网址: https://developer.work.weixin.qq.com/document/path/91770
|
241
|
+
|
242
|
+
[^3]: 配置App专属密钥的网址: https://appleid.apple.com/account/manage
|
243
|
+
|
244
|
+
|
245
|
+
### 建议
|
246
|
+
|
247
|
+
fire-api-token 做全局配置
|
248
|
+
|
249
|
+
tf tag参数化,可以控制是否打tag
|
250
|
+
|
251
|
+
builde 号不交付苹果管理,指令集也不管理,交由工程配置
|
252
|
+
|
253
|
+
显示打包结果的存储路径
|
data/bin/ykfastlane
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
#
|
4
|
+
|
5
|
+
puts "call ykfastlane"
|
6
|
+
|
7
|
+
lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
|
8
|
+
$LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
|
9
|
+
|
10
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
11
|
+
# with your gem easier. You can also use a different console, if you like.
|
12
|
+
|
13
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
14
|
+
# require "pry"
|
15
|
+
# Pry.start
|
16
|
+
require 'interface'
|
17
|
+
puts "call ykfastlane:#{YKFastlane::VERSION}"
|
18
|
+
|
19
|
+
puts "ykfastlane start"
|
20
|
+
YKFastlane::Interface.start(ARGV)
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'rails'
|
2
|
+
require 'thor'
|
3
|
+
|
4
|
+
require "ykfastlane/helper"
|
5
|
+
|
6
|
+
module YKFastlane
|
7
|
+
|
8
|
+
class SubCommandBase < Thor
|
9
|
+
class_option :verbose, :type => :boolean
|
10
|
+
def self.exit_on_failure?
|
11
|
+
true
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.banner(command, namespace = nil, subcommand = false)
|
15
|
+
"#{basename} #{subcommand_prefix} #{command.usage}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.subcommand_prefix
|
19
|
+
self.name.gsub(%r{.*::}, '').gsub(%r{^[A-Z]}) { |match| match[0].downcase }.gsub(%r{[A-Z]}) { |match| "-#{match[0].downcase}" }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class YKFastlaneExecute
|
24
|
+
def self.executeCommand(commandShell_pre, commandShell, workTitle)
|
25
|
+
excuteStr = " "
|
26
|
+
excuteStr << "#{commandShell_pre} && " unless commandShell_pre.blank?
|
27
|
+
excuteStr << commandShell unless commandShell.blank?
|
28
|
+
|
29
|
+
puts "START COMMAND:#{excuteStr}"
|
30
|
+
code = 1
|
31
|
+
system(excuteStr)
|
32
|
+
result = $?
|
33
|
+
puts "command result[#{result.class}]:#{result}"
|
34
|
+
code = result.exitstatus if result.is_a?(Process::Status)
|
35
|
+
|
36
|
+
#### 以下代码注释,因为fastlane脚本中做了任务失败时候的通知
|
37
|
+
# if code != 0
|
38
|
+
# #任务失败, 此处需要发送企业微信的通知到开发群
|
39
|
+
# puts "should report error to developer group"
|
40
|
+
# noticeCmd = commandShell_pre
|
41
|
+
# commandShell = commandShell.gsub!( " ", "\\ " )
|
42
|
+
# commandShell = commandShell.gsub!( "\"", "\\\"")
|
43
|
+
# noticeCmd << "&&fastlane wx_message_notice wx_notice_token:#{Helper::YKWECHAT_ROBOT_TOKEN} msg_title:\"CI work failed\" notice_message:\"#{commandShell}\""
|
44
|
+
# puts "notice_command:#{noticeCmd}"
|
45
|
+
# system(noticeCmd)
|
46
|
+
# end
|
47
|
+
|
48
|
+
code
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.exchangOptionMapToStr(optionHash)
|
52
|
+
paras = {}
|
53
|
+
optionHash.each_pair { |k, v| paras[k] = v }
|
54
|
+
puts "paras:#{paras.dup}"
|
55
|
+
|
56
|
+
puts "YKRUNING_PATH:#{Helper::YKRUNING_PATH}"
|
57
|
+
workspace_path = Helper::YKRUNING_PATH
|
58
|
+
workspace_path = paras["xcworkspace"] unless paras["xcworkspace"].blank?
|
59
|
+
paras[:xcworkspace] = workspace_path
|
60
|
+
paras[:script_run_path] = Helper::YKRUNING_PATH
|
61
|
+
|
62
|
+
puts "options_after:#{paras}"
|
63
|
+
option_str = ""
|
64
|
+
paras.each_pair do |k, v|
|
65
|
+
option_str << " #{k}:\"#{v}\""
|
66
|
+
end
|
67
|
+
option_str
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.executeFastlaneLane(lane_name, optionHash)
|
71
|
+
if optionHash[:wxwork_access_token].blank?
|
72
|
+
wxtoken = YKFastlane::Helper.load_config_value(YKFastlane::Helper::K_wx_access_token)
|
73
|
+
optionHash[:wxwork_access_token] = wxtoken unless wxtoken.blank?
|
74
|
+
end
|
75
|
+
|
76
|
+
option_str = exchangOptionMapToStr(optionHash)
|
77
|
+
command = "bundle exec fastlane #{lane_name} #{option_str}" unless option_str.blank?
|
78
|
+
|
79
|
+
command_pre = "export LANG=en_US.UTF-8 && export LANGUAGE=en_US.UTF-8 && export LC_ALL=en_US.UTF-8 && which ruby"
|
80
|
+
command_pre << " && cd #{YKFastlane::Helper.fastlane_script()}"
|
81
|
+
|
82
|
+
executeCommand(command_pre, command, lane_name)
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
@@ -0,0 +1,152 @@
|
|
1
|
+
require "actions/YKFastlaneExecute"
|
2
|
+
require 'ykfastlane/version'
|
3
|
+
require 'ykfastlane/tools'
|
4
|
+
require 'ykfastlane/helper'
|
5
|
+
require 'actions/archiveHelper'
|
6
|
+
module YKFastlane
|
7
|
+
|
8
|
+
class Archive < YKFastlane::SubCommandBase
|
9
|
+
include YKFastlane::ArchiveHelper
|
10
|
+
|
11
|
+
desc "display_product_path", "display archive output path"
|
12
|
+
|
13
|
+
def display_product_path()
|
14
|
+
YKFastlane::Tools.UI(YKARCHIVE_PRODUCT_PATH)
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'platform_edit_user', "edit or update platform user"
|
18
|
+
option :pgyer_user, :type => :string, :aliases => :u, :required => true, :desc => 'pgyer 平台 user'
|
19
|
+
option :pgyer_api, :type => :string, :aliases => :a, :required => true, :desc => 'pgyer 平台 api, 配置链接: https://appleid.apple.com/account/manage'
|
20
|
+
option :fir_api_token, :type => :string, :aliases => :f, :required => true, :desc => 'fir 平台 api token'
|
21
|
+
option :apple_account, :type => :string, :aliases => :c, :required => true, :desc => 'apple id'
|
22
|
+
option :apple_password, :type => :string, :aliases => :p, :required => true, :desc => 'apple id 专属app密钥, 配置链接: https://appleid.apple.com/account/manage'
|
23
|
+
|
24
|
+
def platform_edit_user()
|
25
|
+
puts "archive platform_edit_user"
|
26
|
+
if options[:pgyer_user].blank? == false && options[:pgyer_api].blank? == false # pgyer
|
27
|
+
pgyerinfo = {
|
28
|
+
K_archiveEnv_pgyer_api => options[:pgyer_api],
|
29
|
+
K_archiveEnv_pgyer_user => options[:pgyer_user]
|
30
|
+
}
|
31
|
+
self.update_archive_map(YKFastlane::ArchiveHelper::K_archiveEnv_config_pgyer, pgyerinfo)
|
32
|
+
puts "archive update pgyer info success"
|
33
|
+
end
|
34
|
+
|
35
|
+
if options[:fir_api_token].blank? == false #fir
|
36
|
+
fir_info = {
|
37
|
+
K_archiveEnv_firApiToken => options[:fir_api_token]
|
38
|
+
}
|
39
|
+
self.update_archive_map(YKFastlane::ArchiveHelper::K_archiveEnv_config_fir, fir_info)
|
40
|
+
puts "archive update fir info success"
|
41
|
+
end
|
42
|
+
|
43
|
+
if options[:apple_password].blank? == false && options[:apple_password].blank? == false # tf
|
44
|
+
tf_info = {
|
45
|
+
K_archiveEnv_tf_account => options[:apple_account],
|
46
|
+
K_archiveEnv_tf_password => options[:apple_password]
|
47
|
+
}
|
48
|
+
self.update_archive_map(YKFastlane::ArchiveHelper::K_archiveEnv_config_tf, tf_info)
|
49
|
+
puts "archive update tf info success"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
desc "list_platform_user", "display the ipa bump platform user map"
|
54
|
+
|
55
|
+
def list_platform_user()
|
56
|
+
self.list_user_map()
|
57
|
+
end
|
58
|
+
|
59
|
+
desc "list_profiles", "print archive profiles info"
|
60
|
+
def list_profiles()
|
61
|
+
code = YKFastlaneExecute.executeFastlaneLane("list_profile_configs", options)
|
62
|
+
exit(code)
|
63
|
+
end
|
64
|
+
|
65
|
+
desc "upload_tf", "upload ipa to test flight, will send failed message to enterprise robot \'#{Helper::YKWECHAT_ROBOT_TOKEN}\'"
|
66
|
+
option :ipa, :required => true, :type => :string, :aliases => :i, :desc => 'scheme name'
|
67
|
+
option :user_name, :type => :string, :aliases => :u, :desc => 'apple id, 如果不传递,则使用env配置的'
|
68
|
+
option :pass_word, :type => :string, :aliases => :p, :desc => 'apple id 专属app密钥, 如果不传递,则使用env配置的 配置链接: https://appleid.apple.com/account/manage'
|
69
|
+
option :wxwork_access_token, :type => :string, :aliases => :t, :desc => '微信机器人token, 用以通知到相关业务群,如果没有, 则会使用配置中的机器人, 如果依旧没有, 则不通知企业微信,但是业务依旧成功'
|
70
|
+
option :note, :type => :string, :aliases => :n, :desc => '通知信息,用以通知相关业务群,如果没有,业务依旧成功'
|
71
|
+
|
72
|
+
def upload_tf()
|
73
|
+
puts "upload_tf"
|
74
|
+
if options[:user_name].blank? || options[:pass_word].blank?
|
75
|
+
apple_info = self.load_archive_config_dict(YKFastlane::ArchiveHelper::K_archiveEnv_config_tf)
|
76
|
+
options.update(apple_dict)
|
77
|
+
end
|
78
|
+
|
79
|
+
code = YKFastlaneExecute.executeFastlaneLane("upload_ipa_to_tf", options)
|
80
|
+
exit(code)
|
81
|
+
end
|
82
|
+
|
83
|
+
desc "tf", "archive ios project and upload to TF, will send failed message to enterprise robot \'#{Helper::YKWECHAT_ROBOT_TOKEN}\'"
|
84
|
+
option :scheme, :required => true, :type => :string, :aliases => :s, :desc => 'scheme name'
|
85
|
+
option :user_name, :type => :string, :aliases => :u, :desc => 'apple id, 如果不传递,则使用env配置的'
|
86
|
+
option :pass_word, :type => :string, :aliases => :p, :desc => 'apple id 专属app密钥, 如果不传递,则使用env配置的 配置链接: https://appleid.apple.com/account/manage'
|
87
|
+
|
88
|
+
option :wxwork_access_token, :type => :string, :aliases => :w, :desc => '企业微信机器人 webhook中的key字段, 如果没有,则使用env中配置的机器人'
|
89
|
+
option :note, :type => :string, :aliases => :n, :desc => '测试包发包信息'
|
90
|
+
option :xcworkspace, :type => :string, :aliases => :x, :desc => '.xcworkspace 文件相对于指令工作目录的相对路径, 如果.xcworkspace文件在工程根目录,则可以不传递此参数'
|
91
|
+
option :cocoapods, :type => :numeric, :aliases => :c, :desc => '是否需要执行pod install, 默认不执行pod install 指令, 1:执行, 非1:不执行'
|
92
|
+
option :flutter_directory, :type => :string, :aliases => :d, :desc => '如果有flutter混编, 此参数是 flutter项目的相对路径.'
|
93
|
+
|
94
|
+
def tf()
|
95
|
+
puts "archive_tf"
|
96
|
+
if options[:user_name].blank? || options[:pass_word].blank?
|
97
|
+
apple_dict = self.load_archive_config_dict(YKFastlane::ArchiveHelper::K_archiveEnv_config_tf)
|
98
|
+
if apple_dict != nil && apple_dict.blank?() == false
|
99
|
+
options.update(apple_dict)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
code = YKFastlaneExecute.executeFastlaneLane("archive_tf", options)
|
104
|
+
exit(code)
|
105
|
+
end
|
106
|
+
|
107
|
+
desc "pgyer", "archive ios project and upload to pgyer, will send failed message to enterprise robot \'#{Helper::YKWECHAT_ROBOT_TOKEN}\'"
|
108
|
+
option :scheme, :required => true, :type => :string, :aliases => :s, :desc => 'scheme name'
|
109
|
+
option :pgyer_api, :type => :string, :aliases => :a, :desc => '蒲公英平台的api key; 如果不传,会使用全局配置的 api key'
|
110
|
+
option :pgyer_user, :type => :string, :aliases => :u, :desc => '蒲公英平台的user key; 如果不传,会使用全局配置的 user key'
|
111
|
+
option :wxwork_access_token, :type => :string, :aliases => :w, :desc => '企业微信机器人 webhook中的key字段, 如果没有,则使用env中配置的机器人'
|
112
|
+
option :note, :type => :string, :aliases => :n, :desc => '测试包发包信息'
|
113
|
+
option :xcworkspace, :type => :string, :aliases => :x, :desc => '.xcworkspace 文件相对于指令工作目录的相对路径, 如果.xcworkspace文件在工程根目录,则可以不传递此参数'
|
114
|
+
option :cocoapods, :type => :numeric, :aliases => :c, :desc => '是否需要执行pod install, 默认不执行pod install 指令, 1:执行, 非1:不执行'
|
115
|
+
option :flutter_directory, :type => :string, :aliases => :d, :desc => '如果有flutter混编, 此参数是 flutter项目的相对路径.'
|
116
|
+
option :export, :type => :string, :aliases => :e, :desc => '包的类型, app-store, validation,ad-hoc, package, enterprise, development, developer-id, mac-application, 默认为enterprise'
|
117
|
+
|
118
|
+
def pgyer()
|
119
|
+
puts "archive_pgyer"
|
120
|
+
|
121
|
+
if options[:pgyer_user].blank? || options[:pgyer_api].blank?
|
122
|
+
dict = self.load_archive_config_dict(YKFastlane::ArchiveHelper::K_archiveEnv_config_pgyer)
|
123
|
+
options.update(dict)
|
124
|
+
end
|
125
|
+
|
126
|
+
code = YKFastlaneExecute.executeFastlaneLane("archive_pgyer", options)
|
127
|
+
exit(code)
|
128
|
+
end
|
129
|
+
|
130
|
+
desc "fir", "archive ios project and upload to fir, will send failed message to enterprise robot \'#{Helper::YKWECHAT_ROBOT_TOKEN}\'"
|
131
|
+
option :scheme, :required => true, :type => :string, :aliases => :s, :desc => 'scheme name'
|
132
|
+
option :fir_api_token, :type => :string, :aliases => :f, :desc => 'Fir平台api token'
|
133
|
+
option :wxwork_access_token, :type => :string, :aliases => :w, :desc => '企业微信机器人 webhook中的key字段, 如果没有,则使用env中配置的机器人'
|
134
|
+
option :note, :type => :string, :aliases => :n, :desc => '测试包发包信息'
|
135
|
+
option :xcworkspace, :type => :string, :aliases => :x, :desc => '.xcworkspace 文件相对于指令工作目录的相对路径, 如果.xcworkspace文件在工程根目录,则可以不传递此参数'
|
136
|
+
option :cocoapods, :type => :numeric, :aliases => :c, :desc => '是否需要执行pod install, 默认不执行pod install 指令, 1:执行, 非1:不执行'
|
137
|
+
option :flutter_directory, :type => :string, :aliases => :d, :desc => '如果有flutter混编, 此参数是 flutter项目的相对路径.'
|
138
|
+
option :export, :type => :string, :aliases => :e, :desc => '包的类型, 包的类型, app-store, validation,ad-hoc, package, enterprise, development, developer-id, mac-application, 默认为enterprise'
|
139
|
+
|
140
|
+
def fir()
|
141
|
+
puts "archive_fir"
|
142
|
+
if options[:fir_api_token].blank?
|
143
|
+
dict = self.load_archive_config_dict(YKFastlane::ArchiveHelper::K_archiveEnv_config_fir)
|
144
|
+
options.update(dict)
|
145
|
+
end
|
146
|
+
|
147
|
+
code = YKFastlaneExecute.executeFastlaneLane("archive_fir", options)
|
148
|
+
exit(code)
|
149
|
+
end
|
150
|
+
|
151
|
+
end
|
152
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'ykfastlane/version'
|
2
|
+
require 'ykfastlane/tools'
|
3
|
+
require 'ykfastlane/helper'
|
4
|
+
module YKFastlane
|
5
|
+
|
6
|
+
module ArchiveHelper
|
7
|
+
YKARCHIVE_PRODUCT_PATH = File.expand_path(File.join(Dir.home, "iosYeahArchive"))
|
8
|
+
|
9
|
+
YKARCHIVE_ENV_PATH = File.join(YKFastlane::YKFASTLANE_ENV_PATH, 'archive_config', 'archive_config.yml')
|
10
|
+
|
11
|
+
K_archiveEnv_config_tf = :test_flight
|
12
|
+
K_archiveEnv_tf_account = :user_name
|
13
|
+
K_archiveEnv_tf_password = :pass_word
|
14
|
+
|
15
|
+
K_archiveEnv_config_fir = :fir
|
16
|
+
K_archiveEnv_firApiToken = :fir_api_token
|
17
|
+
|
18
|
+
K_archiveEnv_config_pgyer = :pgyer
|
19
|
+
K_archiveEnv_pgyer_user = :pgyer_user
|
20
|
+
K_archiveEnv_pgyer_api = :pgyer_api
|
21
|
+
|
22
|
+
def self.update_archive_map(key, value)
|
23
|
+
YKFastlane::Tools.update_yml("", YKARCHIVE_ENV_PATH, key, value)
|
24
|
+
end
|
25
|
+
|
26
|
+
def update_archive_map(key, value)
|
27
|
+
YKFastlane::Tools.update_yml("", YKARCHIVE_ENV_PATH, key, value)
|
28
|
+
end
|
29
|
+
|
30
|
+
def load_archive_config_dict(platform_name)
|
31
|
+
dict = YKFastlane::Tools.load_yml_value(YKARCHIVE_ENV_PATH, platform_name)
|
32
|
+
return dict == nil ? {} : dict
|
33
|
+
end
|
34
|
+
|
35
|
+
def list_user_map()
|
36
|
+
YKFastlane::Tools.display_yml(YKARCHIVE_ENV_PATH)
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'actions/YKFastlaneExecute'
|
2
|
+
require 'ykfastlane/helper'
|
3
|
+
require 'thor'
|
4
|
+
require 'openssl'
|
5
|
+
|
6
|
+
module YKFastlane
|
7
|
+
class Certificate < YKFastlane::SubCommandBase
|
8
|
+
|
9
|
+
desc "sync_apple_profile", "sync and install mobile provision file from apple developer service"
|
10
|
+
option :user_name, :require => true, :type => :string, :aliases => :u, :desc => 'apple account'
|
11
|
+
option :password, :require => true, :type => :string, :aliases => :p, :desc => 'apple account password'
|
12
|
+
option :workspace, :require => false, :type => :string, :aliases => :w, :desc => 'p12 password'
|
13
|
+
option :bundle_ids, :require => false, :type => :array, :aliases => :b, :desc => "bundle identifier arr, separate by \" \" once more than one, exaple: 123 456 234"
|
14
|
+
|
15
|
+
def sync_apple_profile()
|
16
|
+
puts "options:#{options}"
|
17
|
+
arr = options[:bundle_ids]
|
18
|
+
if arr != nil && arr.count > 0
|
19
|
+
str = arr.join(",")
|
20
|
+
options[:bundle_ids] = str
|
21
|
+
end
|
22
|
+
|
23
|
+
if options[:workspace].blank? == false
|
24
|
+
Dir.chdir(Dir.pwd) do
|
25
|
+
options[:workspace] = File.expand_path(options[:workspace])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
puts "options_formatter:#{options}"
|
30
|
+
code = YKFastlaneExecute.executeFastlaneLane("sync_apple_profile", options)
|
31
|
+
exit! code
|
32
|
+
end
|
33
|
+
|
34
|
+
desc "update_profile", "Update one profile"
|
35
|
+
option :profile_path, :require => true, :type => :array, :aliases => :p, :desc => 'profile path'
|
36
|
+
|
37
|
+
def update_profile()
|
38
|
+
result_arr = []
|
39
|
+
arr = options[:profile_path]
|
40
|
+
if arr != nil && arr.count > 0
|
41
|
+
Dir.chdir(Dir.pwd) do
|
42
|
+
arr.each do |one|
|
43
|
+
path = File.expand_path(one)
|
44
|
+
result_arr << path
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
str = result_arr.join(",")
|
50
|
+
options[:profile_path] = str unless str.blank?
|
51
|
+
puts "options:#{options}"
|
52
|
+
code = YKFastlaneExecute.executeFastlaneLane("update_profiles", options)
|
53
|
+
exit! code
|
54
|
+
end
|
55
|
+
|
56
|
+
desc "update_cer", "edit certificate & profile for project schem or target"
|
57
|
+
option :cer_password, :require => true, :type => :string, :aliases => :p, :desc => 'p12 password'
|
58
|
+
option :cer_path, :require => true, :type => :string, :aliases => :c, :desc => 'p12 path'
|
59
|
+
|
60
|
+
def update_cer()
|
61
|
+
puts "options:#{options}"
|
62
|
+
|
63
|
+
para = {}
|
64
|
+
Dir.chdir(Dir.pwd) do
|
65
|
+
para[:cer_path] = File.expand_path(options[:cer_path]) unless options[:cer_path].blank?
|
66
|
+
end
|
67
|
+
|
68
|
+
para[:password] = options[:cer_password]
|
69
|
+
|
70
|
+
code = YKFastlaneExecute.executeFastlaneLane("update_certificate_p12", para)
|
71
|
+
exit! code
|
72
|
+
end
|
73
|
+
|
74
|
+
desc "sync_git", "sync certificate & profile git, and will overwrite the existed files once pass the remote_url"
|
75
|
+
option :remote_url, :require => false, :type => :string, :aliases => :r, :desc => "git remote url, example:#{YKFastlane::Helper.default_certificate_git_remote}"
|
76
|
+
|
77
|
+
def sync_git()
|
78
|
+
puts "#{method(:sync_git)}--options:#{options}"
|
79
|
+
code = YKFastlaneExecute.executeFastlaneLane("sync_certificate_profile", options)
|
80
|
+
exit! code
|
81
|
+
end
|
82
|
+
|
83
|
+
desc "list_details", "list certificate details"
|
84
|
+
|
85
|
+
def list_details()
|
86
|
+
puts("certificate list_details")
|
87
|
+
code = YKFastlaneExecute.executeFastlaneLane("list_profile_certificate_config", options)
|
88
|
+
exit! code
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
data/lib/actions/init.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'git'
|
2
|
+
require 'yaml'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
require 'actions/YKFastlaneExecute'
|
6
|
+
require 'actions/archiveHelper'
|
7
|
+
|
8
|
+
module YKFastlane
|
9
|
+
class Init < YKFastlane::SubCommandBase
|
10
|
+
include Helper
|
11
|
+
|
12
|
+
desc "sync_script", "sync fast file from the remote"
|
13
|
+
long_desc <<-LONGDESC
|
14
|
+
同步远端fastlane脚本,此处可以通过参数下载固定的fastlan仓库,也可以使用环境配置的仓库来下载。
|
15
|
+
LONGDESC
|
16
|
+
option :fastfile_remote, :aliases => :f, :type => :string, :desc => "fastlane 文件仓库地址, 如果未传递,则使用env中配置的,#{Helper::YKCONFIG_PATH}"
|
17
|
+
|
18
|
+
def sync_script()
|
19
|
+
fastfile_remote = options[:fastfile_remote].blank? ? Helper::load_config_value(Helper::K_fastfile_remote) : options[:fastfile_remote]
|
20
|
+
|
21
|
+
if fastfile_remote.blank?
|
22
|
+
puts "no remote, work failed"
|
23
|
+
exit false
|
24
|
+
end
|
25
|
+
|
26
|
+
p = Helper::YKFastlne_SCRIPT_PATH
|
27
|
+
p_temp = p + "_temp"
|
28
|
+
FileUtils.remove_dir(p_temp, force: true)
|
29
|
+
|
30
|
+
cloneResult = YKFastlane::Tools.clone_git_repository(fastfile_remote, p_temp)
|
31
|
+
if cloneResult != 0
|
32
|
+
exit cloneResult
|
33
|
+
end
|
34
|
+
|
35
|
+
if Dir.exist?(p)
|
36
|
+
puts "directory exist, so we delete it:#{p}"
|
37
|
+
FileUtils.remove_dir(p, true)
|
38
|
+
end
|
39
|
+
|
40
|
+
if File.exist?(File.dirname(p)) == false
|
41
|
+
FileUtils.mkdir_p(File.dirname(p))
|
42
|
+
end
|
43
|
+
FileUtils.mv(p_temp, p, force: true, verbose: true)
|
44
|
+
|
45
|
+
Dir.chdir(p) do
|
46
|
+
system("bundle install --verbose")
|
47
|
+
end
|
48
|
+
return 0
|
49
|
+
end
|
50
|
+
|
51
|
+
desc 'config', "update configuration file: #{Helper::YKCONFIG_PATH}"
|
52
|
+
long_desc <<-LONGDESC
|
53
|
+
本指令集只是一个门户指令,核心打包功能是通过调用fastlane脚本来实现的。
|
54
|
+
需要配置: 1.配置fastlane脚本的远程仓库; 2.配置任务失败时候的反馈企业微信机器人, [【企业微信机器人配置】](https://developer.work.weixin.qq.com/document/path/91770)
|
55
|
+
LONGDESC
|
56
|
+
option :fastfile_remote, :aliases => :f, :type => :string, :desc => "fastlane 文件的git remote, 可用参数:#{Helper.default_fast_file_remote()}"
|
57
|
+
option :wx_access_token, :aliases => :t, :type => :string, :desc => "enterprise wechat robot token"
|
58
|
+
|
59
|
+
def config()
|
60
|
+
puts "options:#{options}"
|
61
|
+
Helper.update_config('', Helper::K_fastfile_remote, options[:fastfile_remote]) unless options[:fastfile_remote].blank?
|
62
|
+
Helper.update_config('', Helper::K_wx_access_token, options[:wx_access_token]) unless options[:wx_access_token].blank?
|
63
|
+
YKFastlane::ArchiveHelper.update_archive_map(Helper::K_wx_access_token, options[:wx_access_token]) unless options[:wx_access_token].blank?
|
64
|
+
Helper.display_config_yml
|
65
|
+
end
|
66
|
+
|
67
|
+
desc 'define_fast_execute_path', "指定fastlane文件的路径,此处是为了调试fastlane脚本"
|
68
|
+
option :debug_flag, :aliases => :d, :type => :string, :require => true, :desc => "运行调试脚本的开关, 1:运行调试脚本, 其他:运行默认脚本"
|
69
|
+
option :fastfile_path, :aliases => :e, :type => :string, :desc => "运行的fastlane 文件的路径,此处是为了调试"
|
70
|
+
|
71
|
+
def define_fast_execute_path()
|
72
|
+
Helper.update_config("debug flag", Helper::K_YK_CONFIG_FASTLANE_DEBUG, options[:debug_flag] ? options[:debug_flag] : 0)
|
73
|
+
Helper.update_config("execute path", Helper::K_YK_CONFIG_FASTLANE_SCRIPT, options[:fastfile_path].blank? ? "" : options[:fastfile_path])
|
74
|
+
end
|
75
|
+
|
76
|
+
desc "list_config", "print the env config file: #{Helper::YKCONFIG_PATH}"
|
77
|
+
|
78
|
+
def list_config()
|
79
|
+
Helper.display_config_yml
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
data/lib/actions/pod.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'actions/YKFastlaneExecute'
|
2
|
+
require 'ykfastlane/helper'
|
3
|
+
require 'rails'
|
4
|
+
|
5
|
+
module YKFastlane
|
6
|
+
class Pod < YKFastlane::SubCommandBase
|
7
|
+
desc 'github_transfer', '迁移github三方库到移开gitlab.'
|
8
|
+
long_desc <<-LONGDESC
|
9
|
+
1. 需要在移开gitlab创建一个同名的git仓库.
|
10
|
+
2. 尝试迁移所有tag, 当碰到迁移失败的tag的时候,并不会导致整个迁移的失败;
|
11
|
+
3. 最终会输出迁移成功的数组和失败的数组
|
12
|
+
LONGDESC
|
13
|
+
option :orignal_url, :aliases => :o, :required => true, :type => :string, :desc => '原始源码仓库'
|
14
|
+
option :ykgitlab_url, :aliases => :d, :required => true, :type => :string, :desc => '迁移的目标仓库'
|
15
|
+
option :versions, :aliases => :s, :type => :string, :desc => '迁移的目标版本,多个的时候用空格\' \'隔开, 默认遍历尝试迁移所有的版本,比较耗时'
|
16
|
+
option :wxwork_access_token, :aliases => :w, :type => :string, :desc => '用于将任务结果传给企业微信'
|
17
|
+
|
18
|
+
def github_transfer()
|
19
|
+
puts "github_pod_transfer"
|
20
|
+
if options[:wxwork_access_token].blank?
|
21
|
+
wxtoken = YKFastlane::Helper.load_config_value(YKFastlane::Helper::K_wx_access_token)
|
22
|
+
options[:wxwork_access_token] = wxtoken unless wxtoken.blank?
|
23
|
+
end
|
24
|
+
|
25
|
+
code = Ykfastlane::YKFastlaneExecute.executeFastlaneLane("github_pod_transfer", options)
|
26
|
+
exit(code)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/interface.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ykfastlane/version'
|
4
|
+
|
5
|
+
require 'actions/YKFastlaneExecute'
|
6
|
+
require 'actions/archive'
|
7
|
+
require 'actions/pod'
|
8
|
+
require 'actions/init'
|
9
|
+
require 'actions/certificate'
|
10
|
+
require 'thor'
|
11
|
+
|
12
|
+
module YKFastlane
|
13
|
+
class Interface < Thor
|
14
|
+
include Thor::Actions
|
15
|
+
|
16
|
+
class_option :verbose, :type => :boolean
|
17
|
+
def self.exit_on_failure?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "lanes", 'list all lanes'
|
22
|
+
|
23
|
+
def lanes()
|
24
|
+
puts "lanes"
|
25
|
+
code = YKFastlane::YKFastlaneExecute.executeFastlaneLane("lanes", options)
|
26
|
+
exit(code)
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "archive", "archive functions"
|
30
|
+
subcommand "archive", YKFastlane::Archive
|
31
|
+
|
32
|
+
desc "pod", "cocoapods functions"
|
33
|
+
subcommand "pod", YKFastlane::Pod
|
34
|
+
|
35
|
+
desc "init", "init ykfastlane"
|
36
|
+
subcommand "init", YKFastlane::Init
|
37
|
+
|
38
|
+
desc "certificate", "manager ios certificate & profile files"
|
39
|
+
subcommand "certificate", YKFastlane::Certificate
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'json'
|
3
|
+
require 'ykfastlane/tools'
|
4
|
+
require 'ykfastlane/version'
|
5
|
+
module YKFastlane
|
6
|
+
module Helper
|
7
|
+
include YKFastlane::Tools
|
8
|
+
'' '脚本当前工作路径' ''
|
9
|
+
YKRUNING_PATH = File.expand_path(Dir.pwd)
|
10
|
+
'' '配置文件放置路径' ''
|
11
|
+
YKCONFIG_PATH = File.expand_path(File.join(YKFastlane::YKFASTLANE_ENV_PATH, 'evnConfig.yml'))
|
12
|
+
|
13
|
+
'' 'fastlane脚本放置路径' ''
|
14
|
+
YKFastlne_SCRIPT_PATH = File.expand_path(File.join(YKFastlane::YKFASTLANE_ENV_PATH, 'ykfastlane_script'))
|
15
|
+
|
16
|
+
def self.load_config_yml()
|
17
|
+
Tools.load_yml(Helper::YKCONFIG_PATH)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.display_config_yml()
|
21
|
+
Tools.display_yml(Helper::YKCONFIG_PATH)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.load_config_value(key)
|
25
|
+
Tools.load_yml_value(Helper::YKCONFIG_PATH, key)
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.update_config(qustion, key, value)
|
29
|
+
Tools.update_yml(qustion, Helper::YKCONFIG_PATH, key, value)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.default_git_domain()
|
33
|
+
p0 = "http://gitlab."
|
34
|
+
p1 = "y"
|
35
|
+
p2 = 'ea'
|
36
|
+
p3 = "h"
|
37
|
+
p4 = "ka"
|
38
|
+
p5 = ".com"
|
39
|
+
p0 + p1 + p2 + p3 + p4 + p5
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.default_fast_file_remote()
|
43
|
+
url1 = "#{self.default_git_domain}/App/iOS/ykfastlane.git"
|
44
|
+
url2 = "https://github.com/stephen5652/ykfastlane_scrip.git"
|
45
|
+
"" "
|
46
|
+
\033[0;32m#{url1}\e[0m or \033[0;32m#{url2}\e[0m
|
47
|
+
" ""
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.default_certificate_git_remote()
|
51
|
+
url = "#{self.default_git_domain}/App/iOS/certificates/YKCertificateProfiles.git"
|
52
|
+
"" "
|
53
|
+
\033[0;32m#{url}\e[0m
|
54
|
+
" ""
|
55
|
+
end
|
56
|
+
|
57
|
+
'' ' 配置文件key-fastfile_remote' ''
|
58
|
+
K_fastfile_remote = :fastfile_remote
|
59
|
+
|
60
|
+
'' ' 配置文件key-wx_access_token' ''
|
61
|
+
K_wx_access_token = :wx_access_token
|
62
|
+
|
63
|
+
'' '企业微信CI机器人' ''
|
64
|
+
YKWECHAT_ROBOT_TOKEN = Helper.load_config_value(Helper::K_wx_access_token)
|
65
|
+
|
66
|
+
'' 'fastlane脚本路径' ''
|
67
|
+
K_YK_CONFIG_FASTLANE_SCRIPT = :fast_file
|
68
|
+
'' 'fastlane debug开关' ''
|
69
|
+
K_YK_CONFIG_FASTLANE_DEBUG = :fast_file_debug
|
70
|
+
|
71
|
+
def self.fastlane_script
|
72
|
+
path = Helper.load_config_value(K_YK_CONFIG_FASTLANE_SCRIPT)
|
73
|
+
debug = Helper.load_config_value(K_YK_CONFIG_FASTLANE_DEBUG)
|
74
|
+
puts "path:#{path}"
|
75
|
+
puts "debug flag[#{debug.class}]:#{debug}"
|
76
|
+
if path.blank? || debug.blank? || debug != "1"
|
77
|
+
path = YKFastlne_SCRIPT_PATH
|
78
|
+
end
|
79
|
+
puts "fastlane file path:#{path}"
|
80
|
+
path
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module YKFastlane
|
5
|
+
|
6
|
+
module Tools
|
7
|
+
def self.green(string)
|
8
|
+
"\033[0;32m#{string}\e[0m"
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.UI(string)
|
12
|
+
puts(self.green(string))
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.show_prompt
|
16
|
+
print green(">")
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.yk_ask(question)
|
20
|
+
answer = ""
|
21
|
+
loop do
|
22
|
+
puts "\n#{question}?"
|
23
|
+
show_prompt()
|
24
|
+
answer = STDIN.gets.chomp
|
25
|
+
|
26
|
+
break if answer.length > 0
|
27
|
+
|
28
|
+
print "\nYou need to provide an answer."
|
29
|
+
end
|
30
|
+
puts "answier:#{answer}"
|
31
|
+
answer
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.yk_ask_with_answers(question, possible_answers)
|
35
|
+
print "\n#{question}? ["
|
36
|
+
print_info = Proc.new {
|
37
|
+
possible_answers_string = possible_answers.each_with_index do |answer, i|
|
38
|
+
_answer = (i == 0) ? answer.underlined : answer
|
39
|
+
print " " + _answer
|
40
|
+
print(" /") if i != possible_answers.length - 1
|
41
|
+
end
|
42
|
+
print " ]\n"
|
43
|
+
}
|
44
|
+
print_info.call
|
45
|
+
|
46
|
+
answer = ""
|
47
|
+
loop do
|
48
|
+
show_prompt()
|
49
|
+
answer = STDIN.gets.chomp
|
50
|
+
|
51
|
+
answer = "yes" if answer == "y"
|
52
|
+
answer = "no" if answer == "n"
|
53
|
+
|
54
|
+
# default to first answer
|
55
|
+
if answer == ""
|
56
|
+
answer = possible_answers[0].downcase
|
57
|
+
print answer.yellow
|
58
|
+
end
|
59
|
+
|
60
|
+
break if possible_answers.map { |a| a.downcase }.include? answer
|
61
|
+
|
62
|
+
print "\nPossible answers are ["
|
63
|
+
print_info.call
|
64
|
+
end
|
65
|
+
|
66
|
+
answer
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.load_yml(path)
|
70
|
+
if File.exist?(path) == false
|
71
|
+
FileUtils.makedirs(File.dirname(path))
|
72
|
+
File.new(path, 'w+')
|
73
|
+
end
|
74
|
+
|
75
|
+
f = File.open(path)
|
76
|
+
yml = YAML.load(f, symbolize_names: false)
|
77
|
+
f.close
|
78
|
+
yml = {} if yml == false #空yml的时候, yml = false
|
79
|
+
yml
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.display_yml(path)
|
83
|
+
puts Tools::green(JSON.pretty_generate(load_yml(path)))
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.load_yml_value(path, key)
|
87
|
+
yml = load_yml(path)
|
88
|
+
yml = {} if yml == false #空yml的时候, yml = false
|
89
|
+
re = yml[key].blank? ? nil : yml[key]
|
90
|
+
re
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.update_yml(qustion, path, key, value)
|
94
|
+
yml = load_yml(path)
|
95
|
+
|
96
|
+
updateFlag = :yes
|
97
|
+
if value.blank? #外部未传该参数需要通过问答形式,获取该参数
|
98
|
+
value = Tools.yk_ask("please input #{Tools::green(qustion)}")
|
99
|
+
|
100
|
+
if yml[key].blank? == false #需要确认修改
|
101
|
+
puts "#{key} existed:#{yml[key]}"
|
102
|
+
updateFlag = Tools.yk_ask_with_answers("Are you sure to update #{self.green(qustion)}", ["Yes", "No"]).to_sym
|
103
|
+
end
|
104
|
+
end
|
105
|
+
yml[key] = value unless updateFlag != :yes
|
106
|
+
c_path = Helper::YKCONFIG_PATH
|
107
|
+
f = File.open(path, "w+")
|
108
|
+
YAML.dump(yml, f, symbolize_names: false)
|
109
|
+
f.close
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.over_write_yml_dict(path, dict)
|
113
|
+
f = File.open(path, "w+")
|
114
|
+
YAML.dump(dict, f, symbolize_names: false)
|
115
|
+
f.close
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.clone_git_repository(remote, destinationPath)
|
119
|
+
begin
|
120
|
+
puts "start clone:#{remote}"
|
121
|
+
cloneResult = Git::clone(remote, destinationPath, :log => Logger.new(Logger::Severity::INFO))
|
122
|
+
puts "clone_result:#{cloneResult}"
|
123
|
+
rescue Git::GitExecuteError => e
|
124
|
+
puts "clone failed:#{e}"
|
125
|
+
return 1 #任务失败
|
126
|
+
end
|
127
|
+
return 0
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.git_pull(path)
|
131
|
+
begin
|
132
|
+
git = Git::open(path)
|
133
|
+
git.add()
|
134
|
+
git.reset_hard()
|
135
|
+
curbranch = git.current_branch
|
136
|
+
git.pull('origin', curbranch)
|
137
|
+
rescue Git::GitExecuteError => e
|
138
|
+
puts "pull remote failed:#{e}"
|
139
|
+
return 1 #任务失败
|
140
|
+
end
|
141
|
+
|
142
|
+
return 0
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.git_commit(path, msg)
|
146
|
+
git = Git::open(path)
|
147
|
+
git.add()
|
148
|
+
curbranch = git.current_branch
|
149
|
+
begin
|
150
|
+
git.commit("update:#{msg}")
|
151
|
+
rescue Git::GitExecuteError => e
|
152
|
+
puts "commit update execption:#{e}"
|
153
|
+
end
|
154
|
+
|
155
|
+
status = git.status()
|
156
|
+
if status.untracked.count != 0 || status.changed.count != 0
|
157
|
+
puts "git not clean, work failed"
|
158
|
+
return 1
|
159
|
+
else
|
160
|
+
puts "git clean, work success"
|
161
|
+
git.push('origin', curbranch)
|
162
|
+
return 0
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def self.notify_message_to_enterprise_wechat(msg, status)
|
167
|
+
puts "should send failed message to enterprise wechat:\"#{self.green(msg)}\""
|
168
|
+
exit!(status) unless status == 0
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
end
|
metadata
ADDED
@@ -0,0 +1,183 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ykfastlane
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.9
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- stephen.chen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-10-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: git
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thor
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: yaml
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: security
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: openssl
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: json
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: plist
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: public_suffix
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "<"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: 5.0.0
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "<"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: 5.0.0
|
139
|
+
description: 基于fastlane的 iOS 打包工具.
|
140
|
+
email:
|
141
|
+
- stephen5652@126.com
|
142
|
+
executables:
|
143
|
+
- ykfastlane
|
144
|
+
extensions: []
|
145
|
+
extra_rdoc_files: []
|
146
|
+
files:
|
147
|
+
- LICENSE.txt
|
148
|
+
- README.md
|
149
|
+
- bin/ykfastlane
|
150
|
+
- lib/actions/YKFastlaneExecute.rb
|
151
|
+
- lib/actions/archive.rb
|
152
|
+
- lib/actions/archiveHelper.rb
|
153
|
+
- lib/actions/certificate.rb
|
154
|
+
- lib/actions/init.rb
|
155
|
+
- lib/actions/pod.rb
|
156
|
+
- lib/interface.rb
|
157
|
+
- lib/ykfastlane/helper.rb
|
158
|
+
- lib/ykfastlane/tools.rb
|
159
|
+
- lib/ykfastlane/version.rb
|
160
|
+
homepage: https://github.com/stephen5652/ykfastlane.git
|
161
|
+
licenses:
|
162
|
+
- MIT
|
163
|
+
metadata: {}
|
164
|
+
post_install_message:
|
165
|
+
rdoc_options: []
|
166
|
+
require_paths:
|
167
|
+
- lib
|
168
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
169
|
+
requirements:
|
170
|
+
- - ">="
|
171
|
+
- !ruby/object:Gem::Version
|
172
|
+
version: 2.6.0
|
173
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
174
|
+
requirements:
|
175
|
+
- - ">="
|
176
|
+
- !ruby/object:Gem::Version
|
177
|
+
version: '0'
|
178
|
+
requirements: []
|
179
|
+
rubygems_version: 3.1.6
|
180
|
+
signing_key:
|
181
|
+
specification_version: 4
|
182
|
+
summary: iOS 打包工具.
|
183
|
+
test_files: []
|