ykfastlane 0.3.12
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +253 -0
- data/bin/ykfastlane +20 -0
- data/lib/actions/YKFastlaneExecute.rb +89 -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 +43 -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: e06f98bcfa28e321039c0dd5286884f0df2c68e3524c000c613dcd77cb1a0735
|
4
|
+
data.tar.gz: b8efb63fbf7bb0133e54c496ba5963d3a565ae228a1d1e33c360182500f0480f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1697f0ff64666028c08fb9cc6a2e2e6ced80516c013fabce2d619c47135eb6ae0288a763abd4fcd34fc630db5b5a890ea09b83c00930b260fd986e9fb9ae227c
|
7
|
+
data.tar.gz: fbb93bf62301a2774171ae82b0bf0c20f3e974b2c5ec6d2ca3355eb0f40f25325111427663e03f1105483b1534b044947428b9c58cf727deb6ffffa0233f0dd6
|
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,89 @@
|
|
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
|
+
dict = {}
|
72
|
+
dict.update(optionHash)
|
73
|
+
if dict[:wxwork_access_token].blank?
|
74
|
+
wxtoken = YKFastlane::Helper.load_config_value(YKFastlane::Helper::K_wx_access_token)
|
75
|
+
dict.update({:wxwork_access_token => wxtoken})
|
76
|
+
end
|
77
|
+
|
78
|
+
option_str = exchangOptionMapToStr(dict)
|
79
|
+
command = "bundle exec fastlane #{lane_name} #{option_str}" unless option_str.blank?
|
80
|
+
|
81
|
+
command_pre = "export LANG=en_US.UTF-8 && export LANGUAGE=en_US.UTF-8 && export LC_ALL=en_US.UTF-8 && which ruby"
|
82
|
+
command_pre << " && cd #{YKFastlane::Helper.fastlane_script()}"
|
83
|
+
|
84
|
+
executeCommand(command_pre, command, lane_name)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
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 => false, :desc => 'pgyer 平台 user'
|
19
|
+
option :pgyer_api, :type => :string, :aliases => :a, :required => false, :desc => 'pgyer 平台 api, 配置链接: https://appleid.apple.com/account/manage'
|
20
|
+
option :fir_api_token, :type => :string, :aliases => :f, :required => false, :desc => 'fir 平台 api token'
|
21
|
+
option :apple_account, :type => :string, :aliases => :c, :required => false, :desc => 'apple id'
|
22
|
+
option :apple_password, :type => :string, :aliases => :p, :required => false, :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,43 @@
|
|
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
|
+
require_relative 'actions/YKFastlaneExecute'
|
16
|
+
include YKFastlane::Helper
|
17
|
+
|
18
|
+
class_option :verbose, :type => :boolean
|
19
|
+
def self.exit_on_failure?
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "lanes", 'list all lanes'
|
24
|
+
|
25
|
+
def lanes()
|
26
|
+
puts "lanes"
|
27
|
+
code = YKFastlane::YKFastlaneExecute.executeFastlaneLane("lanes", options)
|
28
|
+
exit(code)
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "archive", "archive functions"
|
32
|
+
subcommand "archive", YKFastlane::Archive
|
33
|
+
|
34
|
+
desc "pod", "cocoapods functions"
|
35
|
+
subcommand "pod", YKFastlane::Pod
|
36
|
+
|
37
|
+
desc "init", "init ykfastlane"
|
38
|
+
subcommand "init", YKFastlane::Init
|
39
|
+
|
40
|
+
desc "certificate", "manager ios certificate & profile files"
|
41
|
+
subcommand "certificate", YKFastlane::Certificate
|
42
|
+
end
|
43
|
+
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.12
|
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: []
|