ocean_package 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.idea/.gitignore +8 -0
- data/.idea/.rakeTasks +7 -0
- data/.idea/dictionaries/ocean.xml +3 -0
- data/.idea/inspectionProfiles/Project_Default.xml +6 -0
- data/.idea/misc.xml +7 -0
- data/.idea/modules.xml +8 -0
- data/.idea/ocean_package.iml +27 -0
- data/.idea/vcs.xml +6 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +11 -0
- data/Gemfile.lock +40 -0
- data/LICENSE.txt +21 -0
- data/README.md +43 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/oceanpackage +5 -0
- data/bin/setup +8 -0
- data/lib/ocean_package.rb +41 -0
- data/lib/ocean_package/command.rb +162 -0
- data/lib/ocean_package/config.rb +41 -0
- data/lib/ocean_package/constants.rb +14 -0
- data/lib/ocean_package/dingtalk.rb +34 -0
- data/lib/ocean_package/fir.rb +167 -0
- data/lib/ocean_package/ipa.rb +188 -0
- data/lib/ocean_package/logger.rb +22 -0
- data/lib/ocean_package/oss.rb +92 -0
- data/lib/ocean_package/package.rb +242 -0
- data/lib/ocean_package/version.rb +3 -0
- data/ocean_package.gemspec +43 -0
- metadata +117 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
|
2
|
+
module OceanPackage
|
3
|
+
|
4
|
+
class Config
|
5
|
+
|
6
|
+
attr_accessor :workspace_path
|
7
|
+
attr_accessor :scheme
|
8
|
+
attr_accessor :configuration
|
9
|
+
|
10
|
+
# attr_accessor :ding_enabled
|
11
|
+
# attr_accessor :ding_token
|
12
|
+
|
13
|
+
def initialize(params = [])
|
14
|
+
argv = CLAide::ARGV.new(params)
|
15
|
+
|
16
|
+
@workspace_path = argv.option("workspace-path", "")
|
17
|
+
puts "workspace_path: #{@workspace_path}"
|
18
|
+
|
19
|
+
@scheme = argv.option("scheme", "")
|
20
|
+
puts "scheme: #{@scheme}"
|
21
|
+
|
22
|
+
@configuration = argv.option("configuration", "")
|
23
|
+
puts "configuration: #{@configuration}"
|
24
|
+
|
25
|
+
# @ding_enabled = argv.flag?("ding-enabled", false)
|
26
|
+
# puts "ding_enabled: #{@ding_enabled}"
|
27
|
+
#
|
28
|
+
# @ding_token = argv.option("ding-token", "")
|
29
|
+
# puts "ding_token: #{@ding_token}"
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def valid
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
|
2
|
+
module OceanPackage
|
3
|
+
|
4
|
+
module Constants
|
5
|
+
|
6
|
+
# 有效的 CONFIGURATION 值
|
7
|
+
AVAILABLE_CONFIGURATIONS = %w(Debug Release)
|
8
|
+
DEFAULT_CONFIGURATION = 'Debug'
|
9
|
+
DEFAULT_COMPANY_NAME = 'YourCompanyName'
|
10
|
+
DEFAULT_ARCHIVE_PATH = '$HOME/Documents/Ipas/'
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
|
2
|
+
module OceanPackage
|
3
|
+
|
4
|
+
class DingTalk
|
5
|
+
require "dingbot"
|
6
|
+
|
7
|
+
attr_accessor :token
|
8
|
+
|
9
|
+
def initialize(token)
|
10
|
+
@token = token
|
11
|
+
configure_ding_bot
|
12
|
+
end
|
13
|
+
|
14
|
+
def configure_ding_bot
|
15
|
+
DingBot.configure do |config|
|
16
|
+
config.endpoint = 'https://oapi.dingtalk.com/robot/send' # API endpoint URL, default: ENV['DINGTALK_API_ENDPOINT'] or https://oapi.dingtalk.com/robot/send
|
17
|
+
config.access_token = @token # access token, default: ENV['DINGTALK_ACCESS_TOKEN']
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# 发送 text 消息,有 @ 某人效果
|
22
|
+
def send_text_message(content = '', at_mobiles = [], is_at_all = false)
|
23
|
+
message = DingBot::Message::Text.new(content, at_mobiles, is_at_all)
|
24
|
+
DingBot.send_msg(message)
|
25
|
+
end
|
26
|
+
|
27
|
+
# 发送消息卡片,可以附带链接,图片
|
28
|
+
def send_card_message(title = '', text = '')
|
29
|
+
message = DingBot::Message::WholeActionCard.new(title, text)
|
30
|
+
DingBot.send_msg(message)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
|
2
|
+
module OceanPackage
|
3
|
+
class Fir
|
4
|
+
|
5
|
+
# token
|
6
|
+
attr_accessor :token
|
7
|
+
# 更新日志
|
8
|
+
attr_accessor :change_log
|
9
|
+
# ipa文件包路径
|
10
|
+
attr_accessor :ipa_file_path
|
11
|
+
# log文件路径
|
12
|
+
attr_accessor :log_path
|
13
|
+
|
14
|
+
def initialize(token, change_log = "", ipa_file_path, log_path)
|
15
|
+
@token = token
|
16
|
+
@change_log = change_log
|
17
|
+
@ipa_file_path = ipa_file_path
|
18
|
+
@log_path = log_path
|
19
|
+
end
|
20
|
+
|
21
|
+
# 命令:查看 fir 信息
|
22
|
+
def info_cmd
|
23
|
+
'fir -v'
|
24
|
+
end
|
25
|
+
|
26
|
+
# 命令:fir 登录
|
27
|
+
def login_cmd
|
28
|
+
cmd = 'fir login'
|
29
|
+
cmd += ' -T ' + @token
|
30
|
+
|
31
|
+
Log.info("fir login command: #{cmd}")
|
32
|
+
|
33
|
+
cmd
|
34
|
+
end
|
35
|
+
|
36
|
+
# 命令:上传ipa文件到fir平台
|
37
|
+
def publish_cmd
|
38
|
+
cmd = 'fir publish'
|
39
|
+
cmd += ' ' + @ipa_file_path
|
40
|
+
cmd += ' -c ' + @change_log
|
41
|
+
cmd += ' -Q'
|
42
|
+
cmd += ' | tee ' + @log_path
|
43
|
+
|
44
|
+
Log.info("fir publish command: #{cmd}")
|
45
|
+
|
46
|
+
cmd
|
47
|
+
end
|
48
|
+
|
49
|
+
# 运行
|
50
|
+
def run
|
51
|
+
unless check
|
52
|
+
return
|
53
|
+
end
|
54
|
+
login
|
55
|
+
publish
|
56
|
+
end
|
57
|
+
|
58
|
+
# 校验
|
59
|
+
def check
|
60
|
+
|
61
|
+
token_value = "#{@token}"
|
62
|
+
if token_value.empty?
|
63
|
+
Log.error("fir token is empty, please check !!!")
|
64
|
+
return false
|
65
|
+
end
|
66
|
+
|
67
|
+
ipa_file_path_value = "#{@ipa_file_path}"
|
68
|
+
if ipa_file_path_value.empty?
|
69
|
+
Log.error("ipa file path is empty, please check !!!")
|
70
|
+
return false
|
71
|
+
end
|
72
|
+
|
73
|
+
return true
|
74
|
+
end
|
75
|
+
|
76
|
+
# 登录
|
77
|
+
def login
|
78
|
+
system(info_cmd)
|
79
|
+
res = system(login_cmd)
|
80
|
+
|
81
|
+
Log.info("fir login result: #{res}")
|
82
|
+
|
83
|
+
unless res == true
|
84
|
+
Log.error("fir login fail, please check !!!")
|
85
|
+
exit(1)
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
# 上传
|
91
|
+
def publish
|
92
|
+
res = system(publish_cmd)
|
93
|
+
|
94
|
+
Log.info("fir publish result: #{res}")
|
95
|
+
|
96
|
+
unless res == true
|
97
|
+
Log.error("fir publish fail, please check !!!")
|
98
|
+
exit(1)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# 查找 release_id
|
103
|
+
def find_release_id
|
104
|
+
# 正则表达式匹配
|
105
|
+
pattern = /.*Release id is.*/
|
106
|
+
release_id = ''
|
107
|
+
File.open(@log_path, "r") do |f|
|
108
|
+
f.each_line do |line|
|
109
|
+
line_s = "#{line}"
|
110
|
+
if line_s =~ pattern
|
111
|
+
release_id = line_s.split(' ').last
|
112
|
+
break
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
Log.info("fir release id value: #{release_id}")
|
117
|
+
release_id
|
118
|
+
end
|
119
|
+
|
120
|
+
# 查找下载链接
|
121
|
+
def find_link
|
122
|
+
# 正则表达式匹配
|
123
|
+
pattern = /.*Published succeed:.*/
|
124
|
+
link = ''
|
125
|
+
File.open(@log_path, "r") do |f|
|
126
|
+
f.each_line do |line|
|
127
|
+
line_s = "#{line}"
|
128
|
+
if line_s =~ pattern
|
129
|
+
link = line_s.split(' ').last
|
130
|
+
break
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
Log.info("fir link value: #{link}")
|
135
|
+
link
|
136
|
+
end
|
137
|
+
|
138
|
+
# 构建完整的下载链接,有 release id
|
139
|
+
def whole_download_link
|
140
|
+
link = find_link
|
141
|
+
link += '?release_id='
|
142
|
+
link += find_release_id
|
143
|
+
|
144
|
+
Log.info("fir whole link value: #{link}")
|
145
|
+
|
146
|
+
link
|
147
|
+
end
|
148
|
+
|
149
|
+
# 查找下载二维码的文件路径
|
150
|
+
def find_qr_code_path
|
151
|
+
# 正则表达式匹配
|
152
|
+
pattern = /.*Local qrcode file:.*/
|
153
|
+
path = ''
|
154
|
+
File.open(@log_path, "r") do |f|
|
155
|
+
f.each_line do |line|
|
156
|
+
line_s = "#{line}"
|
157
|
+
if line_s =~ pattern
|
158
|
+
path = line_s.split(' ').last
|
159
|
+
break
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
Log.info("fir qr code path value: #{path}")
|
164
|
+
path
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
|
2
|
+
module OceanPackage
|
3
|
+
class Ipa
|
4
|
+
|
5
|
+
# ipa 文件路径
|
6
|
+
attr_accessor :path
|
7
|
+
|
8
|
+
def initialize(path)
|
9
|
+
@path = path
|
10
|
+
end
|
11
|
+
|
12
|
+
# ipa 文件所在的文件夹路径
|
13
|
+
def ipa_dir_path
|
14
|
+
dir_path = File.dirname(@path)
|
15
|
+
|
16
|
+
Log.info("ipa dir path: #{dir_path}")
|
17
|
+
|
18
|
+
dir_path
|
19
|
+
end
|
20
|
+
|
21
|
+
# ipa 文件名
|
22
|
+
def ipa_name
|
23
|
+
name = File.basename(@path, ".*")
|
24
|
+
|
25
|
+
Log.info("ipa name: #{name}")
|
26
|
+
|
27
|
+
name
|
28
|
+
end
|
29
|
+
|
30
|
+
# ipa文件名称,包含后缀
|
31
|
+
def ipa_base_name
|
32
|
+
name = File.basename(@path)
|
33
|
+
|
34
|
+
Log.info(puts "ipa base name: #{name}")
|
35
|
+
|
36
|
+
name
|
37
|
+
end
|
38
|
+
|
39
|
+
# 临时目录路径
|
40
|
+
def ipa_tmp_dir_path
|
41
|
+
tmp_path = ipa_dir_path
|
42
|
+
tmp_path += '/' + ipa_name + '_tmp'
|
43
|
+
tmp_path
|
44
|
+
end
|
45
|
+
|
46
|
+
# 临时目录下的ipa文件
|
47
|
+
def tmp_ipa_file_path
|
48
|
+
tmp_path = ipa_tmp_dir_path + '/' + ipa_base_name
|
49
|
+
|
50
|
+
Log.info("tmp ipa file path: #{tmp_path}")
|
51
|
+
|
52
|
+
tmp_path
|
53
|
+
end
|
54
|
+
|
55
|
+
# 临时目录下的 zip 文件路径,把 ipa 后缀改为 zip 后缀
|
56
|
+
def tmp_ipa_zip_file_path
|
57
|
+
zip_file = ipa_tmp_dir_path + '/' + ipa_name + '.zip'
|
58
|
+
|
59
|
+
Log.info(puts "tmp ipa zip file path: #{zip_file}")
|
60
|
+
|
61
|
+
zip_file
|
62
|
+
end
|
63
|
+
|
64
|
+
# 创建临时文件夹
|
65
|
+
def make_tmp_dir
|
66
|
+
FileUtils.mkdir_p(ipa_tmp_dir_path)
|
67
|
+
end
|
68
|
+
|
69
|
+
# 拷贝ipa文件到临时目录下
|
70
|
+
def cp_to_tmp_dir
|
71
|
+
FileUtils.cp(@path, ipa_tmp_dir_path)
|
72
|
+
end
|
73
|
+
|
74
|
+
# 冲命名ipa文件,ipa -> zip
|
75
|
+
def rename_tmp_ipa_file
|
76
|
+
ipa_file = tmp_ipa_file_path
|
77
|
+
new_ipa_file = tmp_ipa_zip_file_path
|
78
|
+
|
79
|
+
Log.info("rename ipa file #{ipa_file} to: #{new_ipa_file}")
|
80
|
+
|
81
|
+
File.rename(ipa_file, new_ipa_file)
|
82
|
+
end
|
83
|
+
|
84
|
+
# 解压缩 zip 文件
|
85
|
+
def unzip_ipa_file
|
86
|
+
cmd = 'unzip -o'
|
87
|
+
cmd += ' -d ' + ipa_tmp_dir_path
|
88
|
+
cmd += ' ' + tmp_ipa_zip_file_path
|
89
|
+
|
90
|
+
Log.info("unzip cmd: #{cmd}")
|
91
|
+
|
92
|
+
res = system(cmd)
|
93
|
+
end
|
94
|
+
|
95
|
+
# 查找 info.plist 文件
|
96
|
+
def find_info_plist_path
|
97
|
+
plist_dir = ipa_tmp_dir_path
|
98
|
+
plist_dir += '/Payload'
|
99
|
+
|
100
|
+
cmd = 'find ' + plist_dir
|
101
|
+
cmd += ' -maxdepth 2'
|
102
|
+
cmd += ' -name Info.plist'
|
103
|
+
|
104
|
+
Log.info("find info plist path cmd: #{cmd}")
|
105
|
+
|
106
|
+
res = %x(#{cmd})
|
107
|
+
# res = system(cmd)
|
108
|
+
|
109
|
+
Log.info("info plist path: #{res}")
|
110
|
+
|
111
|
+
res
|
112
|
+
end
|
113
|
+
|
114
|
+
def find_info_plist_dir
|
115
|
+
plist_path = find_info_plist_path
|
116
|
+
dir = File.dirname(plist_path)
|
117
|
+
|
118
|
+
# Log.info("find info plist dir: #{dir}")
|
119
|
+
|
120
|
+
dir
|
121
|
+
end
|
122
|
+
|
123
|
+
# 读取 info.plist 文件的值
|
124
|
+
def info_plist_value
|
125
|
+
@info ||= CFPropertyList.native_types(
|
126
|
+
CFPropertyList::List.new(file: File.join(find_info_plist_dir, 'Info.plist')).value)
|
127
|
+
|
128
|
+
# Log.info("info plist value: #{@info}")
|
129
|
+
|
130
|
+
@info
|
131
|
+
|
132
|
+
# 这种写法不行的,会有如下错误
|
133
|
+
# UnexpectedError: IOError: File /Users/ocean/Documents/myipas/ztoExpressClient_tmp/Payload/ztoExpressClient.app/Info.plist not readable!
|
134
|
+
# @info ||= CFPropertyList.native_types(
|
135
|
+
# CFPropertyList::List.new(file: find_info_plist_path).value)
|
136
|
+
#
|
137
|
+
# puts "info_plist_value: #{@info}"
|
138
|
+
# @info
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
# app 名称
|
143
|
+
def display_name
|
144
|
+
info_plist_value["CFBundleDisplayName"]
|
145
|
+
end
|
146
|
+
|
147
|
+
# bundle id
|
148
|
+
def bundle_identifier
|
149
|
+
info_plist_value["CFBundleIdentifier"]
|
150
|
+
end
|
151
|
+
|
152
|
+
# 版本
|
153
|
+
def version
|
154
|
+
info_plist_value["CFBundleShortVersionString"]
|
155
|
+
end
|
156
|
+
|
157
|
+
# build 版本
|
158
|
+
def build_version
|
159
|
+
info_plist_value["CFBundleVersion"]
|
160
|
+
end
|
161
|
+
|
162
|
+
def log_value
|
163
|
+
display_name_value = display_name
|
164
|
+
puts "CFBundleDisplayName: #{display_name_value}"
|
165
|
+
|
166
|
+
bundle_identifier_value = bundle_identifier
|
167
|
+
puts "CFBundleIdentifier: #{bundle_identifier_value}"
|
168
|
+
|
169
|
+
version_value = version
|
170
|
+
puts "CFBundleShortVersionString: #{version_value}"
|
171
|
+
|
172
|
+
build_version_value = build_version
|
173
|
+
puts "CFBundleVersion: #{build_version_value}"
|
174
|
+
end
|
175
|
+
|
176
|
+
# 执行相关操作
|
177
|
+
def run
|
178
|
+
make_tmp_dir
|
179
|
+
cp_to_tmp_dir
|
180
|
+
rename_tmp_ipa_file
|
181
|
+
unzip_ipa_file
|
182
|
+
info_plist_value
|
183
|
+
log_value
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
module OceanPackage
|
3
|
+
module Log
|
4
|
+
|
5
|
+
def Log.info(msg)
|
6
|
+
logger = Logger.new(STDOUT)
|
7
|
+
logger.info(msg)
|
8
|
+
end
|
9
|
+
|
10
|
+
def Log.error(msg)
|
11
|
+
logger = Logger.new(STDOUT)
|
12
|
+
logger.error(msg)
|
13
|
+
end
|
14
|
+
|
15
|
+
# 分割线
|
16
|
+
def Log.divider
|
17
|
+
logger = Logger.new(STDOUT)
|
18
|
+
logger.info("=========")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|