fastlane 2.133.0 → 2.136.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.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +78 -78
  3. data/fastlane/lib/fastlane/action.rb +1 -1
  4. data/fastlane/lib/fastlane/actions/actions_helper.rb +1 -1
  5. data/fastlane/lib/fastlane/actions/carthage.rb +7 -0
  6. data/fastlane/lib/fastlane/actions/cocoapods.rb +24 -2
  7. data/fastlane/lib/fastlane/actions/deploygate.rb +1 -1
  8. data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +38 -4
  9. data/fastlane/lib/fastlane/actions/docs/capture_ios_screenshots.md +1 -1
  10. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +4 -2
  11. data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +26 -2
  12. data/fastlane/lib/fastlane/actions/download_dsyms.rb +26 -3
  13. data/fastlane/lib/fastlane/actions/download_from_play_store.rb +1 -1
  14. data/fastlane/lib/fastlane/actions/get_version_number.rb +10 -4
  15. data/fastlane/lib/fastlane/actions/google_play_track_version_codes.rb +5 -1
  16. data/fastlane/lib/fastlane/actions/sonar.rb +16 -0
  17. data/fastlane/lib/fastlane/actions/testfairy.rb +1 -1
  18. data/fastlane/lib/fastlane/actions/update_fastlane.rb +9 -49
  19. data/fastlane/lib/fastlane/actions/update_keychain_access_groups.rb +94 -0
  20. data/fastlane/lib/fastlane/environment_printer.rb +9 -3
  21. data/fastlane/lib/fastlane/fast_file.rb +3 -2
  22. data/fastlane/lib/fastlane/lane_manager.rb +1 -1
  23. data/fastlane/lib/fastlane/plugins/plugin_manager.rb +12 -2
  24. data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +2 -0
  25. data/fastlane/lib/fastlane/runner.rb +2 -2
  26. data/fastlane/lib/fastlane/swift_fastlane_function.rb +9 -0
  27. data/fastlane/lib/fastlane/version.rb +1 -1
  28. data/fastlane/swift/Deliverfile.swift +1 -1
  29. data/fastlane/swift/Fastlane.swift +124 -36
  30. data/fastlane/swift/Gymfile.swift +1 -1
  31. data/fastlane/swift/Matchfile.swift +1 -1
  32. data/fastlane/swift/MatchfileProtocol.swift +2 -2
  33. data/fastlane/swift/Precheckfile.swift +1 -1
  34. data/fastlane/swift/Scanfile.swift +1 -1
  35. data/fastlane/swift/Screengrabfile.swift +1 -1
  36. data/fastlane/swift/ScreengrabfileProtocol.swift +22 -2
  37. data/fastlane/swift/Snapshotfile.swift +1 -1
  38. data/fastlane_core/lib/fastlane_core/configuration/commander_generator.rb +3 -3
  39. data/fastlane_core/lib/fastlane_core/configuration/configuration.rb +1 -1
  40. data/fastlane_core/lib/fastlane_core/device_manager.rb +1 -1
  41. data/fastlane_core/lib/fastlane_core/swag.rb +1 -1
  42. data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +1 -1
  43. data/match/lib/match/importer.rb +1 -1
  44. data/scan/lib/scan/error_handler.rb +9 -4
  45. data/scan/lib/scan/runner.rb +1 -1
  46. data/screengrab/lib/screengrab/module.rb +2 -0
  47. data/screengrab/lib/screengrab/options.rb +33 -11
  48. data/screengrab/lib/screengrab/runner.rb +64 -24
  49. data/sigh/lib/assets/resign.sh +2 -2
  50. data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher.rb +1 -1
  51. data/spaceship/lib/spaceship/client.rb +2 -2
  52. data/supply/lib/supply.rb +23 -0
  53. data/supply/lib/supply/.uploader.rb.swp +0 -0
  54. data/supply/lib/supply/client.rb +101 -55
  55. data/supply/lib/supply/options.rb +50 -14
  56. data/supply/lib/supply/release_listing.rb +18 -0
  57. data/supply/lib/supply/setup.rb +42 -34
  58. data/supply/lib/supply/uploader.rb +191 -93
  59. metadata +32 -37
  60. data/fastlane/lib/fastlane/actions/.hockey.rb.swp +0 -0
  61. data/fastlane/lib/fastlane/actions/.slack.rb.swp +0 -0
  62. data/fastlane/lib/fastlane/actions/.update_project_provisioning.rb.swp +0 -0
  63. data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/xcuserdata/josh.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  64. data/gym/lib/gym/.runner.rb.swp +0 -0
  65. data/pilot/lib/pilot/.manager.rb.swp +0 -0
  66. data/spaceship/lib/spaceship/connect_api/.DS_Store +0 -0
  67. data/spaceship/lib/spaceship/portal/.certificate.rb.swp +0 -0
@@ -18,4 +18,4 @@ class Gymfile: GymfileProtocol {
18
18
 
19
19
 
20
20
 
21
- // Generated with fastlane 2.133.0
21
+ // Generated with fastlane 2.136.0
@@ -18,4 +18,4 @@ class Matchfile: MatchfileProtocol {
18
18
 
19
19
 
20
20
 
21
- // Generated with fastlane 2.133.0
21
+ // Generated with fastlane 2.136.0
@@ -91,7 +91,7 @@ protocol MatchfileProtocol: class {
91
91
  extension MatchfileProtocol {
92
92
  var type: String { return "development" }
93
93
  var readonly: Bool { return false }
94
- var generateAppleCerts: Bool { return true }
94
+ var generateAppleCerts: Bool { return false }
95
95
  var skipProvisioningProfiles: Bool { return false }
96
96
  var appIdentifier: [String] { return [] }
97
97
  var username: String { return "" }
@@ -122,4 +122,4 @@ extension MatchfileProtocol {
122
122
 
123
123
  // Please don't remove the lines below
124
124
  // They are used to detect outdated files
125
- // FastlaneRunnerAPIVersion [0.9.9]
125
+ // FastlaneRunnerAPIVersion [0.9.10]
@@ -18,4 +18,4 @@ class Precheckfile: PrecheckfileProtocol {
18
18
 
19
19
 
20
20
 
21
- // Generated with fastlane 2.133.0
21
+ // Generated with fastlane 2.136.0
@@ -18,4 +18,4 @@ class Scanfile: ScanfileProtocol {
18
18
 
19
19
 
20
20
 
21
- // Generated with fastlane 2.133.0
21
+ // Generated with fastlane 2.136.0
@@ -18,4 +18,4 @@ class Screengrabfile: ScreengrabfileProtocol {
18
18
 
19
19
 
20
20
 
21
- // Generated with fastlane 2.133.0
21
+ // Generated with fastlane 2.136.0
@@ -39,6 +39,9 @@ protocol ScreengrabfileProtocol: class {
39
39
  /// Return the device to this locale after running tests
40
40
  var endingLocale: String { get }
41
41
 
42
+ /// Restarts the adb daemon using `adb root` to allow access to screenshots directories on device. Use if getting 'Permission denied' errors
43
+ var useAdbRoot: Bool { get }
44
+
42
45
  /// The path to the APK for the app under test
43
46
  var appApkPath: String? { get }
44
47
 
@@ -56,6 +59,18 @@ protocol ScreengrabfileProtocol: class {
56
59
 
57
60
  /// Enabling this option will automatically uninstall the application before running it
58
61
  var reinstallApp: Bool { get }
62
+
63
+ /// Add timestamp suffix to screenshot filename
64
+ var useTimestampSuffix: Bool { get }
65
+
66
+ /// Configure the host used by adb to connect, allows running on remote devices farm
67
+ var adbHost: String? { get }
68
+
69
+ /// Enabling this option will clean the status bar
70
+ var cleanStatusBar: Bool { get }
71
+
72
+ /// Specifies the configuration for the clean status bar
73
+ var cleanStatusBarConfig: [String : Any] { get }
59
74
  }
60
75
 
61
76
  extension ScreengrabfileProtocol {
@@ -70,16 +85,21 @@ extension ScreengrabfileProtocol {
70
85
  var useTestsInPackages: [String]? { return nil }
71
86
  var useTestsInClasses: [String]? { return nil }
72
87
  var launchArguments: [String]? { return nil }
73
- var testInstrumentationRunner: String { return "android.support.test.runner.AndroidJUnitRunner" }
88
+ var testInstrumentationRunner: String { return "androidx.test.runner.AndroidJUnitRunner" }
74
89
  var endingLocale: String { return "en-US" }
90
+ var useAdbRoot: Bool { return false }
75
91
  var appApkPath: String? { return nil }
76
92
  var testsApkPath: String? { return nil }
77
93
  var specificDevice: String? { return nil }
78
94
  var deviceType: String { return "phone" }
79
95
  var exitOnTestFailure: Bool { return true }
80
96
  var reinstallApp: Bool { return false }
97
+ var useTimestampSuffix: Bool { return true }
98
+ var adbHost: String? { return nil }
99
+ var cleanStatusBar: Bool { return false }
100
+ var cleanStatusBarConfig: [String : Any] { return [:] }
81
101
  }
82
102
 
83
103
  // Please don't remove the lines below
84
104
  // They are used to detect outdated files
85
- // FastlaneRunnerAPIVersion [0.9.11]
105
+ // FastlaneRunnerAPIVersion [0.9.12]
@@ -18,4 +18,4 @@ class Snapshotfile: SnapshotfileProtocol {
18
18
 
19
19
 
20
20
 
21
- // Generated with fastlane 2.133.0
21
+ // Generated with fastlane 2.136.0
@@ -93,9 +93,9 @@ module FastlaneCore
93
93
  return if short_switch.nil?
94
94
 
95
95
  UI.user_error!("Short option #{short_switch} already taken for key #{key}") if used_switches.include?(short_switch)
96
- UI.user_error!("-v is already used for the version (key #{key})") if short_switch == "-v"
97
- UI.user_error!("-h is already used for the help screen (key #{key})") if short_switch == "-h"
98
- UI.user_error!("-t is already used for the trace screen (key #{key})") if short_switch == "-t"
96
+ UI.user_error!("-v is already used for the fastlane version (key #{key})") if short_switch == "-v"
97
+ UI.user_error!("-h is already used for the fastlane help screen (key #{key})") if short_switch == "-h"
98
+ UI.user_error!("-t is already used for the fastlane trace screen (key #{key})") if short_switch == "-t"
99
99
 
100
100
  used_switches << short_switch
101
101
  end
@@ -120,7 +120,7 @@ module FastlaneCore
120
120
  index = @available_options.find_index { |item| item.key == conflicting_option_key }
121
121
  conflicting_option = @available_options[index]
122
122
 
123
- # ignore conflicts because because value of conflict option is nil
123
+ # ignore conflicts because value of conflict option is nil
124
124
  next if @values[conflicting_option.key].nil?
125
125
 
126
126
  if current.conflict_block
@@ -307,7 +307,7 @@ module FastlaneCore
307
307
  logarchive_dst = File.join(logs_destination_dir, "system_logs-#{log_identity}.logarchive").shellescape
308
308
  FileUtils.rm_rf(logarchive_dst)
309
309
  FileUtils.mkdir_p(File.expand_path("..", logarchive_dst))
310
- command = "xcrun simctl spawn #{device.udid} log collect --output #{logarchive_dst} 2>/dev/null"
310
+ command = "xcrun simctl spawn --standalone #{device.udid} log collect --output #{logarchive_dst} 2>/dev/null"
311
311
  FastlaneCore::CommandExecutor.execute(command: command, print_all: false, print_command: true)
312
312
  end
313
313
  end
@@ -45,7 +45,7 @@ module FastlaneCore
45
45
 
46
46
  def self.show_loader
47
47
  return unless should_be_shown?
48
- # sound is disabled as i didn't find a royality free nice midi :(
48
+ # sound is disabled as I didn't find a royality free nice midi :(
49
49
  @output = StringIO.new
50
50
  # if FastlaneCore::Env.truthy?("FL_DO_SOUND")
51
51
  # @sound_thr = Thread.new do
@@ -117,7 +117,7 @@ module Commander
117
117
  abort(e.to_s)
118
118
  end
119
119
  end
120
- rescue FastlaneCore::Interface::FastlaneCommonException => e # these are exceptions that we dont count as crashes
120
+ rescue FastlaneCore::Interface::FastlaneCommonException => e # these are exceptions that we don't count as crashes
121
121
  display_user_error!(e, e.to_s)
122
122
  rescue FastlaneCore::Interface::FastlaneError => e # user_error!
123
123
  rescue_fastlane_error(e)
@@ -17,7 +17,7 @@ module Match
17
17
  UI.user_error!("Certificate does not exist at path: #{cert_path}") unless File.exist?(cert_path)
18
18
  UI.user_error!("Private key does not exist at path: #{p12_path}") unless File.exist?(p12_path)
19
19
 
20
- # Base64 encrypt contents to find match from API to find a cert ID
20
+ # Base64 encode contents to find match from API to find a cert ID
21
21
  cert_contents_base_64 = Base64.strict_encode64(File.open(cert_path).read)
22
22
 
23
23
  # Storage
@@ -6,8 +6,13 @@ module Scan
6
6
  class << self
7
7
  # @param [String] The output of the errored build
8
8
  # This method should raise an exception in any case, as the return code indicated a failed build
9
- def handle_build_error(output)
10
- # The order of the handling below is import
9
+ def handle_build_error(output, log_path)
10
+ # The order of the handling below is important
11
+
12
+ instruction = 'See the log'
13
+ location = Scan.config[:suppress_xcode_output] ? "here: '#{log_path}'" : "above"
14
+ details = "#{instruction} #{location}."
15
+
11
16
  case output
12
17
  when /US\-ASCII/
13
18
  print("Your shell environment is not correctly configured")
@@ -23,7 +28,7 @@ module Scan
23
28
  print("For more information visit this stackoverflow answer:")
24
29
  print("https://stackoverflow.com/a/17031697/445598")
25
30
  when /Testing failed/
26
- UI.build_failure!("Error building the application - see the log above")
31
+ UI.build_failure!("Error building the application. #{details}")
27
32
  when /Executed/, /Failing tests:/
28
33
  # this is *really* important:
29
34
  # we don't want to raise an exception here
@@ -38,7 +43,7 @@ module Scan
38
43
  # followed by a list of tests that failed.
39
44
  return
40
45
  end
41
- UI.build_failure!("Error building/testing the application - see the log above")
46
+ UI.build_failure!("Error building/testing the application. #{details}")
42
47
  end
43
48
 
44
49
  private
@@ -67,7 +67,7 @@ module Scan
67
67
  error: proc do |error_output|
68
68
  begin
69
69
  exit_status = $?.exitstatus
70
- ErrorHandler.handle_build_error(error_output)
70
+ ErrorHandler.handle_build_error(error_output, @test_command_generator.xcodebuild_log_path)
71
71
  rescue => ex
72
72
  SlackPoster.new.run({
73
73
  build_errors: 1
@@ -1,4 +1,5 @@
1
1
  require 'fastlane_core/helper'
2
+ require 'fastlane/boolean'
2
3
  require_relative 'detect_values'
3
4
 
4
5
  module Screengrab
@@ -19,6 +20,7 @@ module Screengrab
19
20
 
20
21
  Helper = FastlaneCore::Helper # you gotta love Ruby: Helper.* should use the Helper class contained in FastlaneCore
21
22
  UI = FastlaneCore::UI
23
+ Boolean = Fastlane::Boolean
22
24
  ROOT = Pathname.new(File.expand_path('../../..', __FILE__))
23
25
  DESCRIPTION = "Automated localized screenshots of your Android app on every device".freeze
24
26
  end
@@ -32,7 +32,7 @@ module Screengrab
32
32
  env_name: 'SCREENGRAB_CLEAR_PREVIOUS_SCREENSHOTS',
33
33
  description: "Enabling this option will automatically clear previously generated screenshots before running screengrab",
34
34
  default_value: false,
35
- is_string: false),
35
+ type: Boolean),
36
36
  FastlaneCore::ConfigItem.new(key: :output_directory,
37
37
  short_option: "-o",
38
38
  env_name: "SCREENGRAB_OUTPUT_DIRECTORY",
@@ -43,7 +43,7 @@ module Screengrab
43
43
  description: "Don't open the summary after running _screengrab_",
44
44
  default_value: DEFAULT_SKIP_OPEN_SUMMARY,
45
45
  default_value_dynamic: true,
46
- is_string: false),
46
+ type: Boolean),
47
47
  FastlaneCore::ConfigItem.new(key: :app_package_name,
48
48
  env_name: 'SCREENGRAB_APP_PACKAGE_NAME',
49
49
  short_option: "-a",
@@ -68,22 +68,26 @@ module Screengrab
68
68
  type: Array,
69
69
  description: "Only run tests in these Java classes"),
70
70
  FastlaneCore::ConfigItem.new(key: :launch_arguments,
71
- env_name: 'SCREENGRAB_LAUNCH_ARGUMENTS',
72
- optional: true,
73
- short_option: "-e",
74
- type: Array,
75
- description: "Additional launch arguments"),
71
+ env_name: 'SCREENGRAB_LAUNCH_ARGUMENTS',
72
+ optional: true,
73
+ short_option: "-e",
74
+ type: Array,
75
+ description: "Additional launch arguments"),
76
76
  FastlaneCore::ConfigItem.new(key: :test_instrumentation_runner,
77
77
  env_name: 'SCREENGRAB_TEST_INSTRUMENTATION_RUNNER',
78
78
  optional: true,
79
- default_value: 'android.support.test.runner.AndroidJUnitRunner',
79
+ default_value: 'androidx.test.runner.AndroidJUnitRunner',
80
80
  description: "The fully qualified class name of your test instrumentation runner"),
81
81
  FastlaneCore::ConfigItem.new(key: :ending_locale,
82
82
  env_name: 'SCREENGRAB_ENDING_LOCALE',
83
83
  optional: true,
84
- is_string: true,
85
84
  default_value: 'en-US',
86
85
  description: "Return the device to this locale after running tests"),
86
+ FastlaneCore::ConfigItem.new(key: :use_adb_root,
87
+ env_name: 'SCREENGRAB_USE_ADB_ROOT',
88
+ description: "Restarts the adb daemon using `adb root` to allow access to screenshots directories on device. Use if getting 'Permission denied' errors",
89
+ default_value: false,
90
+ type: Boolean),
87
91
  FastlaneCore::ConfigItem.new(key: :app_apk_path,
88
92
  env_name: 'SCREENGRAB_APP_APK_PATH',
89
93
  optional: true,
@@ -123,12 +127,30 @@ module Screengrab
123
127
  env_name: 'EXIT_ON_TEST_FAILURE',
124
128
  description: "Whether or not to exit Screengrab on test failure. Exiting on failure will not copy sceenshots to local machine nor open sceenshots summary",
125
129
  default_value: true,
126
- is_string: false),
130
+ type: Boolean),
127
131
  FastlaneCore::ConfigItem.new(key: :reinstall_app,
128
132
  env_name: 'SCREENGRAB_REINSTALL_APP',
129
133
  description: "Enabling this option will automatically uninstall the application before running it",
130
134
  default_value: false,
131
- is_string: false)
135
+ type: Boolean),
136
+ FastlaneCore::ConfigItem.new(key: :use_timestamp_suffix,
137
+ env_name: 'SCREENGRAB_USE_TIMESTAMP_SUFFIX',
138
+ description: "Add timestamp suffix to screenshot filename",
139
+ default_value: true,
140
+ type: Boolean),
141
+ FastlaneCore::ConfigItem.new(key: :adb_host,
142
+ env_name: 'SCREENGRAB_ADB_HOST',
143
+ description: "Configure the host used by adb to connect, allows running on remote devices farm",
144
+ optional: true),
145
+ FastlaneCore::ConfigItem.new(key: :clean_status_bar,
146
+ env_name: 'SCREENGRAB_CLEAN_STATUS_BAR',
147
+ description: "Enabling this option will clean the status bar",
148
+ default_value: false,
149
+ type: Boolean),
150
+ FastlaneCore::ConfigItem.new(key: :clean_status_bar_config,
151
+ description: "Specifies the configuration for the clean status bar",
152
+ default_value: {},
153
+ type: Hash)
132
154
  ]
133
155
  end
134
156
  end
@@ -57,8 +57,13 @@ module Screengrab
57
57
 
58
58
  device_screenshots_paths = [
59
59
  determine_external_screenshots_path(device_serial),
60
- determine_internal_screenshots_path
61
- ]
60
+ determine_internal_screenshots_paths(@config[:app_package_name], @config[:locales])
61
+ ].flatten
62
+
63
+ # Root is needed to access device paths at /data
64
+ if @config[:use_adb_root]
65
+ run_adb_command("root", print_all: false, print_command: true)
66
+ end
62
67
 
63
68
  clear_device_previous_screenshots(device_serial, device_screenshots_paths)
64
69
 
@@ -67,6 +72,8 @@ module Screengrab
67
72
 
68
73
  validate_apk(app_apk_path)
69
74
 
75
+ enable_clean_status_bar(device_serial, app_apk_path)
76
+
70
77
  run_tests(device_serial, app_apk_path, tests_apk_path, test_classes_to_use, test_packages_to_use, @config[:launch_arguments])
71
78
 
72
79
  number_of_screenshots = pull_screenshots_from_device(device_serial, device_screenshots_paths, device_type_dir_name)
@@ -77,7 +84,7 @@ module Screengrab
77
84
  end
78
85
 
79
86
  def select_device
80
- devices = run_adb_command("adb devices -l", print_all: true, print_command: true).split("\n")
87
+ devices = run_adb_command("devices -l", print_all: true, print_command: true).split("\n")
81
88
  # the first output by adb devices is "List of devices attached" so remove that and any adb startup output
82
89
  devices.reject! do |device|
83
90
  [
@@ -139,15 +146,19 @@ module Screengrab
139
146
  # macOS evaluates $foo in `echo $foo` before executing the command,
140
147
  # Windows doesn't - hence the double backslash vs. single backslash
141
148
  command = Helper.windows? ? "shell echo \$EXTERNAL_STORAGE " : "shell echo \\$EXTERNAL_STORAGE"
142
- device_ext_storage = run_adb_command("adb -s #{device_serial} #{command}",
149
+ device_ext_storage = run_adb_command("-s #{device_serial} #{command}",
143
150
  print_all: true,
144
151
  print_command: true)
145
152
  device_ext_storage = device_ext_storage.strip
146
153
  File.join(device_ext_storage, @config[:app_package_name], 'screengrab')
147
154
  end
148
155
 
149
- def determine_internal_screenshots_path
150
- "/data/data/#{@config[:app_package_name]}/app_screengrab"
156
+ def determine_internal_screenshots_paths(app_package_name, locales)
157
+ locale_paths = locales.map do |locale|
158
+ "/data/user/0/#{app_package_name}/files/#{app_package_name}/screengrab/#{locale}/images/screenshots"
159
+ end
160
+
161
+ return ["/data/data/#{app_package_name}/app_screengrab"] + locale_paths
151
162
  end
152
163
 
153
164
  def clear_device_previous_screenshots(device_serial, device_screenshots_paths)
@@ -155,7 +166,7 @@ module Screengrab
155
166
 
156
167
  device_screenshots_paths.each do |device_path|
157
168
  if_device_path_exists(device_serial, device_path) do |path|
158
- run_adb_command("adb -s #{device_serial} shell rm -rf #{path}",
169
+ run_adb_command("-s #{device_serial} shell rm -rf #{path}",
159
170
  print_all: true,
160
171
  print_command: true)
161
172
  end
@@ -182,13 +193,13 @@ module Screengrab
182
193
 
183
194
  def install_apks(device_serial, app_apk_path, tests_apk_path)
184
195
  UI.message('Installing app APK')
185
- apk_install_output = run_adb_command("adb -s #{device_serial} install -t -r #{app_apk_path.shellescape}",
196
+ apk_install_output = run_adb_command("-s #{device_serial} install -t -r #{app_apk_path.shellescape}",
186
197
  print_all: true,
187
198
  print_command: true)
188
199
  UI.user_error!("App APK could not be installed") if apk_install_output.include?("Failure [")
189
200
 
190
201
  UI.message('Installing tests APK')
191
- apk_install_output = run_adb_command("adb -s #{device_serial} install -t -r #{tests_apk_path.shellescape}",
202
+ apk_install_output = run_adb_command("-s #{device_serial} install -t -r #{tests_apk_path.shellescape}",
192
203
  print_all: true,
193
204
  print_command: true)
194
205
  UI.user_error!("Tests APK could not be installed") if apk_install_output.include?("Failure [")
@@ -199,14 +210,14 @@ module Screengrab
199
210
 
200
211
  if packages.include?(app_package_name.to_s)
201
212
  UI.message('Uninstalling app APK')
202
- run_adb_command("adb -s #{device_serial} uninstall #{app_package_name}",
213
+ run_adb_command("-s #{device_serial} uninstall #{app_package_name}",
203
214
  print_all: true,
204
215
  print_command: true)
205
216
  end
206
217
 
207
218
  if packages.include?(tests_package_name.to_s)
208
219
  UI.message('Uninstalling tests APK')
209
- run_adb_command("adb -s #{device_serial} uninstall #{tests_package_name}",
220
+ run_adb_command("-s #{device_serial} uninstall #{tests_package_name}",
210
221
  print_all: true,
211
222
  print_command: true)
212
223
  end
@@ -214,20 +225,16 @@ module Screengrab
214
225
 
215
226
  def grant_permissions(device_serial)
216
227
  UI.message('Granting the permission necessary to change locales on the device')
217
- run_adb_command("adb -s #{device_serial} shell pm grant #{@config[:app_package_name]} android.permission.CHANGE_CONFIGURATION",
228
+ run_adb_command("-s #{device_serial} shell pm grant #{@config[:app_package_name]} android.permission.CHANGE_CONFIGURATION",
218
229
  print_all: true,
219
230
  print_command: true)
220
231
 
221
- device_api_version = run_adb_command("adb -s #{device_serial} shell getprop ro.build.version.sdk",
222
- print_all: true,
223
- print_command: true).to_i
224
-
225
- if device_api_version >= 23
232
+ if device_api_version(device_serial) >= 23
226
233
  UI.message('Granting the permissions necessary to access device external storage')
227
- run_adb_command("adb -s #{device_serial} shell pm grant #{@config[:app_package_name]} android.permission.WRITE_EXTERNAL_STORAGE",
234
+ run_adb_command("-s #{device_serial} shell pm grant #{@config[:app_package_name]} android.permission.WRITE_EXTERNAL_STORAGE",
228
235
  print_all: true,
229
236
  print_command: true)
230
- run_adb_command("adb -s #{device_serial} shell pm grant #{@config[:app_package_name]} android.permission.READ_EXTERNAL_STORAGE",
237
+ run_adb_command("-s #{device_serial} shell pm grant #{@config[:app_package_name]} android.permission.READ_EXTERNAL_STORAGE",
231
238
  print_all: true,
232
239
  print_command: true)
233
240
  end
@@ -252,9 +259,10 @@ module Screengrab
252
259
  def run_tests_for_locale(locale, device_serial, test_classes_to_use, test_packages_to_use, launch_arguments)
253
260
  UI.message("Running tests for locale: #{locale}")
254
261
 
255
- instrument_command = ["adb -s #{device_serial} shell am instrument --no-window-animation -w",
262
+ instrument_command = ["-s #{device_serial} shell am instrument --no-window-animation -w",
256
263
  "-e testLocale #{locale.tr('-', '_')}",
257
264
  "-e endingLocale #{@config[:ending_locale].tr('-', '_')}"]
265
+ instrument_command << "-e appendTimestamp #{@config[:use_timestamp_suffix]}"
258
266
  instrument_command << "-e class #{test_classes_to_use.join(',')}" if test_classes_to_use
259
267
  instrument_command << "-e package #{test_packages_to_use.join(',')}" if test_packages_to_use
260
268
  instrument_command << launch_arguments.map { |item| '-e ' + item }.join(' ') if launch_arguments
@@ -281,10 +289,11 @@ module Screengrab
281
289
 
282
290
  # Make a temp directory into which to pull the screenshots before they are moved to their final location.
283
291
  # This makes directory cleanup easier, as the temp directory will be removed when the block completes.
292
+
284
293
  Dir.mktmpdir do |tempdir|
285
294
  device_screenshots_paths.each do |device_path|
286
295
  if_device_path_exists(device_serial, device_path) do |path|
287
- run_adb_command("adb -s #{device_serial} pull #{path} #{tempdir}",
296
+ run_adb_command("-s #{device_serial} pull #{path} #{tempdir}",
288
297
  print_all: false,
289
298
  print_command: true)
290
299
  end
@@ -347,7 +356,7 @@ module Screengrab
347
356
  # Some device commands fail if executed against a device path that does not exist, so this helper method
348
357
  # provides a way to conditionally execute a block only if the provided path exists on the device.
349
358
  def if_device_path_exists(device_serial, device_path)
350
- return if run_adb_command("adb -s #{device_serial} shell ls #{device_path}",
359
+ return if run_adb_command("-s #{device_serial} shell ls #{device_path}",
351
360
  print_all: false,
352
361
  print_command: false).include?('No such file')
353
362
 
@@ -359,7 +368,7 @@ module Screengrab
359
368
 
360
369
  # Return an array of packages that are installed on the device
361
370
  def installed_packages(device_serial)
362
- packages = run_adb_command("adb -s #{device_serial} shell pm list packages",
371
+ packages = run_adb_command("-s #{device_serial} shell pm list packages",
363
372
  print_all: true,
364
373
  print_command: true)
365
374
  packages.split("\n").map { |package| package.gsub("package:", "") }
@@ -367,7 +376,9 @@ module Screengrab
367
376
 
368
377
  def run_adb_command(command, print_all: false, print_command: false)
369
378
  adb_path = @android_env.adb_path.chomp("adb")
370
- output = @executor.execute(command: adb_path + command,
379
+ adb_host = @config[:adb_host]
380
+ host = adb_host.nil? ? '' : "-H #{adb_host} "
381
+ output = @executor.execute(command: adb_path + "adb " + host + command,
371
382
  print_all: print_all,
372
383
  print_command: print_command) || ''
373
384
  output.lines.reject do |line|
@@ -375,5 +386,34 @@ module Screengrab
375
386
  line.start_with?('adb: ')
376
387
  end.join('') # Lines retain their newline chars
377
388
  end
389
+
390
+ def device_api_version(device_serial)
391
+ run_adb_command("-s #{device_serial} shell getprop ro.build.version.sdk",
392
+ print_all: true, print_command: true).to_i
393
+ end
394
+
395
+ def enable_clean_status_bar(device_serial, app_apk_path)
396
+ return unless device_api_version(device_serial) >= 23
397
+
398
+ # Check if the app wants to use the clean status bar feature
399
+ badging_dump = @executor.execute(command: "#{@android_env.aapt_path} dump badging #{app_apk_path}",
400
+ print_all: true, print_command: true)
401
+ return unless badging_dump.include?('uses-feature: name=\'tools.fastlane.screengrab.cleanstatusbar\'')
402
+
403
+ UI.message('Enabling clean status bar')
404
+
405
+ # Make sure the app requests the DUMP permission
406
+ unless badging_dump.include?('uses-permission: name=\'android.permission.DUMP\'')
407
+ UI.user_error!("The clean status bar feature requires the android.permission.DUMP permission but it could not be found in your app APK")
408
+ end
409
+
410
+ # Grant the DUMP permission
411
+ run_adb_command("-s #{device_serial} shell pm grant #{@config[:app_package_name]} android.permission.DUMP",
412
+ print_all: true, print_command: true)
413
+
414
+ # Enable the SystemUI demo mode
415
+ run_adb_command("-s #{device_serial} shell settings put global sysui_demo_allowed 1",
416
+ print_all: true, print_command: true)
417
+ end
378
418
  end
379
419
  end