fastlane-plugin-match_keystore 0.1.16 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aaedb3d25e8614b96c43af4e88ddbc46f56e71a7a97a92d2336507afc3afded8
4
- data.tar.gz: 741fc33e956879046126da3fec54cb6f939b34eb8859e22d27244de8a7e6f823
3
+ metadata.gz: 13f57b6db57c10e142d53885360cb1416f676402fd7f234b61a549720501d9c6
4
+ data.tar.gz: 2809854cf748f5ba4931fd4cbe8dfc6292cfea2f4e5d556a887ed422ebfcacc2
5
5
  SHA512:
6
- metadata.gz: e0d3ef8b5d0b9c5a66fcc8bece867e8d230e9f44764b963774cbdfbe110b38f7ef2446bf9592fd913716da8267471ef1cb7d2b6d30a70e494ef8ae75d78c84a9
7
- data.tar.gz: 37849dd986d716d6ce16ab7fe8af4f3d18d7b8c3a1840f6f7d4ccade7121b7ced9ac2085e486c8c4442da6f7bf76435ac7581267a730bb204619f5c41d8b558a
6
+ metadata.gz: 97a47758d5a39ebf414ae7a232e8767cb0dfa6ac7c484f3180b8e3149d3e879fb3ce3b27d363eae444703e9f3a9bad5b4ddc5d66f2987ed5fa0ed29b04bd4c74
7
+ data.tar.gz: 2c27e6a39112bdef3c44c6ed8abd77a31e19c9ce52a002040562d9f4aee229b4cf0e60cbe868196493acc983ca61b39acdfadebd2914e5a9ba15d40dd1024751
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:
@@ -43,6 +50,8 @@ The keystore properties are encrypted with AES in order to secure sensitive data
43
50
  end
44
51
  ```
45
52
 
53
+ You can build aab files as well by providing an `aab_path` instead of an `apk_path`.
54
+
46
55
  ## Example
47
56
 
48
57
  Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin. Try it by cloning the repo, running `fastlane install_plugins` and `bundle exec fastlane test`.
@@ -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
 
@@ -11,14 +12,13 @@ module Fastlane
11
12
  MATCH_KEYSTORE_PATH = :MATCH_KEYSTORE_PATH
12
13
  MATCH_KEYSTORE_ALIAS_NAME = :MATCH_KEYSTORE_ALIAS_NAME
13
14
  MATCH_KEYSTORE_APK_SIGNED = :MATCH_KEYSTORE_APK_SIGNED
15
+ MATCH_KEYSTORE_AAB_SIGNED = :MATCH_KEYSTORE_AAB_SIGNED
14
16
  end
15
17
 
16
18
  class MatchKeystoreAction < Action
17
19
 
18
- def self.openssl_path
19
- path = "/usr/local/opt/openssl@1.1/bin"
20
- path
21
- end
20
+ KEY_VERSION = "2"
21
+ OPENSSL_BIN_PATH_MAC = "/usr/local/opt/openssl@1.1/bin"
22
22
 
23
23
  def self.to_md5(value)
24
24
  hash_value = Digest::MD5.hexdigest value
@@ -119,8 +119,7 @@ module Fastlane
119
119
 
120
120
  def self.openssl(forceOpenSSL)
121
121
  if forceOpenSSL
122
- path = openssl_path
123
- output = "#{path}/openssl"
122
+ output = "#{self::OPENSSL_BIN_PATH_MAC}/openssl"
124
123
  else
125
124
  output = "openssl"
126
125
  end
@@ -137,10 +136,15 @@ module Fastlane
137
136
  result
138
137
  end
139
138
 
140
- def self.gen_key(key_path, password)
139
+ def self.gen_key(key_path, password, compat_key)
141
140
  `rm -f '#{key_path}'`
142
141
  shaValue = self.sha512(password)
143
- `echo "#{shaValue}" > '#{key_path}'`
142
+ # Backward-compatibility
143
+ if compat_key == "1"
144
+ `echo "#{password}" | openssl dgst -sha512 | awk '{print $2}' | cut -c1-128 > '#{key_path}'`
145
+ else
146
+ `echo "#{shaValue}" > '#{key_path}'`
147
+ end
144
148
  end
145
149
 
146
150
  def self.encrypt_file(clear_file, encrypt_file, key_path, forceOpenSSL)
@@ -190,7 +194,7 @@ module Fastlane
190
194
 
191
195
  # Check SHA-512-File
192
196
  key_path = File.join(Dir.pwd, '/temp/key.txt')
193
- self.gen_key(key_path, fakeValue)
197
+ self.gen_key(key_path, fakeValue, false)
194
198
  shaValue = self.get_file_content(key_path).strip!
195
199
  excepted = "cc6a7b0d89cc61c053f7018a305672bdb82bc07e5015f64bb063d9662be4ec81ec8afa819b009de266482b6bd56b7068def2524c32f5b5d4d9db49ee4578499d"
196
200
  self.assert_equals("SHA-512-File", excepted, shaValue)
@@ -250,49 +254,68 @@ module Fastlane
250
254
  build_tools_path = self.get_build_tools(version_targeted)
251
255
  UI.message("Build-tools path: #{build_tools_path}")
252
256
 
253
- # https://developer.android.com/studio/command-line/zipalign
254
- if zip_align == true
255
- apk_path_aligned = apk_path.gsub(".apk", "-aligned.apk")
256
- `rm -f '#{apk_path_aligned}'`
257
- UI.message("Aligning APK (zipalign): #{apk_path}")
258
- output = `#{build_tools_path}zipalign -v 4 '#{apk_path}' '#{apk_path_aligned}'`
259
- puts ""
260
- puts output
261
-
262
- if !File.file?(apk_path_aligned)
263
- raise "Aligned APK not exists!"
264
- end
265
-
266
- else
267
- UI.message("No zip align!")
268
- apk_path_aligned = apk_path
269
- end
257
+ # https://developer.android.com/studio/command-line/apksigner
270
258
  apk_path_signed = apk_path.gsub(".apk", "-signed.apk")
271
259
  apk_path_signed = apk_path_signed.gsub("unsigned", "")
272
260
  apk_path_signed = apk_path_signed.gsub("--", "-")
273
-
274
- # https://developer.android.com/studio/command-line/apksigner
275
261
  `rm -f '#{apk_path_signed}'`
276
- UI.message("Signing APK: #{apk_path_aligned}")
262
+
263
+ UI.message("Signing APK (input): #{apk_path}")
277
264
  apksigner_opts = ""
278
265
  build_tools_version = self.get_build_tools_version(version_targeted)
279
266
  UI.message("Build-tools version: #{build_tools_version}")
280
267
  if Gem::Version.new(build_tools_version) >= Gem::Version.new('30')
281
268
  apksigner_opts = "--v4-signing-enabled false "
282
269
  end
283
- 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_aligned}'`
270
+ 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}'`
284
271
  puts ""
285
272
  puts output
286
273
 
287
- UI.message("Verifing APK signature: #{apk_path_signed}")
274
+ UI.message("Verifing APK signature (output): #{apk_path_signed}")
288
275
  output = `#{build_tools_path}apksigner verify '#{apk_path_signed}'`
289
276
  puts ""
290
277
  puts output
291
- `rm -f '#{apk_path_aligned}'`
278
+
279
+
280
+ # https://developer.android.com/studio/command-line/zipalign
281
+ if zip_align != false
282
+ apk_path_aligned = apk_path_signed.gsub(".apk", "-aligned.apk")
283
+ `rm -f '#{apk_path_aligned}'`
284
+ UI.message("Aligning APK (zipalign): #{apk_path_signed}")
285
+ output = `#{build_tools_path}zipalign -v 4 '#{apk_path_signed}' '#{apk_path_aligned}'`
286
+ puts ""
287
+ puts output
288
+
289
+ if !File.file?(apk_path_aligned)
290
+ raise "Aligned APK not exists!"
291
+ end
292
+
293
+ `rm -f '#{apk_path_signed}'`
294
+ apk_path_signed = apk_path_aligned
295
+
296
+ else
297
+ UI.message("No zip align - deactivated via parameter!")
298
+ end
292
299
 
293
300
  apk_path_signed
294
301
  end
295
302
 
303
+ def self.sign_aab(aab_path, keystore_path, key_password, alias_name, alias_password)
304
+
305
+ aab_path_signed = aab_path.gsub('.aab', '-signed.aab')
306
+ aab_path_signed = aab_path_signed.gsub('unsigned', '')
307
+ aab_path_signed = aab_path_signed.gsub('--', '-')
308
+ `rm -f '#{aab_path_signed}'`
309
+
310
+ UI.message("Signing AAB (input): #{aab_path}")
311
+ aabsigner_opts = ""
312
+ output = `jarsigner -keystore '#{keystore_path}' -storepass '#{key_password}' -keypass '#{alias_password}' -signedjar '#{aab_path_signed}' '#{aab_path}' '#{alias_name}'`
313
+ puts ""
314
+ puts output
315
+
316
+ aab_path_signed
317
+ end
318
+
296
319
  def self.resolve_dir(path)
297
320
  if !File.directory?(path)
298
321
  path = File.join(Dir.pwd, path)
@@ -316,6 +339,34 @@ module Fastlane
316
339
  data
317
340
  end
318
341
 
342
+ def self.resolve_aab_path(aab_path)
343
+
344
+ # Set default AAB path if not set:
345
+ if aab_path.to_s.strip.empty?
346
+ aab_path = '/app/build/outputs/bundle/release/'
347
+ end
348
+
349
+ if !aab_path.to_s.end_with?('.aab')
350
+
351
+ aab_path = self.resolve_dir(aab_path)
352
+
353
+ pattern = File.join(aab_path, '*.aab')
354
+ files = Dir[pattern]
355
+
356
+ for file in files
357
+ if file.to_s.end_with?('.aab') && !file.to_s.end_with?("-signed.aab")
358
+ apk_path = file
359
+ break
360
+ end
361
+ end
362
+
363
+ else
364
+ aab_path = self.resolve_file(aab_path)
365
+ end
366
+
367
+ aab_path
368
+ end
369
+
319
370
  def self.resolve_apk_path(apk_path)
320
371
 
321
372
  # Set default APK path if not set:
@@ -360,6 +411,7 @@ module Fastlane
360
411
  git_url = params[:git_url]
361
412
  package_name = params[:package_name]
362
413
  apk_path = params[:apk_path]
414
+ aab_path = params[:aab_path]
363
415
  existing_keystore = params[:existing_keystore]
364
416
  match_secret = params[:match_secret]
365
417
  override_keystore = params[:override_keystore]
@@ -367,6 +419,8 @@ module Fastlane
367
419
  clear_keystore = params[:clear_keystore]
368
420
  unit_test = params[:unit_test]
369
421
  build_tools_version = params[:build_tools_version]
422
+ zip_align = params[:zip_align]
423
+ compat_key = params[:compat_key]
370
424
 
371
425
  # Test OpenSSL/LibreSSL
372
426
  if unit_test
@@ -390,6 +444,11 @@ module Fastlane
390
444
  # Check OpenSSL:
391
445
  self.check_ssl_version(false)
392
446
 
447
+ # Check is backward-compatibility is required:
448
+ if !compat_key.to_s.strip.empty?
449
+ UI.message("Compatiblity version: #{compat_key}")
450
+ end
451
+
393
452
  # Init workign local directory:
394
453
  dir_name = ENV['HOME'] + '/.match_keystore'
395
454
  unless File.directory?(dir_name)
@@ -398,7 +457,11 @@ module Fastlane
398
457
  end
399
458
 
400
459
  # Init 'security password' for AES encryption:
401
- key_name = "#{self.to_md5(git_url)}.hex"
460
+ if compat_key == "1"
461
+ key_name = "#{self.to_md5(git_url)}.hex"
462
+ else
463
+ key_name = "#{self.to_md5(git_url)}-#{self::KEY_VERSION}.hex"
464
+ end
402
465
  key_path = File.join(dir_name, key_name)
403
466
  # UI.message(key_path)
404
467
  if !File.file?(key_path)
@@ -407,7 +470,7 @@ module Fastlane
407
470
  raise "Security password is not defined! Please use 'match_secret' parameter for CI."
408
471
  end
409
472
  UI.message "Generating security key '#{key_name}'..."
410
- self.gen_key(key_path, security_password)
473
+ self.gen_key(key_path, security_password, compat_key)
411
474
  end
412
475
 
413
476
  # Check is 'security password' is well initialized:
@@ -446,14 +509,10 @@ module Fastlane
446
509
  gitDir = File.join(repo_dir, '/.git')
447
510
  if !File.directory?(gitDir)
448
511
  UI.message("Cloning remote Keystores repository...")
449
- puts ''
450
512
  `git clone #{git_url} #{repo_dir}`
451
- puts ''
452
513
  else
453
514
  UI.message("Pulling remote Keystores repository...")
454
- puts ''
455
515
  `cd #{repo_dir} && git pull`
456
- puts ''
457
516
  end
458
517
 
459
518
  # Load parameters from JSON for CI or Unit Tests:
@@ -554,6 +613,7 @@ module Fastlane
554
613
  self.decrypt_file(properties_encrypt_path, properties_path, key_path, false)
555
614
 
556
615
  properties = self.load_properties(properties_path)
616
+ # Pry::ColorPrinter.pp(properties)
557
617
  key_password = properties['keyPassword']
558
618
  alias_name = properties['aliasName']
559
619
  alias_password = properties['aliasPassword']
@@ -561,13 +621,13 @@ module Fastlane
561
621
  File.delete(properties_path)
562
622
  end
563
623
 
564
- # Resolve path to the APK to sign:
565
- output_signed_apk = ''
566
- apk_path = self.resolve_apk_path(apk_path)
567
-
568
624
  # Sign APK:
569
- if File.file?(apk_path)
625
+ if apk_path && File.file?(apk_path)
570
626
  UI.message("APK to sign: " + apk_path)
627
+
628
+ # Resolve path to the APK to sign:
629
+ output_signed_apk = ''
630
+ apk_path = self.resolve_apk_path(apk_path)
571
631
 
572
632
  if File.file?(keystore_path)
573
633
 
@@ -579,21 +639,49 @@ module Fastlane
579
639
  key_password,
580
640
  alias_name,
581
641
  alias_password,
582
- true, # Zip align
642
+ zip_align, # Zip align
583
643
  build_tools_version # Buil-tools version
584
644
  )
585
645
  puts ''
586
646
  end
587
- else
588
- UI.message("No APK file found to sign!")
589
- end
590
647
 
591
- # Prepare contect shared values for next lanes:
592
- Actions.lane_context[SharedValues::MATCH_KEYSTORE_PATH] = keystore_path
593
- Actions.lane_context[SharedValues::MATCH_KEYSTORE_ALIAS_NAME] = alias_name
594
- Actions.lane_context[SharedValues::MATCH_KEYSTORE_APK_SIGNED] = output_signed_apk
648
+ # Prepare contect shared values for next lanes:
649
+ Actions.lane_context[SharedValues::MATCH_KEYSTORE_PATH] = keystore_path
650
+ Actions.lane_context[SharedValues::MATCH_KEYSTORE_ALIAS_NAME] = alias_name
651
+ Actions.lane_context[SharedValues::MATCH_KEYSTORE_APK_SIGNED] = output_signed_apk
652
+
653
+ output_signed_apk
654
+ # Sign AAB
655
+ elsif aab_path && File.file?(aab_path)
656
+ UI.message('AAB to sign: '+ aab_path)
657
+
658
+ # Resolve path to the AAB to sign:
659
+ output_signed_aab = ''
660
+ aab_path = self.resolve_aab_path(aab_path)
661
+
662
+ if File.file?(keystore_path)
663
+
664
+ UI.message("Signing the AAB...")
665
+ puts ''
666
+ output_signed_aab = self.sign_aab(
667
+ aab_path,
668
+ keystore_path,
669
+ key_password,
670
+ alias_name,
671
+ alias_password
672
+ )
673
+ puts ''
674
+ end
675
+
676
+ # Prepare contect shared values for next lanes:
677
+ Actions.lane_context[SharedValues::MATCH_KEYSTORE_PATH] = keystore_path
678
+ Actions.lane_context[SharedValues::MATCH_KEYSTORE_ALIAS_NAME] = alias_name
679
+ Actions.lane_context[SharedValues::MATCH_KEYSTORE_AAB_SIGNED] = output_signed_aab
595
680
 
596
- output_signed_apk
681
+ output_signed_aab
682
+ else
683
+ UI.message("No APK or AAB file found")
684
+ end
597
685
  end
598
686
 
599
687
  def self.description
@@ -601,7 +689,7 @@ module Fastlane
601
689
  end
602
690
 
603
691
  def self.authors
604
- ["Christopher NEY"]
692
+ ["Christopher NEY", "Simon Scherzinger"]
605
693
  end
606
694
 
607
695
  def self.return_value
@@ -612,7 +700,8 @@ module Fastlane
612
700
  [
613
701
  ['MATCH_KEYSTORE_PATH', 'File path of the Keystore fot the App.'],
614
702
  ['MATCH_KEYSTORE_ALIAS_NAME', 'Keystore Alias Name.'],
615
- ['MATCH_KEYSTORE_APK_SIGNED', 'Path of the signed APK.']
703
+ ['MATCH_KEYSTORE_APK_SIGNED', 'Path of the signed APK.'],
704
+ ['MATCH_KEYSTORE_AAB_SIGNED', 'Path of the signed AAB.']
616
705
  ]
617
706
  end
618
707
 
@@ -638,6 +727,11 @@ module Fastlane
638
727
  description: "Path of the APK file to sign",
639
728
  optional: true,
640
729
  type: String),
730
+ FastlaneCore::ConfigItem.new(key: :aab_path,
731
+ env_name: "MATCH_KEYSTORE_AAB_PATH",
732
+ description: "Path of the AAB file to sign",
733
+ optional: true,
734
+ type: String),
641
735
  FastlaneCore::ConfigItem.new(key: :match_secret,
642
736
  env_name: "MATCH_KEYSTORE_SECRET",
643
737
  description: "Secret to decrypt keystore.properties file (CI)",
@@ -662,17 +756,27 @@ module Fastlane
662
756
  env_name: "MATCH_KEYSTORE_BUILD_TOOLS_VERSION",
663
757
  description: "Set built-tools version (by default latest available on machine)",
664
758
  optional: true,
665
- type: String),
759
+ type: String),
760
+ FastlaneCore::ConfigItem.new(key: :zip_align,
761
+ env_name: "MATCH_KEYSTORE_ZIPALIGN",
762
+ description: "Define if plugin will run zipalign on APK before sign it (true by default)",
763
+ optional: true,
764
+ type: Boolean),
765
+ FastlaneCore::ConfigItem.new(key: :compat_key,
766
+ env_name: "MATCH_KEYSTORE_COMPAT_KEY",
767
+ description: "Define the compatibility key version used on local machine (nil by default)",
768
+ optional: true,
769
+ type: String),
666
770
  FastlaneCore::ConfigItem.new(key: :clear_keystore,
667
771
  env_name: "MATCH_KEYSTORE_CLEAR",
668
772
  description: "Clear the local keystore (false by default)",
669
773
  optional: true,
670
774
  type: Boolean),
671
775
  FastlaneCore::ConfigItem.new(key: :unit_test,
672
- env_name: "MATCH_KEYSTORE_UNIT_TESTS",
776
+ env_name: "MATCH_KEYSTORE_UNIT_TESTS",
673
777
  description: "launch Unit Tests (false by default)",
674
- optional: true,
675
- type: Boolean)
778
+ optional: true,
779
+ type: Boolean)
676
780
  ]
677
781
  end
678
782
 
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module MatchKeystore
3
- VERSION = "0.1.16"
3
+ VERSION = "0.2.1"
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.16
4
+ version: 0.2.1
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-08 00:00:00.000000000 Z
11
+ date: 2021-09-15 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.17
171
171
  signing_key:
172
172
  specification_version: 4
173
173
  summary: Easily sync your Android keystores across your team