fir-cli 1.7.4.1 → 2.0.0.beta
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 +4 -4
- data/.travis.yml +0 -2
- data/README.md +8 -1
- data/fir-cli.gemspec +2 -1
- data/lib/fir/cli.rb +5 -3
- data/lib/fir/util/ali_uploader.rb +78 -0
- data/lib/fir/util/app_uploader.rb +111 -0
- data/lib/fir/util/info.rb +2 -0
- data/lib/fir/util/publish.rb +98 -173
- data/lib/fir/util/publisher.rb +34 -0
- data/lib/fir/util/qiniu_uploader.rb +73 -0
- data/lib/fir/version.rb +1 -1
- data/luckin_coffee.png +0 -0
- metadata +16 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 673a534b58afadd5a2b7491884a074dd2db722b636929ac3a43c5de1778e981d
|
4
|
+
data.tar.gz: fcf5a3e79f1bfaf937d6ae13bfed6f40c3f405e59344c797c1fe7a43f8489ddd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3d62c7e16583cf776c29bbbaec8dfae9104b01534cbf52882545bebf688fda89a51dd928cbd31ae7ccab6ac833fffd1650c13f9c2639f526396c1bdd4ec60a99
|
7
|
+
data.tar.gz: 31d38f670026014742b1a4c1cf87b5f1e33d13bb294266d327dc517a655a395a84629f226285432899c0755882e3304a2ab199b21994f227b348fa54f7d20b53
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -14,6 +14,7 @@ fir.im-cli 可以通过指令查看, 上传, iOS/Android 应用.
|
|
14
14
|
|
15
15
|
|
16
16
|
# 最近更新
|
17
|
+
- (2.0.0) publish 使用更快的存储商, 加速上传速度, 若感觉没以前可使用 switch_to_qiniu 恢复
|
17
18
|
- 支持了在fastlane 直接调用, 具体请参见 [https://github.com/FIRHQ/fastlane-plugin-fir_cli](https://github.com/FIRHQ/fastlane-plugin-fir_cli)
|
18
19
|
- publish 支持 新参数 force_pin_history, 可以 将上传的版本, 固定在下载页面上(当大于最大固定版本数后, 会挤掉最老的固定版本) [2019年11月18日]
|
19
20
|
- publish 支持 新参数 specify_icon_file_path, 可以直接指定 app 的 icon 图标文件 [2019年11月18日]
|
@@ -78,7 +79,7 @@ docker run firhq/fir-cli:latest -e API_TOKEN=XXXX -v ./1.apk:1.apk publish 1.apk
|
|
78
79
|
|
79
80
|
## 提交反馈
|
80
81
|
|
81
|
-
- 联系微信 `atpking
|
82
|
+
- 联系微信 `atpking`, 请注明 "fir-cli 交流"
|
82
83
|
|
83
84
|
- 使用 Github 的 [Issue](https://github.com/FIRHQ/fir-cli/issues)
|
84
85
|
|
@@ -86,3 +87,9 @@ docker run firhq/fir-cli:latest -e API_TOKEN=XXXX -v ./1.apk:1.apk publish 1.apk
|
|
86
87
|
|
87
88
|
- 感谢 sparkrico 提供修正的 https://github.com/sparkrico/ruby_apk 解决了 android 解析的问题
|
88
89
|
|
90
|
+
|
91
|
+
## 鼓励维护
|
92
|
+
|
93
|
+
感谢支持
|
94
|
+
|
95
|
+

|
data/fir-cli.gemspec
CHANGED
@@ -27,6 +27,7 @@ Gem::Specification.new do |spec|
|
|
27
27
|
/_/ /___/_/ |_| \____/_____/___/
|
28
28
|
|
29
29
|
## 更新记录
|
30
|
+
- (2.0.0) publish 使用更快的存储商, 加速上传速度, 若感觉没以前可使用 switch_to_qiniu 恢复
|
30
31
|
- (1.7.4) 配合 fastlane-plugin-fir_cli 做了一些小优化
|
31
32
|
- (1.7.3) 新增了 上传指定图标, 不上传图标 以及 将版本固定显示在下载页上
|
32
33
|
- (1.7.2) 修正了无论是否加参数都固定出现二维码图片的bug
|
@@ -44,7 +45,7 @@ Gem::Specification.new do |spec|
|
|
44
45
|
# spec.add_development_dependency 'byebug'
|
45
46
|
spec.add_development_dependency 'minitest', '~> 5.7'
|
46
47
|
spec.add_development_dependency 'pry', '~> 0.10'
|
47
|
-
|
48
|
+
|
48
49
|
spec.add_dependency 'thor', '~> 0.19'
|
49
50
|
spec.add_dependency 'rest-client', '~> 2.0'
|
50
51
|
spec.add_dependency 'ruby_android_apk', '~> 0.7.7.1'
|
data/lib/fir/cli.rb
CHANGED
@@ -107,12 +107,14 @@ module FIR
|
|
107
107
|
method_option :short, type: :string, aliases: '-s', desc: 'Set custom short link'
|
108
108
|
method_option :changelog, type: :string, aliases: '-c', desc: 'Set changelog'
|
109
109
|
method_option :qrcode, type: :boolean, aliases: '-Q', desc: 'Generate qrcode'
|
110
|
-
method_option :need_release_id, type: :boolean, aliases: '-R', desc: 'Add release id with fir url (WARNING: FIR ONLY SAVED 30 releases recently per app'
|
110
|
+
method_option :need_release_id, type: :boolean, aliases: '-R', default: false, desc: 'Add release id with fir url (WARNING: FIR ONLY SAVED 30 releases recently per app'
|
111
111
|
|
112
|
-
method_option :force_pin_history, type: :boolean, aliases: '-H', default: false,
|
113
|
-
method_option :skip_update_icon, type: :boolean, aliases: '-S', default: false,
|
112
|
+
method_option :force_pin_history, type: :boolean, aliases: '-H', default: false, desc: 'pin this release to the download page by force'
|
113
|
+
method_option :skip_update_icon, type: :boolean, aliases: '-S', default: false, desc: 'skip update app icon'
|
114
114
|
method_option :specify_icon_file, type: :string, desc: 'specify icon file'
|
115
115
|
|
116
|
+
method_option :switch_to_qiniu, type: :boolean, default: false, aliases: '-N', desc: 'if app upload slowly, u can switch this option'
|
117
|
+
|
116
118
|
method_option :mappingfile, type: :string, aliases: '-m', desc: 'App mapping file'
|
117
119
|
method_option :dingtalk_access_token, type: :string, aliases: '-D', desc: 'Send msg to dingtalk, only need access_token, not whole url'
|
118
120
|
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './app_uploader'
|
4
|
+
# require 'byebug'
|
5
|
+
|
6
|
+
module FIR
|
7
|
+
class AliUploader < AppUploader
|
8
|
+
def upload_icon
|
9
|
+
if skip_update_icon?
|
10
|
+
logger.info 'skip update icon...'
|
11
|
+
return
|
12
|
+
end
|
13
|
+
try_to_action('upload icon') do
|
14
|
+
# 拿到 icon 的授权
|
15
|
+
icon_url = uploading_info[:cert][:icon][:upload_url]
|
16
|
+
icon_info = uploading_icon_info
|
17
|
+
|
18
|
+
logger.debug "icon_url = #{icon_url}, icon_info = #{icon_info}"
|
19
|
+
|
20
|
+
put_file(icon_url, uploading_icon_info, uploading_info[:cert][:icon][:custom_headers])
|
21
|
+
|
22
|
+
callback_to_api(callback_url, callback_icon_information)
|
23
|
+
end
|
24
|
+
rescue StandardError => e
|
25
|
+
# ignore icon error
|
26
|
+
logger.info "ignore icon upload error #{e.message}"
|
27
|
+
end
|
28
|
+
|
29
|
+
def upload_binary
|
30
|
+
try_to_action 'upload binary ...' do
|
31
|
+
binary_url = uploading_info[:cert][:binary][:upload_url]
|
32
|
+
binary_info = uploading_binary_info
|
33
|
+
|
34
|
+
logger.debug "binary_url = #{binary_url}, binary_info = #{binary_info}"
|
35
|
+
headers = uploading_info[:cert][:binary][:custom_headers]
|
36
|
+
headers_copy = {
|
37
|
+
'CONTENT-DISPOSITION' => headers[:"CONTENT-DISPOSITION"],
|
38
|
+
'Content-Type' => headers[:"content-type"],
|
39
|
+
'date' => headers[:date],
|
40
|
+
'x-oss-date' => headers[:"x-oss-date"],
|
41
|
+
'authorization' => headers[:authorization]
|
42
|
+
}
|
43
|
+
|
44
|
+
logger.debug headers_copy
|
45
|
+
put_file(binary_url, binary_info, headers_copy)
|
46
|
+
|
47
|
+
callback_to_api(callback_url, callback_binary_information)
|
48
|
+
end
|
49
|
+
rescue StandardError => e
|
50
|
+
logger.error "binary upload to ali fail, #{e.message}"
|
51
|
+
exit 1
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
|
56
|
+
def put_file(url, file, headers)
|
57
|
+
RestClient::Request.execute(
|
58
|
+
method: 'PUT',
|
59
|
+
url: url,
|
60
|
+
payload: file,
|
61
|
+
headers: headers,
|
62
|
+
timeout: 300
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
def callback_url
|
67
|
+
"#{fir_api[:base_url]}/auth/ali/callback"
|
68
|
+
end
|
69
|
+
|
70
|
+
def uploading_icon_info
|
71
|
+
File.new(icon_file_path, 'rb')
|
72
|
+
end
|
73
|
+
|
74
|
+
def uploading_binary_info
|
75
|
+
File.new(file_path, 'rb')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
module FIR
|
2
|
+
class AppUploader
|
3
|
+
include ApiTools::DefaultRestModule
|
4
|
+
include Config
|
5
|
+
|
6
|
+
attr_accessor :app_info, :user_info, :uploading_info, :options
|
7
|
+
def initialize(app_info, user_info, uploading_info, options)
|
8
|
+
@app_info = app_info
|
9
|
+
@user_info = user_info
|
10
|
+
@uploading_info = uploading_info
|
11
|
+
@options = options
|
12
|
+
end
|
13
|
+
|
14
|
+
def upload
|
15
|
+
upload_icon
|
16
|
+
binary_callback_info = upload_binary
|
17
|
+
# 将 binary 的callback信息返回
|
18
|
+
binary_callback_info
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def callback_to_api(callback_url, callback_binary_information)
|
24
|
+
return if callback_binary_information.blank?
|
25
|
+
|
26
|
+
post callback_url, callback_binary_information
|
27
|
+
end
|
28
|
+
|
29
|
+
def icon_file_path
|
30
|
+
if options[:specify_icon_file].blank?
|
31
|
+
app_info[:icons].max_by { |f| File.size(f) }
|
32
|
+
else
|
33
|
+
File.absolute_path(options[:specify_icon_file])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# 是否跳过 icon 上传
|
38
|
+
def skip_update_icon?
|
39
|
+
options[:skip_icon_upload].to_s == 'true'
|
40
|
+
end
|
41
|
+
|
42
|
+
def read_changelog
|
43
|
+
changelog = options[:changelog].to_s.to_utf8
|
44
|
+
return if changelog.blank?
|
45
|
+
|
46
|
+
File.exist?(changelog) ? File.read(changelog) : changelog
|
47
|
+
end
|
48
|
+
|
49
|
+
def icon_cert
|
50
|
+
uploading_info[:cert][:icon]
|
51
|
+
end
|
52
|
+
|
53
|
+
def binary_cert
|
54
|
+
uploading_info[:cert][:binary]
|
55
|
+
end
|
56
|
+
|
57
|
+
def file_path
|
58
|
+
app_info[:file_path]
|
59
|
+
end
|
60
|
+
|
61
|
+
def try_to_action(action, &block)
|
62
|
+
logger.debug "begin to #{action}"
|
63
|
+
answer = block.call
|
64
|
+
logger.debug "#{action} finished"
|
65
|
+
answer
|
66
|
+
rescue StandardError => e
|
67
|
+
logger.error "#{action} error ! #{e.message}"
|
68
|
+
raise e
|
69
|
+
end
|
70
|
+
|
71
|
+
def app_id
|
72
|
+
uploading_info[:id]
|
73
|
+
end
|
74
|
+
|
75
|
+
def callback_icon_information
|
76
|
+
return {} if icon_file_path.nil?
|
77
|
+
{
|
78
|
+
key: icon_cert[:key],
|
79
|
+
token: icon_cert[:token],
|
80
|
+
origin: 'fir-cli',
|
81
|
+
parent_id: app_id,
|
82
|
+
fsize: File.size(icon_file_path),
|
83
|
+
fname: 'blob'
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
def callback_binary_information
|
88
|
+
{
|
89
|
+
build: app_info[:build],
|
90
|
+
fname: File.basename(file_path),
|
91
|
+
key: binary_cert[:key],
|
92
|
+
name: app_info[:display_name] || app_info[:name],
|
93
|
+
origin: 'fir-cli',
|
94
|
+
parent_id: app_id,
|
95
|
+
release_tag: 'develop',
|
96
|
+
fsize: File.size(file_path),
|
97
|
+
release_type: app_info[:release_type],
|
98
|
+
distribution_name: app_info[:distribution_name],
|
99
|
+
token: binary_cert[:token],
|
100
|
+
version: app_info[:version],
|
101
|
+
changelog: read_changelog,
|
102
|
+
user_id: user_info[:id]
|
103
|
+
}.reject { |x| x.nil? || x == '' }
|
104
|
+
end
|
105
|
+
|
106
|
+
def logger
|
107
|
+
FIR.logger
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
data/lib/fir/util/info.rb
CHANGED
@@ -26,12 +26,14 @@ module FIR
|
|
26
26
|
app = ipa.app
|
27
27
|
info = app.full_info(options)
|
28
28
|
ipa.cleanup
|
29
|
+
info[:file_path] = ipa_path
|
29
30
|
info
|
30
31
|
end
|
31
32
|
|
32
33
|
def apk_info(apk_path, options = {})
|
33
34
|
apk = FIR::Parser::Apk.new(apk_path)
|
34
35
|
info = apk.full_info(options)
|
36
|
+
info[:file_path] = apk_path
|
35
37
|
info
|
36
38
|
end
|
37
39
|
end
|
data/lib/fir/util/publish.rb
CHANGED
@@ -1,146 +1,75 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
# require 'byebug'
|
4
|
+
require_relative './qiniu_uploader'
|
5
|
+
|
6
|
+
require_relative './ali_uploader'
|
7
|
+
|
3
8
|
module FIR
|
4
9
|
module Publish
|
5
10
|
def publish(*args, options)
|
6
11
|
initialize_publish_options(args, options)
|
7
|
-
@options = options
|
8
12
|
check_supported_file_and_token
|
9
|
-
|
10
13
|
logger_info_publishing_message
|
11
14
|
|
12
|
-
|
13
|
-
|
14
|
-
@uploading_info = fetch_uploading_info
|
15
|
-
@app_id = @uploading_info[:id]
|
15
|
+
logger.info 'begin to upload ...'
|
16
|
+
received_app_info = upload_app
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
short = received_app_info[:short]
|
19
|
+
release_id = received_app_info[:release_id]
|
20
|
+
|
21
|
+
logger.info 'end upload'
|
20
22
|
|
21
23
|
logger_info_dividing_line
|
22
|
-
logger_info_app_short_and_qrcode
|
23
24
|
|
24
|
-
|
25
|
+
download_url = build_download_url(short, release_id)
|
26
|
+
logger.info "Published succeed: #{download_url}"
|
27
|
+
|
28
|
+
qrcode_path = build_qrcode download_url
|
29
|
+
dingtalk_notifier(download_url, qrcode_path)
|
25
30
|
upload_mapping_file_with_publish
|
31
|
+
|
26
32
|
logger_info_blank_line
|
27
|
-
|
33
|
+
|
28
34
|
{
|
29
35
|
app_id: @app_id,
|
30
|
-
release_id:
|
31
|
-
short:
|
36
|
+
release_id: release_id,
|
37
|
+
short: short
|
32
38
|
}
|
33
39
|
end
|
34
40
|
|
35
|
-
|
36
|
-
user_info = fetch_user_info(@token)
|
41
|
+
protected
|
37
42
|
|
38
|
-
|
39
|
-
|
43
|
+
def logger_info_publishing_message
|
44
|
+
email = @user_info.fetch(:email, '')
|
45
|
+
name = @user_info.fetch(:name, '')
|
40
46
|
|
41
47
|
logger.info "Publishing app via #{name}<#{email}>......."
|
42
48
|
logger_info_dividing_line
|
43
49
|
end
|
44
50
|
|
45
51
|
def upload_app
|
52
|
+
|
53
|
+
app_uploaded_callback_data = if @options[:switch_to_qiniu]
|
54
|
+
QiniuUploader.new(@app_info, @user_info, @uploading_info, @options).upload
|
55
|
+
else
|
56
|
+
AliUploader.new(@app_info, @user_info, @uploading_info, @options).upload
|
57
|
+
end
|
46
58
|
|
47
|
-
|
48
|
-
@binary_cert = @uploading_info[:cert][:binary]
|
49
|
-
logger.debug "in upload app begin to upload icon"
|
50
|
-
upload_app_icon unless @skip_update_icon
|
51
|
-
logger.debug "in upload icon finished"
|
52
|
-
|
53
|
-
logger.debug "in upload app begin to upload binary"
|
54
|
-
@app_uploaded_callback_data = upload_app_binary
|
55
|
-
logger.debug "in upload binary"
|
56
|
-
@release_id = @app_uploaded_callback_data[:release_id]
|
57
|
-
|
58
|
-
force_pin_release if @force_pin_history
|
59
|
+
release_id = app_uploaded_callback_data[:release_id]
|
59
60
|
|
60
61
|
logger.info "App id is #{@app_id}"
|
61
|
-
logger.info "Release id is #{
|
62
|
+
logger.info "Release id is #{release_id}"
|
63
|
+
|
64
|
+
# 处理上传完毕后, 需要的后续操作
|
65
|
+
force_pin_release(release_id) if @force_pin_history
|
62
66
|
upload_device_info
|
63
67
|
update_app_info
|
64
|
-
fetch_app_info
|
65
|
-
end
|
66
68
|
|
67
|
-
|
68
|
-
|
69
|
-
upload_file(word)
|
70
|
-
storage = ENV['SOTRAGE_NAME'] || 'qiniu'
|
71
|
-
information = send("#{word}_information")
|
72
|
-
post("#{fir_api[:base_url]}/auth/#{storage}/callback", information) unless information.blank?
|
73
|
-
end
|
74
|
-
end
|
69
|
+
app_info_dict = fetch_app_info
|
70
|
+
app_info_dict[:release_id] = release_id
|
75
71
|
|
76
|
-
|
77
|
-
logger.info "Uploading app #{postfix}......"
|
78
|
-
url = @uploading_info[:cert][postfix.to_sym][:upload_url]
|
79
|
-
info = send("uploading_#{postfix}_info")
|
80
|
-
logger.debug "url = #{url}, info = #{info}"
|
81
|
-
uploaded_info = post(url, info.merge(manual_callback: true),
|
82
|
-
params_to_json: false,
|
83
|
-
header: nil)
|
84
|
-
rescue StandardError => e
|
85
|
-
logger.error "Uploading app #{postfix} failed"
|
86
|
-
exit 1 if postfix != 'icon'
|
87
|
-
end
|
88
|
-
|
89
|
-
def uploading_icon_info
|
90
|
-
large_icon_path = @app_info[:icons].max_by { |f| File.size(f) }
|
91
|
-
@uncrushed_icon_path = @specify_icon_file_path || convert_icon(large_icon_path)
|
92
|
-
{
|
93
|
-
key: @icon_cert[:key],
|
94
|
-
token: @icon_cert[:token],
|
95
|
-
file: File.new(@uncrushed_icon_path, 'rb'),
|
96
|
-
'x:is_converted' => '1'
|
97
|
-
}
|
98
|
-
end
|
99
|
-
|
100
|
-
def icon_information
|
101
|
-
return {} if @uncrushed_icon_path.nil?
|
102
|
-
{
|
103
|
-
key: @icon_cert[:key],
|
104
|
-
token: @icon_cert[:token],
|
105
|
-
origin: 'fir-cli',
|
106
|
-
parent_id: @app_id,
|
107
|
-
fsize: File.size(@uncrushed_icon_path),
|
108
|
-
fname: 'blob'
|
109
|
-
}
|
110
|
-
end
|
111
|
-
|
112
|
-
def binary_information
|
113
|
-
{
|
114
|
-
build: @app_info[:build],
|
115
|
-
fname: File.basename(@file_path),
|
116
|
-
key: @binary_cert[:key],
|
117
|
-
name: @app_info[:display_name] || @app_info[:name],
|
118
|
-
origin: 'fir-cli',
|
119
|
-
parent_id: @app_id,
|
120
|
-
release_tag: 'develop',
|
121
|
-
fsize: File.size(@file_path),
|
122
|
-
release_type: @app_info[:release_type],
|
123
|
-
distribution_name: @app_info[:distribution_name],
|
124
|
-
token: @binary_cert[:token],
|
125
|
-
version: @app_info[:version],
|
126
|
-
changelog: @changelog,
|
127
|
-
user_id: @user_info[:id]
|
128
|
-
}.reject { |x| x.nil? || x == '' }
|
129
|
-
end
|
130
|
-
|
131
|
-
def uploading_binary_info
|
132
|
-
{
|
133
|
-
key: @binary_cert[:key],
|
134
|
-
token: @binary_cert[:token],
|
135
|
-
file: File.new(@file_path, 'rb'),
|
136
|
-
# Custom variables
|
137
|
-
'x:name' => @app_info[:display_name] || @app_info[:name],
|
138
|
-
'x:build' => @app_info[:build],
|
139
|
-
'x:version' => @app_info[:version],
|
140
|
-
'x:changelog' => @changelog,
|
141
|
-
'x:release_type' => @app_info[:release_type],
|
142
|
-
'x:distribution_name' => @app_info[:distribution_name]
|
143
|
-
}
|
72
|
+
app_info_dict
|
144
73
|
end
|
145
74
|
|
146
75
|
def upload_device_info
|
@@ -151,7 +80,7 @@ module FIR
|
|
151
80
|
post fir_api[:udids_url], key: @binary_cert[:key],
|
152
81
|
udids: @app_info[:devices].join(','),
|
153
82
|
api_token: @token
|
154
|
-
|
83
|
+
end
|
155
84
|
|
156
85
|
def update_app_info
|
157
86
|
update_info = { short: @short, passwd: @passwd, is_opened: @is_opened }.compact
|
@@ -163,27 +92,33 @@ module FIR
|
|
163
92
|
patch fir_api[:app_url] + "/#{@app_id}", update_info.merge(api_token: @token)
|
164
93
|
end
|
165
94
|
|
95
|
+
# 获得 上传文件的授权信息
|
166
96
|
def fetch_uploading_info
|
167
97
|
logger.info "Fetching #{@app_info[:identifier]}@fir.im uploading info......"
|
168
98
|
logger.info "Uploading app: #{@app_info[:name]}-#{@app_info[:version]}(Build #{@app_info[:build]})"
|
169
99
|
|
170
|
-
post fir_api[:app_url],
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
100
|
+
post fir_api[:app_url],
|
101
|
+
{ type: @app_info[:type],
|
102
|
+
bundle_id: @app_info[:identifier],
|
103
|
+
fname: @file_path.split('/').last,
|
104
|
+
force_upload: options[:switch_to_qiniu] ? 'qiniu' : 'ali',
|
105
|
+
skip_icon_upload: @options[:skip_update_icon],
|
106
|
+
manual_callback: true,
|
107
|
+
protocol: 'https',
|
108
|
+
api_token: @token },
|
109
|
+
header: {
|
110
|
+
user_agent: 'new-cli'
|
111
|
+
}
|
179
112
|
end
|
180
113
|
|
181
114
|
def fetch_app_info
|
182
115
|
logger.info 'Fetch app info from fir.im'
|
183
116
|
|
184
|
-
|
185
|
-
write_app_info(id:
|
186
|
-
|
117
|
+
fir_app_info = get(fir_api[:app_url] + "/#{@app_id}", api_token: @token)
|
118
|
+
write_app_info(id: fir_app_info[:id],
|
119
|
+
short: fir_app_info[:short],
|
120
|
+
name: fir_app_info[:name])
|
121
|
+
fir_app_info
|
187
122
|
end
|
188
123
|
|
189
124
|
def upload_mapping_file_with_publish
|
@@ -197,62 +132,67 @@ module FIR
|
|
197
132
|
token: @token
|
198
133
|
end
|
199
134
|
|
200
|
-
def
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
logger.info "
|
205
|
-
|
206
|
-
@qrcode_path = "#{File.dirname(@file_path)}/fir-#{@app_info[:name]}.png"
|
207
|
-
FIR.generate_rqrcode(@download_url, @qrcode_path)
|
208
|
-
|
209
|
-
logger.info "Local qrcode file: #{@qrcode_path}" if @export_qrcode
|
135
|
+
def build_qrcode(download_url)
|
136
|
+
qrcode_path = "#{File.dirname(@file_path)}/fir-#{@app_info[:name]}.png"
|
137
|
+
FIR.generate_rqrcode(download_url, qrcode_path)
|
138
|
+
# 为何在这里必须生成 QrCode ? 因为要在 dingtalk 调用
|
139
|
+
logger.info "Local qrcode file: #{qrcode_path}" if @export_qrcode
|
140
|
+
qrcode_path
|
210
141
|
end
|
211
142
|
|
212
|
-
|
143
|
+
def build_download_url(short, release_id)
|
144
|
+
url = "#{fir_api[:domain]}/#{short}"
|
145
|
+
url += "?release_id=#{release_id}" if options[:need_release_id]
|
146
|
+
url
|
147
|
+
end
|
213
148
|
|
214
149
|
def options
|
215
150
|
@options
|
216
151
|
end
|
217
152
|
|
218
|
-
def force_pin_release
|
219
|
-
post "#{fir_api[:base_url]}/apps/#{@app_id}/releases/#{
|
153
|
+
def force_pin_release(release_id)
|
154
|
+
post "#{fir_api[:base_url]}/apps/#{@app_id}/releases/#{release_id}/force_set_history",
|
220
155
|
api_token: @token
|
221
156
|
end
|
222
157
|
|
223
|
-
def
|
224
|
-
|
225
|
-
end
|
158
|
+
def dingtalk_notifier(download_url, qrcode_path)
|
159
|
+
return if options[:dingtalk_access_token].blank?
|
226
160
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
"
|
232
|
-
"
|
233
|
-
"title": "#{title} uploaded",
|
234
|
-
"text": "#{title} uploaded at #{Time.now}\nurl: #{@download_url}\n ))})"
|
235
|
-
}
|
161
|
+
title = "#{@app_info[:name]}-#{@app_info[:version]}(Build #{@app_info[:build]})"
|
162
|
+
payload = {
|
163
|
+
"msgtype": 'markdown',
|
164
|
+
"markdown": {
|
165
|
+
"title": "#{title} uploaded",
|
166
|
+
"text": "#{title} uploaded at #{Time.now}\nurl: #{download_url}\n ))})"
|
236
167
|
}
|
237
|
-
|
238
|
-
|
239
|
-
|
168
|
+
}
|
169
|
+
url = "https://oapi.dingtalk.com/robot/send?access_token=#{options[:dingtalk_access_token]}"
|
170
|
+
|
171
|
+
# 用完了二维码, 就删了
|
172
|
+
File.delete(qrcode_path) unless @export_qrcode
|
173
|
+
|
174
|
+
DefaultRest.post(url, payload)
|
240
175
|
rescue StandardError => e
|
241
176
|
logger.warn "Dingtalk send error #{e.message}"
|
242
177
|
end
|
243
178
|
|
244
179
|
def initialize_publish_options(args, options)
|
245
|
-
@
|
246
|
-
@
|
247
|
-
@
|
248
|
-
@
|
249
|
-
@
|
250
|
-
@
|
251
|
-
@
|
180
|
+
@options = options
|
181
|
+
@file_path = File.absolute_path(args.first.to_s)
|
182
|
+
@file_type = File.extname(@file_path).delete('.')
|
183
|
+
@token = options[:token] || current_token
|
184
|
+
@changelog = read_changelog(options[:changelog]).to_s.to_utf8
|
185
|
+
@short = options[:short].to_s
|
186
|
+
@passwd = options[:password].to_s
|
187
|
+
@is_opened = @passwd.blank? ? options[:open] : false
|
252
188
|
@export_qrcode = !!options[:qrcode]
|
189
|
+
@app_info = send("#{@file_type}_info", @file_path, full_info: true)
|
190
|
+
@user_info = fetch_user_info(@token)
|
191
|
+
@uploading_info = fetch_uploading_info # 获得上传信息
|
192
|
+
@app_id = @uploading_info[:id]
|
253
193
|
|
254
|
-
@force_pin_history = options[:force_pin_history]
|
255
194
|
@skip_update_icon = options[:skip_update_icon]
|
195
|
+
@force_pin_history = options[:force_pin_history]
|
256
196
|
@specify_icon_file_path = File.absolute_path(options[:specify_icon_file]) unless options[:specify_icon_file].blank?
|
257
197
|
end
|
258
198
|
|
@@ -268,20 +208,5 @@ module FIR
|
|
268
208
|
check_token_cannot_be_blank(@token)
|
269
209
|
fetch_user_info(@token)
|
270
210
|
end
|
271
|
-
|
272
|
-
def convert_icon(origin_path)
|
273
|
-
# 兼容性不太好, 蔽掉转化图标
|
274
|
-
return origin_path
|
275
|
-
|
276
|
-
logger.info "Converting app's icon......"
|
277
|
-
|
278
|
-
if @app_info[:type] == 'ios'
|
279
|
-
output_path = Tempfile.new(['uncrushed_icon', '.png']).path
|
280
|
-
FIR::Parser::Pngcrush.uncrush_icon(origin_path, output_path)
|
281
|
-
origin_path = output_path if File.size(output_path) != 0
|
282
|
-
end
|
283
|
-
|
284
|
-
origin_path
|
285
|
-
end
|
286
211
|
end
|
287
212
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FIR
|
4
|
+
module Util
|
5
|
+
class Publisher
|
6
|
+
include FIR::Util
|
7
|
+
|
8
|
+
attr_accessor :args, :options
|
9
|
+
|
10
|
+
def initialize(args, options)
|
11
|
+
@file_path = File.absolute_path(args.first.to_s)
|
12
|
+
@file_type = File.extname(@file_path).delete('.')
|
13
|
+
@token = options[:token] || current_token
|
14
|
+
@changelog = read_changelog(options[:changelog]).to_s.to_utf8
|
15
|
+
@short = options[:short].to_s
|
16
|
+
@passwd = options[:password].to_s
|
17
|
+
@is_opened = @passwd.blank? ? options[:open] : false
|
18
|
+
@export_qrcode = !!options[:qrcode]
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def file_path
|
24
|
+
@file_path = File.absolute_path(args.first.to_s)
|
25
|
+
end
|
26
|
+
|
27
|
+
def read_changelog(changelog)
|
28
|
+
return if changelog.blank?
|
29
|
+
|
30
|
+
File.exist?(changelog) ? File.read(changelog) : changelog
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './app_uploader'
|
4
|
+
# require 'byebug'
|
5
|
+
|
6
|
+
module FIR
|
7
|
+
class QiniuUploader < AppUploader
|
8
|
+
def upload_icon
|
9
|
+
if skip_update_icon?
|
10
|
+
logger.info 'skip update icon...'
|
11
|
+
return
|
12
|
+
end
|
13
|
+
try_to_action('upload icon') do
|
14
|
+
# 拿到 icon 的授权
|
15
|
+
icon_url = uploading_info[:cert][:icon][:upload_url]
|
16
|
+
icon_info = uploading_icon_info
|
17
|
+
|
18
|
+
logger.debug "icon_url = #{icon_url}, icon_info = #{icon_info}"
|
19
|
+
|
20
|
+
_uploaded_info = post(icon_url, icon_info.merge(manual_callback: true),
|
21
|
+
params_to_json: false,
|
22
|
+
header: nil)
|
23
|
+
|
24
|
+
callback_to_api(callback_url, callback_icon_information)
|
25
|
+
end
|
26
|
+
rescue StandardError => e
|
27
|
+
# ignore icon error
|
28
|
+
logger.info "ignore icon upload error #{e.message}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def upload_binary
|
32
|
+
try_to_action 'upload binary ...' do
|
33
|
+
binary_url = uploading_info[:cert][:binary][:upload_url]
|
34
|
+
binary_info = uploading_binary_info
|
35
|
+
|
36
|
+
_uploaded_info = post(binary_url, binary_info.merge(manual_callback: true),
|
37
|
+
params_to_json: false,
|
38
|
+
header: nil)
|
39
|
+
|
40
|
+
callback_to_api(callback_url, callback_binary_information)
|
41
|
+
end
|
42
|
+
rescue StandardError => e
|
43
|
+
logger.error "binary upload to qiniu fail, #{e.message}"
|
44
|
+
exit 1
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
def callback_url
|
50
|
+
"#{fir_api[:base_url]}/auth/qiniu/callback"
|
51
|
+
end
|
52
|
+
|
53
|
+
# 七牛需要的 icon params
|
54
|
+
def uploading_icon_info
|
55
|
+
icon_cert = uploading_info[:cert][:icon]
|
56
|
+
{
|
57
|
+
key: icon_cert[:key],
|
58
|
+
token: icon_cert[:token],
|
59
|
+
file: File.new(icon_file_path, 'rb')
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
# 七牛需要的 binary params
|
64
|
+
def uploading_binary_info
|
65
|
+
binary_cert = uploading_info[:cert][:binary]
|
66
|
+
{
|
67
|
+
key: binary_cert[:key],
|
68
|
+
token: binary_cert[:token],
|
69
|
+
file: File.new(file_path, 'rb')
|
70
|
+
}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/fir/version.rb
CHANGED
data/luckin_coffee.png
ADDED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fir-cli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.beta
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- NaixSpirit
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-11-
|
12
|
+
date: 2019-11-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -198,6 +198,8 @@ files:
|
|
198
198
|
- lib/fir/patches/os_patch.rb
|
199
199
|
- lib/fir/patches/try.rb
|
200
200
|
- lib/fir/util.rb
|
201
|
+
- lib/fir/util/ali_uploader.rb
|
202
|
+
- lib/fir/util/app_uploader.rb
|
201
203
|
- lib/fir/util/build_apk.rb
|
202
204
|
- lib/fir/util/build_common.rb
|
203
205
|
- lib/fir/util/build_ipa.rb
|
@@ -213,9 +215,12 @@ files:
|
|
213
215
|
- lib/fir/util/parser/ipa.rb
|
214
216
|
- lib/fir/util/parser/pngcrush.rb
|
215
217
|
- lib/fir/util/publish.rb
|
218
|
+
- lib/fir/util/publisher.rb
|
219
|
+
- lib/fir/util/qiniu_uploader.rb
|
216
220
|
- lib/fir/version.rb
|
217
221
|
- lib/fir/xcode_wrapper.sh
|
218
222
|
- lib/fir_cli.rb
|
223
|
+
- luckin_coffee.png
|
219
224
|
- test/build_ipa_test.rb
|
220
225
|
- test/cases/test_apk.apk
|
221
226
|
- test/cases/test_apk_txt
|
@@ -234,12 +239,13 @@ metadata: {}
|
|
234
239
|
post_install_message: "\n ______________ ________ ____\n /
|
235
240
|
____/ _/ __ \\ / ____/ / / _/\n / /_ / // /_/ /_____/ / / / /
|
236
241
|
/\n / __/ _/ // _, _/_____/ /___/ /____/ /\n /_/ /___/_/ |_| \\____/_____/___/\n\n
|
237
|
-
\ ## 更新记录\n - (
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
fork, issue 和 pull
|
242
|
+
\ ## 更新记录\n - (2.0.0) publish 使用更快的存储商, 加速上传速度, 若感觉没以前可使用 switch_to_qiniu 恢复\n
|
243
|
+
\ - (1.7.4) 配合 fastlane-plugin-fir_cli 做了一些小优化\n - (1.7.3) 新增了 上传指定图标, 不上传图标 以及
|
244
|
+
将版本固定显示在下载页上\n - (1.7.2) 修正了无论是否加参数都固定出现二维码图片的bug\n - (1.7.1) 增加了 钉钉推送 , 增加了返回指定版本下载地址\n
|
245
|
+
\ - (1.7.0) 过期了ipa_build 功能, 增加了对 android manifest instant run 的兼容\n - (1.6.13)
|
246
|
+
上传图标逻辑修改\n - (1.6.12) 修复了部分机器没有默认安装 byebug 的问题\n - (1.6.11) 变化了 ruby gem 仓库地址\n
|
247
|
+
\ - [fir-cli](https://github.com/firhq/fir-cli) 已经开源\n - 欢迎 fork, issue 和 pull
|
248
|
+
request\n "
|
243
249
|
rdoc_options: []
|
244
250
|
require_paths:
|
245
251
|
- lib
|
@@ -250,9 +256,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
250
256
|
version: '0'
|
251
257
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
252
258
|
requirements:
|
253
|
-
- - "
|
259
|
+
- - ">"
|
254
260
|
- !ruby/object:Gem::Version
|
255
|
-
version:
|
261
|
+
version: 1.3.1
|
256
262
|
requirements: []
|
257
263
|
rubygems_version: 3.0.3
|
258
264
|
signing_key:
|