fir-cli 1.2.2 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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)