fir-cli 1.2.2 → 1.2.3

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.
@@ -1,14 +1,14 @@
1
1
  # encoding: utf-8
2
2
 
3
3
  module OS
4
-
5
4
  class << self
5
+
6
6
  def windows?
7
- (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
7
+ !(/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM).nil?
8
8
  end
9
9
 
10
10
  def mac?
11
- (/darwin/ =~ RUBY_PLATFORM) != nil
11
+ !(/darwin/ =~ RUBY_PLATFORM).nil?
12
12
  end
13
13
 
14
14
  def unix?
@@ -18,5 +18,11 @@ module OS
18
18
  def linux?
19
19
  OS.unix? && !OS.mac?
20
20
  end
21
+
22
+ def set_locale
23
+ system 'export LC_ALL=en_US.UTF-8'
24
+ system 'export LC_CTYPE=en_US.UTF-8'
25
+ system 'export LANG=en_US.UTF-8'
26
+ end
21
27
  end
22
28
  end
@@ -3,18 +3,17 @@
3
3
  module FIR
4
4
  module BuildApk
5
5
 
6
- def build_apk *args, options
6
+ def build_apk(*args, options)
7
7
  initialize_build_common_options(args, options)
8
8
 
9
9
  Dir.chdir(@build_dir)
10
10
 
11
- @build_cmd = initialize_apk_build_cmd(args, options)
12
- @output_path = options[:output].blank? ? "#{@build_dir}/build/outputs/apk" : File.absolute_path(options[:output].to_s)
11
+ @build_cmd = initialize_apk_build_cmd
13
12
 
14
13
  logger_info_and_run_build_command
15
14
 
16
- @builded_app_path ||= Dir[@output_path].find { |i| i =~ /release/ }
17
- @builded_app_path ||= Dir["#{@output_path}/*.apk"].first
15
+ output_apk
16
+ @builded_app_path = Dir["#{@output_path}/*.apk"].first
18
17
 
19
18
  publish_build_app if options.publish?
20
19
 
@@ -23,18 +22,41 @@ module FIR
23
22
 
24
23
  private
25
24
 
26
- def initialize_apk_build_cmd args, options
27
- check_build_gradle_exist
25
+ def initialize_apk_build_cmd
26
+ check_build_gradle_exist
28
27
 
29
- apk_build_cmd = "gradle clean;gradle build"
30
- apk_build_cmd
31
- end
28
+ apk_build_cmd = 'gradle clean;gradle build'
29
+ apk_build_cmd
30
+ end
31
+
32
+ def gradle_build_path
33
+ "#{@build_dir}/build/outputs/apk"
34
+ end
35
+
36
+ def output_apk
37
+ @builded_apk ||= Dir["#{gradle_build_path}/*.apk"].find { |i| i =~ /release/ }
38
+ @builded_apk ||= Dir["#{@build_dir}/*.apk"].find { |i| i =~ /release/ }
39
+
40
+ check_no_output_apk
41
+
42
+ apk_info = FIR.apk_info(@builded_apk)
43
+ apk_name = "#{apk_info[:name]}-#{apk_info[:version]}-Build-#{apk_info[:build]}"
32
44
 
33
- def check_build_gradle_exist
34
- unless File.exist?("#{@build_dir}/build.gradle")
35
- logger.error "The build.gradle is not exit, please use gradle and edit"
36
- exit 1
37
- end
45
+ FileUtils.cp(@builded_apk, "#{@output_path}/#{apk_name}.apk")
46
+ end
47
+
48
+ def check_no_output_apk
49
+ unless @builded_apk
50
+ logger.error 'Builded has no output apk'
51
+ exit 1
38
52
  end
53
+ end
54
+
55
+ def check_build_gradle_exist
56
+ return if File.exist?("#{@build_dir}/build.gradle")
57
+
58
+ logger.error "The build.gradle isn't exit, please use gradle and edit"
59
+ exit 1
60
+ end
39
61
  end
40
62
  end
@@ -3,17 +3,31 @@
3
3
  module FIR
4
4
  module BuildCommon
5
5
 
6
- def initialize_build_common_options args, options
6
+ def initialize_build_common_options(args, options)
7
+ @build_dir = initialize_build_dir(args)
8
+ @output_path = initialize_output_path(options)
9
+ @token = options[:token] || current_token
10
+ @changelog = options[:changelog].to_s
11
+ @short = options[:short].to_s
12
+ @proj = options[:proj].to_s
13
+ end
14
+
15
+ def initialize_build_dir(args)
7
16
  if args.first.blank? || !File.exist?(args.first)
8
- @build_dir = Dir.pwd
17
+ Dir.pwd
9
18
  else
10
- @build_dir = File.absolute_path(args.shift.to_s) # pop the first param
19
+ File.absolute_path(args.shift.to_s) # pop the first param
11
20
  end
21
+ end
12
22
 
13
- @token = options[:token] || current_token
14
- @changelog = options[:changelog].to_s
15
- @short = options[:short].to_s
16
- @proj = options[:proj].to_s
23
+ def initialize_output_path(options)
24
+ if options[:output].blank?
25
+ output_path = "#{@build_dir}/fir_build"
26
+ FileUtils.mkdir_p(output_path) unless File.exist?(output_path)
27
+ output_path
28
+ else
29
+ File.absolute_path(options[:output].to_s)
30
+ end
17
31
  end
18
32
 
19
33
  def publish_build_app
@@ -26,10 +40,26 @@ module FIR
26
40
  def logger_info_and_run_build_command
27
41
  puts @build_cmd if $DEBUG
28
42
 
29
- logger.info "Building......"
43
+ logger.info 'Building......'
30
44
  logger_info_dividing_line
31
45
 
32
46
  logger.info `#{@build_cmd}`
33
47
  end
48
+
49
+ # split ['a=1', 'b=2'] => { 'a' => '1', 'b' => '2' }
50
+ def split_assignment_array_to_hash(arr)
51
+ hash = {}
52
+ arr.each do |assignment|
53
+ k, v = assignment.split('=', 2).map(&:strip)
54
+ hash[k] = v
55
+ end
56
+
57
+ hash
58
+ end
59
+
60
+ # convert { "a" => "1", "b" => "2" } => "a='1' b='2'"
61
+ def convert_hash_to_assignment_string(hash)
62
+ hash.collect { |k, v| "#{k}='#{v}'" }.join(' ')
63
+ end
34
64
  end
35
65
  end
@@ -3,17 +3,17 @@
3
3
  module FIR
4
4
  module BuildIpa
5
5
 
6
- def build_ipa *args, options
6
+ def build_ipa(*args, options)
7
7
  initialize_build_common_options(args, options)
8
8
 
9
9
  @build_tmp_dir = Dir.mktmpdir
10
- @output_path = options[:output].blank? ? "#{@build_dir}/fir_build_ipa" : File.absolute_path(options[:output].to_s)
11
10
  @build_cmd = initialize_ipa_build_cmd(args, options)
12
11
 
13
12
  logger_info_and_run_build_command
14
13
 
15
14
  output_ipa
16
15
  @builded_app_path = Dir["#{@output_path}/*.ipa"].first
16
+
17
17
  publish_build_app if options.publish?
18
18
  upload_build_dsym_mapping_file if options.mapping?
19
19
 
@@ -22,128 +22,123 @@ module FIR
22
22
 
23
23
  private
24
24
 
25
- def initialize_ipa_build_cmd args, options
26
- ipa_build_cmd = "xcodebuild build -sdk iphoneos"
25
+ def initialize_ipa_build_cmd(args, options)
26
+ @configuration = options[:configuration]
27
+ @wrapper_name = File.basename(options[:name].to_s, '.*') + '.app' unless options[:name].blank?
28
+ @target_name = options[:target]
29
+ @scheme_name = options[:scheme]
30
+ @dsym_name = @wrapper_name + '.dSYM' unless @wrapper_name.blank?
31
+
32
+ build_cmd = 'xcodebuild build -sdk iphoneos'
33
+ build_cmd += initialize_xcode_build_path(options)
34
+ build_cmd += " -configuration '#{@configuration}'" unless @configuration.blank?
35
+ build_cmd += " -target '#{@target_name}'" unless @target_name.blank?
36
+ build_cmd += " #{ipa_custom_settings(args)} 2>&1"
37
+ build_cmd
38
+ end
27
39
 
28
- @configuration = options[:configuration]
29
- @wrapper_name = File.basename(options[:name].to_s, '.*') + '.app' unless options[:name].blank?
30
- @target_name = options[:target]
31
- @scheme_name = options[:scheme]
32
- @dsym_name = @wrapper_name + '.dSYM' unless @wrapper_name.blank?
40
+ def ipa_custom_settings(args)
41
+ custom_settings = split_assignment_array_to_hash(args)
33
42
 
34
- ipa_build_cmd += initialize_xcode_build_path(options)
35
- ipa_build_cmd += " -configuration '#{@configuration}'" unless @configuration.blank?
36
- ipa_build_cmd += " -target '#{@target_name}'" unless @target_name.blank?
37
- ipa_build_cmd += " #{ipa_custom_settings(args)} 2>&1"
43
+ setting_str = convert_hash_to_assignment_string(custom_settings)
44
+ setting_str += " WRAPPER_NAME='#{@wrapper_name}'" unless @wrapper_name.blank?
45
+ setting_str += " TARGET_BUILD_DIR='#{@build_tmp_dir}'" unless custom_settings['TARGET_BUILD_DIR']
46
+ setting_str += " CONFIGURATION_BUILD_DIR='#{@build_tmp_dir}'" unless custom_settings['CONFIGURATION_BUILD_DIR']
47
+ setting_str += " DWARF_DSYM_FOLDER_PATH='#{@output_path}'" unless custom_settings['DWARF_DSYM_FOLDER_PATH']
48
+ setting_str += " DWARF_DSYM_FILE_NAME='#{@dsym_name}'" unless @dsym_name.blank?
49
+ setting_str
50
+ end
38
51
 
39
- ipa_build_cmd
40
- end
52
+ def output_ipa
53
+ Dir.chdir(@build_tmp_dir) do
54
+ apps = Dir['*.app']
55
+ check_no_output_app(apps)
41
56
 
42
- def ipa_custom_settings args
43
- custom_settings = parse_ipa_custom_settings(args)
44
-
45
- # convert { "a" => "1", "b" => "2" } => "a='1' b='2'"
46
- setting_str = custom_settings.collect { |k, v| "#{k}='#{v}'" }.join(' ')
47
- setting_str += " WRAPPER_NAME='#{@wrapper_name}'" unless @wrapper_name.blank?
48
- setting_str += " TARGET_BUILD_DIR='#{@build_tmp_dir}'" unless custom_settings['TARGET_BUILD_DIR']
49
- setting_str += " CONFIGURATION_BUILD_DIR='#{@build_tmp_dir}'" unless custom_settings['CONFIGURATION_BUILD_DIR']
50
- setting_str += " DWARF_DSYM_FOLDER_PATH='#{@output_path}'" unless custom_settings['DWARF_DSYM_FOLDER_PATH']
51
- setting_str += " DWARF_DSYM_FILE_NAME='#{@dsym_name}'" unless @dsym_name.blank?
52
- setting_str
53
- end
57
+ apps.each do |app|
58
+ temp_ipa = zip_app2ipa(File.join(@build_tmp_dir, app))
59
+ ipa_info = FIR.ipa_info(temp_ipa)
60
+ ipa_name = "#{ipa_info[:name]}-#{ipa_info[:version]}-Build-#{ipa_info[:build]}"
54
61
 
55
- def output_ipa
56
- FileUtils.mkdir_p(@output_path) unless File.exist?(@output_path)
57
- Dir.chdir(@build_tmp_dir) do
58
- apps = Dir["*.app"]
59
- if apps.length == 0
60
- logger.error "Builded has no output app, Can not be packaged"
61
- exit 1
62
- end
63
-
64
- apps.each do |app|
65
- ipa_path = File.join(@output_path, "#{File.basename(app, '.app')}.ipa")
66
- zip_app2ipa(File.join(@build_tmp_dir, app), ipa_path)
67
- end
62
+ FileUtils.cp(temp_ipa, "#{@output_path}/#{ipa_name}.ipa")
68
63
  end
69
-
70
- logger.info "Build Success"
71
64
  end
72
65
 
73
- def upload_build_dsym_mapping_file
74
- logger_info_blank_line
66
+ logger.info 'Build Success'
67
+ end
75
68
 
76
- @app_info = ipa_info(@builded_app_path)
77
- @mapping_file = Dir["#{@output_path}/*.dSYM/Contents/Resources/DWARF/*"].first
69
+ def upload_build_dsym_mapping_file
70
+ logger_info_blank_line
78
71
 
79
- mapping @mapping_file, proj: @proj,
80
- build: @app_info[:build],
81
- version: @app_info[:version],
82
- token: @token
83
- end
72
+ @app_info = ipa_info(@builded_app_path)
73
+ @mapping_file = Dir["#{@output_path}/*.dSYM/Contents/Resources/DWARF/*"].first
84
74
 
85
- def initialize_xcode_build_path options
86
- if options.workspace?
87
- workspace = check_and_find_ios_xcworkspace(@build_dir)
88
- check_ios_scheme(@scheme_name)
75
+ mapping @mapping_file, proj: @proj,
76
+ build: @app_info[:build],
77
+ version: @app_info[:version],
78
+ token: @token
79
+ end
89
80
 
90
- return " -workspace '#{workspace}' -scheme '#{@scheme_name}'"
91
- else
92
- project = check_and_find_ios_xcodeproj(@build_dir)
81
+ def initialize_xcode_build_path(options)
82
+ if options.workspace?
83
+ workspace = check_and_find_ios_xcworkspace(@build_dir)
84
+ check_ios_scheme(@scheme_name)
93
85
 
94
- return " -project '#{project}'"
95
- end
86
+ return " -workspace '#{workspace}' -scheme '#{@scheme_name}'"
87
+ else
88
+ project = check_and_find_ios_xcodeproj(@build_dir)
89
+
90
+ return " -project '#{project}'"
96
91
  end
92
+ end
97
93
 
98
- %w(xcodeproj xcworkspace).each do |workplace|
99
- define_method "check_and_find_ios_#{workplace}" do |path|
100
- unless File.exist?(path)
101
- logger.error "The first param BUILD_DIR must be a #{workplace} directory"
102
- exit 1
103
- end
94
+ %w(xcodeproj xcworkspace).each do |workplace|
95
+ define_method "check_and_find_ios_#{workplace}" do |path|
96
+ unless File.exist?(path)
97
+ logger.error "The first param BUILD_DIR must be a #{workplace} directory"
98
+ exit 1
99
+ end
104
100
 
105
- if File.extname(path) == ".#{workplace}"
106
- build_dir = path
107
- else
108
- build_dir = Dir["#{path}/*.#{workplace}"].first
109
- if build_dir.blank?
110
- logger.error "The #{workplace} file is missing, check the BUILD_DIR"
111
- exit 1
112
- end
101
+ if File.extname(path) == ".#{workplace}"
102
+ build_dir = path
103
+ else
104
+ build_dir = Dir["#{path}/*.#{workplace}"].first
105
+ if build_dir.blank?
106
+ logger.error "The #{workplace} file is missing, check the BUILD_DIR"
107
+ exit 1
113
108
  end
114
-
115
- build_dir
116
109
  end
110
+
111
+ build_dir
117
112
  end
113
+ end
118
114
 
119
- def check_ios_scheme scheme_name
120
- if scheme_name.blank?
121
- logger.error "Must provide a scheme by `-S` option when build a workspace"
122
- exit 1
123
- end
115
+ def check_ios_scheme(scheme_name)
116
+ if scheme_name.blank?
117
+ logger.error 'Must provide a scheme by `-S` option when build a workspace'
118
+ exit 1
124
119
  end
120
+ end
125
121
 
126
- def zip_app2ipa app_path, ipa_path
127
- Dir.mktmpdir do |tmpdir|
128
- Dir.chdir(tmpdir) do
129
- Dir.mkdir("Payload")
130
- FileUtils.cp_r(app_path, "Payload")
131
- system("rm -rf #{ipa_path}") if File.file? ipa_path
132
- system("zip -qr #{ipa_path} Payload")
133
- end
134
- end
122
+ def check_no_output_app(apps)
123
+ if apps.length == 0
124
+ logger.error 'Builded has no output app, Can not be packaged'
125
+ exit 1
135
126
  end
127
+ end
136
128
 
137
- # convert ['a=1', 'b=2'] => { 'a' => '1', 'b' => '2' }
138
- def parse_ipa_custom_settings args
139
- hash = {}
140
- args.each do |setting|
141
- k, v = setting.split('=', 2).map(&:strip)
142
- hash[k] = v
143
- end
129
+ def zip_app2ipa(app_path)
130
+ ipa_path = Tempfile.new(['temp', '.ipa']).path
144
131
 
145
- hash
132
+ Dir.mktmpdir do |tmpdir|
133
+ Dir.chdir(tmpdir) do
134
+ Dir.mkdir('Payload')
135
+ FileUtils.cp_r(app_path, 'Payload')
136
+ system("rm -rf #{ipa_path}") if File.file?(ipa_path)
137
+ system("zip -qr #{ipa_path} Payload")
138
+ end
146
139
  end
147
140
 
141
+ ipa_path
142
+ end
148
143
  end
149
144
  end
@@ -3,7 +3,7 @@
3
3
  module FIR
4
4
  module Config
5
5
  CONFIG_PATH = "#{ENV['HOME']}/.fir-cli"
6
- API_YML_PATH = File.expand_path("../../", __FILE__) + '/api.yml'
6
+ API_YML_PATH = File.expand_path('../../', __FILE__) + '/api.yml'
7
7
  APP_FILE_TYPE = %w(.ipa .apk).freeze
8
8
 
9
9
  def fir_api
@@ -15,14 +15,15 @@ module FIR
15
15
  end
16
16
 
17
17
  def config
18
- @config ||= YAML.load_file(CONFIG_PATH).deep_symbolize_keys if File.exist?(CONFIG_PATH)
18
+ return unless File.exist?(CONFIG_PATH)
19
+ @config ||= YAML.load_file(CONFIG_PATH).deep_symbolize_keys
19
20
  end
20
21
 
21
22
  def reload_config
22
23
  @config = YAML.load_file(CONFIG_PATH).deep_symbolize_keys
23
24
  end
24
25
 
25
- def write_config hash
26
+ def write_config(hash)
26
27
  File.open(CONFIG_PATH, 'w+') { |f| f << YAML.dump(hash) }
27
28
  end
28
29
 
data/lib/fir/util/http.rb CHANGED
@@ -2,10 +2,9 @@
2
2
 
3
3
  module FIR
4
4
  module Http
5
-
6
5
  DEFAULT_TIMEOUT = 300
7
6
 
8
- def get url, params = {}
7
+ def get(url, params = {})
9
8
  begin
10
9
  res = ::RestClient::Request.execute(
11
10
  method: :get,
@@ -14,11 +13,11 @@ module FIR
14
13
  headers: default_headers.merge(params: params)
15
14
  )
16
15
  rescue => e
17
- logger.error e.message.to_s + " - " + e.response.to_s
16
+ logger.error e.message.to_s + ' - ' + e.response.to_s
18
17
  exit 1
19
18
  end
20
19
 
21
- JSON.parse(res.body.force_encoding("UTF-8"), symbolize_names: true)
20
+ JSON.parse(res.body.force_encoding('UTF-8'), symbolize_names: true)
22
21
  end
23
22
 
24
23
  %w(post patch put).each do |method|
@@ -32,18 +31,18 @@ module FIR
32
31
  headers: default_headers
33
32
  )
34
33
  rescue => e
35
- logger.error e.message.to_s + " - " + e.response.to_s
34
+ logger.error e.message.to_s + ' - ' + e.response.to_s
36
35
  exit 1
37
36
  end
38
37
 
39
- JSON.parse(res.body.force_encoding("UTF-8"), symbolize_names: true)
38
+ JSON.parse(res.body.force_encoding('UTF-8'), symbolize_names: true)
40
39
  end
41
40
  end
42
41
 
43
42
  private
44
43
 
45
- def default_headers
46
- { content_type: :json, source: 'fir-cli', version: FIR::VERSION }
47
- end
44
+ def default_headers
45
+ { content_type: :json, source: 'fir-cli', version: FIR::VERSION }
46
+ end
48
47
  end
49
48
  end
data/lib/fir/util/info.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module FIR
4
4
  module Info
5
5
 
6
- def info *args, options
6
+ def info(*args, options)
7
7
  file_path = File.absolute_path(args.first.to_s)
8
8
  is_all = !options[:all].blank?
9
9
 
@@ -15,66 +15,24 @@ module FIR
15
15
  logger.info "Analyzing #{file_type} file......"
16
16
  logger_info_dividing_line
17
17
 
18
- app_info = send("#{file_type}_info", file_path, is_all)
18
+ app_info = send("#{file_type}_info", file_path, full_info: is_all)
19
19
  app_info.each { |k, v| logger.info "#{k}: #{v}" }
20
20
 
21
21
  logger_info_blank_line
22
22
  end
23
23
 
24
- def ipa_info ipa_path, is_all = false
25
- ipa = FIR::Parser::Ipa.new(ipa_path)
26
- app = ipa.app
27
-
28
- info = {
29
- type: 'ios',
30
- identifier: app.identifier,
31
- name: app.name,
32
- display_name: app.display_name,
33
- build: app.version.to_s,
34
- version: app.short_version.to_s,
35
- devices: app.devices,
36
- release_type: app.release_type || ipa.release_type,
37
- distribution_name: app.distribution_name
38
- }
39
-
40
- if is_all
41
- info[:icons] = []
42
- app.icons.each do |icon|
43
- tmp_icon_path = "#{Dir.tmpdir}/icon-#{SecureRandom.hex[4..9]}.png"
44
- FileUtils.cp(icon, tmp_icon_path)
45
- info[:icons] << tmp_icon_path
46
- end
47
-
48
- app.hide_developer_certificates
49
-
50
- info[:plist] = app.info
51
- info[:mobileprovision] = app.mobileprovision
52
- end
24
+ def ipa_info(ipa_path, options = {})
25
+ ipa = FIR::Parser::Ipa.new(ipa_path)
26
+ app = ipa.app
27
+ info = app.full_info(options).merge(release_type: ipa.release_type)
53
28
 
54
29
  ipa.cleanup
55
30
  info
56
31
  end
57
32
 
58
- def apk_info apk_path, is_all = false
59
- apk = Android::Apk.new(apk_path)
60
- info = {
61
- type: 'android',
62
- identifier: apk.manifest.package_name,
63
- name: apk.label,
64
- build: apk.manifest.version_code.to_s,
65
- version: apk.manifest.version_name.to_s
66
- }
67
-
68
- # apk.icon is a hash, { icon_name: icon_data }
69
- if is_all
70
- info[:icons] = []
71
- apk.icon.each do |name, data|
72
- tmp_icon_path = "#{Dir.tmpdir}/icon-#{SecureRandom.hex[4..9]}.png"
73
- File.open(tmp_icon_path, 'w+') { |f| f << data }
74
- info[:icons] << tmp_icon_path
75
- end
76
- end
77
-
33
+ def apk_info(apk_path, options = {})
34
+ apk = FIR::Parser::Apk.new(apk_path)
35
+ info = apk.full_info(options)
78
36
  info
79
37
  end
80
38
  end
@@ -3,7 +3,7 @@
3
3
  module FIR
4
4
  module Login
5
5
 
6
- def login token
6
+ def login(token)
7
7
  check_token_cannot_be_blank token
8
8
 
9
9
  user_info = fetch_user_info(token)