fastlane-plugin-match_keystore 0.1.14 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d5b1878b6e0f6453f4c62eab321b2080210dcaa93fafcb04b14ac9819e7f996e
4
- data.tar.gz: 18748d40e3d7c6dbe63179c8bbc726b5284049c25349d28c5ad1e76d529c21de
3
+ metadata.gz: 554236b09184bb0b50f9209ae0de3ba469e58bd66a5c0cc28880e8e259f3721a
4
+ data.tar.gz: b6c33c5ec05a4f72e2cbc04db6e64b2048b361408bedbaa9fe58e52908cbc5b3
5
5
  SHA512:
6
- metadata.gz: 31e657e39efa81b9141182a75f8df3ee5cc1704a6b1ed2b8526d50ee1e361aaf7d74ed3b8a04771e323a215850051eba4b3f6f932c9808ec8cf57bc70ad894f7
7
- data.tar.gz: 1dce9a11c73f7921cea57a5953b7b64b2497bb401864cc906386617f342f3792a8c360d81d6709c3538b4282b6e9462c3fb7d5a87b215cebaffc950448bf6d76
6
+ metadata.gz: f99fe0dbb68617919711aaded1054d931a85dbc8730f2ac69fd289341389014fb02a25cc58b833c148991e85bb871cf360450821cff284427c60c6d7000f0f42
7
+ data.tar.gz: c9de35e3c6cae52e1dca0d78823079f1239bc890df3c5865fb288f1fbe666e181ddba39d5de9136bb82622bdfc380c79b5b045907ca2e5d5df95df87448222b4
data/README.md CHANGED
@@ -2,6 +2,13 @@
2
2
 
3
3
  [![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-match_keystore)
4
4
 
5
+ ## Machine requirements
6
+
7
+ * OpenSSL 1.1.1 min OR LibreSSL 2.9 min installed
8
+ * Git installed
9
+ * Android SDK & Build-tools installed
10
+ * ANDROID_HOME environment variable defined
11
+
5
12
  ## Getting Started
6
13
 
7
14
  This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-match_keystore`, add it to your project by running:
@@ -2,6 +2,7 @@ require 'fastlane/action'
2
2
  require 'fileutils'
3
3
  require 'os'
4
4
  require 'json'
5
+ require 'pry'
5
6
  require 'digest'
6
7
  require_relative '../helper/match_keystore_helper'
7
8
 
@@ -15,11 +16,19 @@ module Fastlane
15
16
 
16
17
  class MatchKeystoreAction < Action
17
18
 
19
+ KEY_VERSION = "2"
20
+ OPENSSL_BIN_PATH_MAC = "/usr/local/opt/openssl@1.1/bin"
21
+
18
22
  def self.to_md5(value)
19
23
  hash_value = Digest::MD5.hexdigest value
20
24
  hash_value
21
25
  end
22
26
 
27
+ def self.sha512(value)
28
+ hash_value = Digest::SHA512.hexdigest value
29
+ hash_value
30
+ end
31
+
23
32
  def self.load_json(json_path)
24
33
  file = File.read(json_path)
25
34
  data_hash = JSON.parse(file)
@@ -53,69 +62,259 @@ module Fastlane
53
62
  android_home
54
63
  end
55
64
 
56
- def self.get_build_tools
65
+ def self.get_build_tools_version(targeted_version)
66
+ path = self.get_build_tools(targeted_version)
67
+ version = path.split('/').last
68
+ version
69
+ end
70
+
71
+ def self.get_build_tools(targeted_version)
57
72
  android_home = self.get_android_home()
58
73
  build_tools_root = File.join(android_home, '/build-tools')
59
74
 
60
- sub_dirs = Dir.glob(File.join(build_tools_root, '*', ''))
61
- build_tools_last_version = ''
62
- for sub_dir in sub_dirs
63
- build_tools_last_version = sub_dir
75
+ build_tools_path = ""
76
+ if !targeted_version.to_s.strip.empty?
77
+ build_tools_path = File.join(build_tools_root, "/#{targeted_version}/")
64
78
  end
65
79
 
66
- build_tools_last_version
80
+ if !File.directory?(build_tools_path)
81
+ sub_dirs = Dir.glob(File.join(build_tools_root, '*', ''))
82
+ build_tools_last_version = ''
83
+ for sub_dir in sub_dirs
84
+ build_tools_last_version = sub_dir
85
+ end
86
+ build_tools_path = build_tools_last_version
87
+ end
88
+
89
+ build_tools_path
67
90
  end
68
91
 
69
- def self.check_openssl_version
70
- output = `openssl version`
71
- if !output.start_with?("OpenSSL")
72
- raise "Please install OpenSSL 1.1.1 at least https://www.openssl.org/"
92
+ def self.check_ssl_version(forceOpenSSL)
93
+ libressl_min = '2.9'
94
+ openssl_min = '1.1.1'
95
+
96
+ openssl = self.openssl(forceOpenSSL)
97
+ output = `#{openssl} version`
98
+ if !output.start_with?("LibreSSL") && !output.start_with?("OpenSSL")
99
+ raise "Please install OpenSSL '#{openssl_min}' at least OR LibreSSL #{libressl_min}' at least"
73
100
  end
74
- UI.message("OpenSSL version: " + output.strip)
101
+ UI.message("SSL/TLS protocol library: '#{output.strip!}'")
102
+
103
+ # Check minimum verion:
104
+ vesion = output.to_str.scan(/[0-9\.]{1,}/).first
105
+ UI.message("SSL/TLS protocol version: '#{vesion}'")
106
+ if self.is_libre_ssl(forceOpenSSL)
107
+ if Gem::Version.new(vesion) < Gem::Version.new(libressl_min)
108
+ raise "Minimum version for LibreSSL is '#{libressl_min}', please update it. Use homebrew is your are Mac user, and update ~/.bah_profile or ~/.zprofile"
109
+ end
110
+ else
111
+ if Gem::Version.new(vesion) > Gem::Version.new(openssl_min)
112
+ raise "Minimum version for OpenSSL is '#{openssl_min}' please update it. Use homebrew is your are Mac user, and update ~/.bah_profile or ~/.zprofile"
113
+ end
114
+ end
115
+
116
+ output.strip
75
117
  end
76
118
 
77
- def self.gen_key(key_path, password)
119
+ def self.openssl(forceOpenSSL)
120
+ if forceOpenSSL
121
+ output = "#{self::OPENSSL_BIN_PATH_MAC}/openssl"
122
+ else
123
+ output = "openssl"
124
+ end
125
+ output
126
+ end
127
+
128
+ def self.is_libre_ssl(forceOpenSSL)
129
+ result = false
130
+ openssl = self.openssl(forceOpenSSL)
131
+ output = `#{openssl} version`
132
+ if output.start_with?("LibreSSL")
133
+ result = true
134
+ end
135
+ result
136
+ end
137
+
138
+ def self.gen_key(key_path, password, compat_key)
78
139
  `rm -f '#{key_path}'`
79
- `echo "#{password}" | openssl dgst -sha512 | awk '{print $2}' | cut -c1-128 > '#{key_path}'`
140
+ shaValue = self.sha512(password)
141
+ # Backward-compatibility
142
+ if compat_key == "1"
143
+ `echo "#{password}" | openssl dgst -sha512 | awk '{print $2}' | cut -c1-128 > '#{key_path}'`
144
+ else
145
+ `echo "#{shaValue}" > '#{key_path}'`
146
+ end
80
147
  end
81
148
 
82
- def self.encrypt_file(clear_file, encrypt_file, key_path)
149
+ def self.encrypt_file(clear_file, encrypt_file, key_path, forceOpenSSL)
83
150
  `rm -f '#{encrypt_file}'`
84
- `openssl enc -aes-256-cbc -salt -pbkdf2 -in '#{clear_file}' -out '#{encrypt_file}' -pass file:'#{key_path}'`
151
+ libre_ssl = self.is_libre_ssl(forceOpenSSL)
152
+ openssl_bin = self.openssl(forceOpenSSL)
153
+ `#{openssl_bin} enc -aes-256-cbc -salt -pbkdf2 -in '#{clear_file}' -out '#{encrypt_file}' -pass file:'#{key_path}'`
85
154
  end
86
155
 
87
- def self.decrypt_file(encrypt_file, clear_file, key_path)
156
+ def self.decrypt_file(encrypt_file, clear_file, key_path, forceOpenSSL)
88
157
  `rm -f '#{clear_file}'`
89
- `openssl enc -d -aes-256-cbc -pbkdf2 -in '#{encrypt_file}' -out '#{clear_file}' -pass file:'#{key_path}'`
158
+ libre_ssl = self.is_libre_ssl(forceOpenSSL)
159
+ openssl_bin = self.openssl(forceOpenSSL)
160
+ `#{openssl_bin} enc -d -aes-256-cbc -pbkdf2 -in '#{encrypt_file}' -out '#{clear_file}' -pass file:'#{key_path}'`
161
+ end
162
+
163
+ def self.assert_equals(test_name, excepted, value)
164
+ puts "Unit Test: #{test_name}"
165
+ if value != excepted
166
+ puts " - Excepted: #{excepted}"
167
+ puts " - Returned: #{value}"
168
+ raise "Unit Test - #{test_name} error!"
169
+ else
170
+ puts " - OK"
171
+ end
90
172
  end
91
173
 
92
- def self.sign_apk(apk_path, keystore_path, key_password, alias_name, alias_password, zip_align)
174
+ def self.test_security
93
175
 
94
- build_tools_path = self.get_build_tools()
176
+ self.check_ssl_version(false)
177
+
178
+ # Clear temp files
179
+ temp_dir = File.join(Dir.pwd, '/temp/')
180
+ FileUtils.rm_rf(temp_dir)
181
+ Dir.mkdir(temp_dir)
182
+
183
+ fakeValue = "4esfsf4dsfds!efs5ZDOJF"
184
+ # Check MD5
185
+ md5value = self.to_md5(fakeValue)
186
+ excepted = "1c815cd208fe08076c9e7b6595d121d1"
187
+ self.assert_equals("MD5", excepted, md5value)
188
+
189
+ # Check SHA-512
190
+ shaValue = self.sha512(fakeValue)
191
+ excepted = "cc6a7b0d89cc61c053f7018a305672bdb82bc07e5015f64bb063d9662be4ec81ec8afa819b009de266482b6bd56b7068def2524c32f5b5d4d9db49ee4578499d"
192
+ self.assert_equals("SHA-512", excepted, shaValue)
193
+
194
+ # Check SHA-512-File
195
+ key_path = File.join(Dir.pwd, '/temp/key.txt')
196
+ self.gen_key(key_path, fakeValue, false)
197
+ shaValue = self.get_file_content(key_path).strip!
198
+ excepted = "cc6a7b0d89cc61c053f7018a305672bdb82bc07e5015f64bb063d9662be4ec81ec8afa819b009de266482b6bd56b7068def2524c32f5b5d4d9db49ee4578499d"
199
+ self.assert_equals("SHA-512-File", excepted, shaValue)
200
+
201
+
202
+ # Check LibreSSL
203
+ result = self.is_libre_ssl(false)
204
+ self.assert_equals("Is-LibreSSL", true, result)
205
+ result = self.is_libre_ssl(true)
206
+ self.assert_equals("Is-LibreSSL", false, result)
207
+
208
+ # Encrypt OpenSSL
209
+ clear_file = File.join(Dir.pwd, '/temp/clear.txt')
210
+ openssl_encrypt_file = File.join(Dir.pwd, '/temp/openssl_encrypted.txt')
211
+ self.content_to_file(clear_file, fakeValue)
212
+ self.encrypt_file(clear_file, openssl_encrypt_file, key_path, true)
213
+ result = File.file?(openssl_encrypt_file) && File.size(openssl_encrypt_file) > 10
214
+ self.assert_equals("Encrypt-OpenSSL", true, result)
215
+
216
+ # Encrypt LibreSSL
217
+ encrypt_file_libre = File.join(Dir.pwd, '/temp/libressl_encrypted.txt')
218
+ self.content_to_file(clear_file, fakeValue)
219
+ self.encrypt_file(clear_file, encrypt_file_libre, key_path, false)
220
+ result = File.file?(encrypt_file_libre) && File.size(encrypt_file_libre) > 10
221
+ self.assert_equals("Encrypt-LibreSSL", true, result)
222
+
223
+ # exit!
224
+
225
+ # Decrypt OpenSSL (from OpenSSL)
226
+ openssl_clear_file = File.join(Dir.pwd, '/temp/openssl_clear.txt')
227
+ self.decrypt_file(openssl_encrypt_file, openssl_clear_file, key_path, true)
228
+ decrypted = self.get_file_content(openssl_clear_file).strip!
229
+ self.assert_equals("Decrypt-OpenSSL", fakeValue, decrypted)
230
+
231
+ # Decrypt LibreSSL (from LibreSSL)
232
+ libressl_clear_file = File.join(Dir.pwd, '/temp/libressl_clear.txt')
233
+ self.decrypt_file(encrypt_file_libre, libressl_clear_file, key_path, false)
234
+ decrypted = self.get_file_content(libressl_clear_file).strip!
235
+ self.assert_equals("Decrypt-LibreSSL", fakeValue, decrypted)
236
+
237
+ # Decrypt LibreSSL (from OpenSSL)
238
+ libressl_clear_file = File.join(Dir.pwd, '/temp/libressl_from_openssl_clear.txt')
239
+ self.decrypt_file(openssl_encrypt_file, libressl_clear_file, key_path, false)
240
+ decrypted = self.get_file_content(libressl_clear_file).strip!
241
+ self.assert_equals("Decrypt-LibreSSL-from-OpenSSL", fakeValue, decrypted)
242
+
243
+ # Decrypt OpenSSL (from LibreSSL)
244
+ openssl_clear_file = File.join(Dir.pwd, '/temp/openssl_from_libressl_clear.txt')
245
+ self.decrypt_file(encrypt_file_libre, openssl_clear_file, key_path, true)
246
+ decrypted = self.get_file_content(openssl_clear_file).strip!
247
+ self.assert_equals("Decrypt-OpenSSL-from-LibreSSL", fakeValue, decrypted)
248
+
249
+ end
250
+
251
+ def self.sign_apk(apk_path, keystore_path, key_password, alias_name, alias_password, zip_align, version_targeted)
252
+
253
+ build_tools_path = self.get_build_tools(version_targeted)
95
254
  UI.message("Build-tools path: #{build_tools_path}")
96
255
 
97
- # https://developer.android.com/studio/command-line/zipalign
98
- if zip_align == true
99
- apk_path_aligned = apk_path.gsub(".apk", "-aligned.apk")
100
- `rm -f '#{apk_path_aligned}'`
101
- UI.message("Aligning APK (zipalign): #{apk_path_aligned}")
102
- `#{build_tools_path}zipalign -f -v 4 '#{apk_path}' '#{apk_path_aligned}'`
103
- else
104
- UI.message("No zip align!")
105
- apk_path_aligned = apk_path
106
- end
256
+ # https://developer.android.com/studio/command-line/apksigner
107
257
  apk_path_signed = apk_path.gsub(".apk", "-signed.apk")
108
258
  apk_path_signed = apk_path_signed.gsub("unsigned", "")
109
259
  apk_path_signed = apk_path_signed.gsub("--", "-")
110
-
111
- # https://developer.android.com/studio/command-line/apksigner
112
260
  `rm -f '#{apk_path_signed}'`
113
- `#{build_tools_path}apksigner sign --ks '#{keystore_path}' --ks-key-alias '#{alias_name}' --ks-pass pass:'#{key_password}' --key-pass pass:'#{alias_password}' --v1-signing-enabled true --v2-signing-enabled true --out '#{apk_path_signed}' '#{apk_path_aligned}'`
114
-
115
- `#{build_tools_path}apksigner verify '#{apk_path_signed}'`
116
- `rm -f '#{apk_path_aligned}'`
261
+
262
+ UI.message("Signing APK (input): #{apk_path}")
263
+ apksigner_opts = ""
264
+ build_tools_version = self.get_build_tools_version(version_targeted)
265
+ UI.message("Build-tools version: #{build_tools_version}")
266
+ if Gem::Version.new(build_tools_version) >= Gem::Version.new('30')
267
+ apksigner_opts = "--v4-signing-enabled false "
268
+ end
269
+ output = `#{build_tools_path}apksigner sign --ks '#{keystore_path}' --ks-key-alias '#{alias_name}' --ks-pass pass:'#{key_password}' --key-pass pass:'#{alias_password}' --v1-signing-enabled true --v2-signing-enabled true #{apksigner_opts}--out '#{apk_path_signed}' '#{apk_path}'`
270
+ puts ""
271
+ puts output
272
+
273
+ UI.message("Verifing APK signature (output): #{apk_path_signed}")
274
+ output = `#{build_tools_path}apksigner verify '#{apk_path_signed}'`
275
+ puts ""
276
+ puts output
277
+
278
+
279
+ # https://developer.android.com/studio/command-line/zipalign
280
+ if zip_align != false
281
+ apk_path_aligned = apk_path_signed.gsub(".apk", "-aligned.apk")
282
+ `rm -f '#{apk_path_aligned}'`
283
+ UI.message("Aligning APK (zipalign): #{apk_path_signed}")
284
+ output = `#{build_tools_path}zipalign -v 4 '#{apk_path_signed}' '#{apk_path_aligned}'`
285
+ puts ""
286
+ puts output
287
+
288
+ if !File.file?(apk_path_aligned)
289
+ raise "Aligned APK not exists!"
290
+ end
291
+
292
+ `rm -f '#{apk_path_signed}'`
293
+ apk_path_signed = apk_path_aligned
294
+
295
+ else
296
+ UI.message("No zip align - deactivated via parameter!")
297
+ end
117
298
 
118
299
  apk_path_signed
300
+ end
301
+
302
+ def self.resolve_dir(path)
303
+ if !File.directory?(path)
304
+ path = File.join(Dir.pwd, path)
305
+ end
306
+ path
307
+ end
308
+
309
+ def self.resolve_file(path)
310
+ if !File.file?(path)
311
+ path = File.join(Dir.pwd, path)
312
+ end
313
+ path
314
+ end
315
+
316
+ def self.content_to_file(file_path, content)
317
+ `echo #{content} > #{file_path}`
119
318
  end
120
319
 
121
320
  def self.get_file_content(file_path)
@@ -132,9 +331,7 @@ module Fastlane
132
331
 
133
332
  if !apk_path.to_s.end_with?(".apk")
134
333
 
135
- if !File.directory?(apk_path)
136
- apk_path = File.join(Dir.pwd, apk_path)
137
- end
334
+ apk_path = self.resolve_dir(apk_path)
138
335
 
139
336
  pattern = File.join(apk_path, '*.apk')
140
337
  files = Dir[pattern]
@@ -147,11 +344,7 @@ module Fastlane
147
344
  end
148
345
 
149
346
  else
150
-
151
- if !File.file?(apk_path)
152
- apk_path = File.join(Dir.pwd, apk_path)
153
- end
154
-
347
+ apk_path = self.resolve_file(apk_path)
155
348
  end
156
349
 
157
350
  apk_path
@@ -177,6 +370,17 @@ module Fastlane
177
370
  match_secret = params[:match_secret]
178
371
  override_keystore = params[:override_keystore]
179
372
  keystore_data = params[:keystore_data]
373
+ clear_keystore = params[:clear_keystore]
374
+ unit_test = params[:unit_test]
375
+ build_tools_version = params[:build_tools_version]
376
+ zip_align = params[:zip_align]
377
+ compat_key = params[:compat_key]
378
+
379
+ # Test OpenSSL/LibreSSL
380
+ if unit_test
381
+ result_test = self.test_security
382
+ exit!
383
+ end
180
384
 
181
385
  # Init constants:
182
386
  keystore_name = 'keystore.jks'
@@ -192,7 +396,12 @@ module Fastlane
192
396
  end
193
397
 
194
398
  # Check OpenSSL:
195
- self.check_openssl_version
399
+ self.check_ssl_version(false)
400
+
401
+ # Check is backward-compatibility is required:
402
+ if !compat_key.to_s.strip.empty?
403
+ UI.message("Compatiblity version: #{compat_key}")
404
+ end
196
405
 
197
406
  # Init workign local directory:
198
407
  dir_name = ENV['HOME'] + '/.match_keystore'
@@ -202,7 +411,11 @@ module Fastlane
202
411
  end
203
412
 
204
413
  # Init 'security password' for AES encryption:
205
- key_name = "#{self.to_md5(git_url)}.hex"
414
+ if compat_key == "1"
415
+ key_name = "#{self.to_md5(git_url)}.hex"
416
+ else
417
+ key_name = "#{self.to_md5(git_url)}-#{self::KEY_VERSION}.hex"
418
+ end
206
419
  key_path = File.join(dir_name, key_name)
207
420
  # UI.message(key_path)
208
421
  if !File.file?(key_path)
@@ -211,7 +424,7 @@ module Fastlane
211
424
  raise "Security password is not defined! Please use 'match_secret' parameter for CI."
212
425
  end
213
426
  UI.message "Generating security key '#{key_name}'..."
214
- self.gen_key(key_path, security_password)
427
+ self.gen_key(key_path, security_password, compat_key)
215
428
  end
216
429
 
217
430
  # Check is 'security password' is well initialized:
@@ -222,42 +435,40 @@ module Fastlane
222
435
  raise "The security key '#{key_name}' is malformed, or not initialized!"
223
436
  end
224
437
 
225
- # Create repo directory to sync remote Keystores repository:
438
+ # Clear repo Keystore (local) - mostly for testing:
226
439
  repo_dir = File.join(dir_name, self.to_md5(git_url))
227
- # UI.message(repo_dir)
440
+ if clear_keystore && File.directory?(repo_dir)
441
+ FileUtils.rm_rf(repo_dir)
442
+ UI.message("Local repo keystore (#{repo_dir}) directory deleted!")
443
+ end
444
+
445
+ # Create repo directory to sync remote Keystores repository:
228
446
  unless File.directory?(repo_dir)
229
447
  UI.message("Creating 'repo' directory...")
230
448
  FileUtils.mkdir_p(repo_dir)
231
449
  end
232
450
 
451
+ # Check if package name defined:
452
+ if package_name.to_s.strip.empty?
453
+ raise "Package name is not defined!"
454
+ end
455
+
456
+ # Define paths:
457
+ keystoreAppDir = File.join(repo_dir, package_name)
458
+ keystore_path = File.join(keystoreAppDir, keystore_name)
459
+ properties_path = File.join(keystoreAppDir, properties_name)
460
+ properties_encrypt_path = File.join(keystoreAppDir, properties_encrypt_name)
461
+
233
462
  # Cloning/pulling GIT remote repository:
234
463
  gitDir = File.join(repo_dir, '/.git')
235
464
  if !File.directory?(gitDir)
236
465
  UI.message("Cloning remote Keystores repository...")
237
- puts ''
238
466
  `git clone #{git_url} #{repo_dir}`
239
- puts ''
240
467
  else
241
468
  UI.message("Pulling remote Keystores repository...")
242
- puts ''
243
469
  `cd #{repo_dir} && git pull`
244
- puts ''
245
- end
246
-
247
- # Create sub-directory for Android app:
248
- if package_name.to_s.strip.empty?
249
- raise "Package name is not defined!"
250
- end
251
- keystoreAppDir = File.join(repo_dir, package_name)
252
- unless File.directory?(keystoreAppDir)
253
- UI.message("Creating '#{package_name}' keystore directory...")
254
- FileUtils.mkdir_p(keystoreAppDir)
255
470
  end
256
471
 
257
- keystore_path = File.join(keystoreAppDir, keystore_name)
258
- properties_path = File.join(keystoreAppDir, properties_name)
259
- properties_encrypt_path = File.join(keystoreAppDir, properties_encrypt_name)
260
-
261
472
  # Load parameters from JSON for CI or Unit Tests:
262
473
  if keystore_data != nil && File.file?(keystore_data)
263
474
  data_json = self.load_json(keystore_data)
@@ -274,6 +485,7 @@ module Fastlane
274
485
 
275
486
  # Create keystore with command
276
487
  override_keystore = !existing_keystore.to_s.strip.empty? && File.file?(existing_keystore)
488
+ UI.message("Existing Keystore: #{existing_keystore}")
277
489
  if !File.file?(keystore_path) || override_keystore
278
490
 
279
491
  if File.file?(keystore_path)
@@ -294,7 +506,7 @@ module Fastlane
294
506
  end
295
507
 
296
508
  # https://developer.android.com/studio/publish/app-signing
297
- if !File.file?(existing_keystore)
509
+ if existing_keystore.to_s.strip.empty? || !File.file?(existing_keystore)
298
510
  UI.message("Generating Android Keystore...")
299
511
 
300
512
  full_name = self.prompt2(text: "Certificate First and Last Name: ", value: data_full_name)
@@ -335,7 +547,7 @@ module Fastlane
335
547
  out_file.puts("aliasPassword=#{alias_password}")
336
548
  out_file.close
337
549
 
338
- self.encrypt_file(properties_path, properties_encrypt_path, key_path)
550
+ self.encrypt_file(properties_path, properties_encrypt_path, key_path, false)
339
551
  File.delete(properties_path)
340
552
 
341
553
  # Print Keystore data in repo:
@@ -352,9 +564,10 @@ module Fastlane
352
564
  else
353
565
  UI.message "Keystore file already exists, continue..."
354
566
 
355
- self.decrypt_file(properties_encrypt_path, properties_path, key_path)
567
+ self.decrypt_file(properties_encrypt_path, properties_path, key_path, false)
356
568
 
357
569
  properties = self.load_properties(properties_path)
570
+ # Pry::ColorPrinter.pp(properties)
358
571
  key_password = properties['keyPassword']
359
572
  alias_name = properties['aliasName']
360
573
  alias_password = properties['aliasPassword']
@@ -380,12 +593,13 @@ module Fastlane
380
593
  key_password,
381
594
  alias_name,
382
595
  alias_password,
383
- true # Zip align
596
+ zip_align, # Zip align
597
+ build_tools_version # Buil-tools version
384
598
  )
385
599
  puts ''
386
600
  end
387
601
  else
388
- UI.message("No APK file found to sign!")
602
+ UI.message("No APK file found at: #{apk_path}")
389
603
  end
390
604
 
391
605
  # Prepare contect shared values for next lanes:
@@ -457,7 +671,32 @@ module Fastlane
457
671
  env_name: "MATCH_KEYSTORE_JSON_PATH",
458
672
  description: "Required data to import an existing keystore, or create a new one",
459
673
  optional: true,
460
- type: String)
674
+ type: String),
675
+ FastlaneCore::ConfigItem.new(key: :build_tools_version,
676
+ env_name: "MATCH_KEYSTORE_BUILD_TOOLS_VERSION",
677
+ description: "Set built-tools version (by default latest available on machine)",
678
+ optional: true,
679
+ type: String),
680
+ FastlaneCore::ConfigItem.new(key: :zip_align,
681
+ env_name: "MATCH_KEYSTORE_ZIPALIGN",
682
+ description: "Define if plugin will run zipalign on APK before sign it (true by default)",
683
+ optional: true,
684
+ type: Boolean),
685
+ FastlaneCore::ConfigItem.new(key: :compat_key,
686
+ env_name: "MATCH_KEYSTORE_COMPAT_KEY",
687
+ description: "Define the compatibility key version used on local machine (nil by default)",
688
+ optional: true,
689
+ type: String),
690
+ FastlaneCore::ConfigItem.new(key: :clear_keystore,
691
+ env_name: "MATCH_KEYSTORE_CLEAR",
692
+ description: "Clear the local keystore (false by default)",
693
+ optional: true,
694
+ type: Boolean),
695
+ FastlaneCore::ConfigItem.new(key: :unit_test,
696
+ env_name: "MATCH_KEYSTORE_UNIT_TESTS",
697
+ description: "launch Unit Tests (false by default)",
698
+ optional: true,
699
+ type: Boolean)
461
700
  ]
462
701
  end
463
702
 
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module MatchKeystore
3
- VERSION = "0.1.14"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-match_keystore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.14
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Christopher NEY
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-07 00:00:00.000000000 Z
11
+ date: 2021-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -167,7 +167,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
167
  - !ruby/object:Gem::Version
168
168
  version: '0'
169
169
  requirements: []
170
- rubygems_version: 3.0.3
170
+ rubygems_version: 3.2.6
171
171
  signing_key:
172
172
  specification_version: 4
173
173
  summary: Easily sync your Android keystores across your team