fastlane 2.186.0 → 2.187.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +86 -86
- data/fastlane/lib/fastlane/actions/create_keychain.rb +5 -2
- data/fastlane/lib/fastlane/actions/docs/build_app.md +1 -1
- data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +25 -26
- data/fastlane/lib/fastlane/actions/docs/capture_ios_screenshots.md +2 -2
- data/fastlane/lib/fastlane/actions/docs/create_app_online.md +171 -67
- data/fastlane/lib/fastlane/actions/latest_testflight_build_number.rb +3 -4
- data/fastlane/lib/fastlane/actions/lcov.rb +0 -4
- data/fastlane/lib/fastlane/actions/mailgun.rb +21 -27
- data/fastlane/lib/fastlane/actions/make_changelog_from_jenkins.rb +1 -1
- data/fastlane/lib/fastlane/actions/modify_services.rb +59 -24
- data/fastlane/lib/fastlane/actions/nexus_upload.rb +2 -2
- data/fastlane/lib/fastlane/actions/notarize.rb +1 -4
- data/fastlane/lib/fastlane/actions/number_of_commits.rb +1 -1
- data/fastlane/lib/fastlane/actions/oclint.rb +15 -14
- data/fastlane/lib/fastlane/actions/pod_push.rb +0 -2
- data/fastlane/lib/fastlane/actions/podio_item.rb +0 -7
- data/fastlane/lib/fastlane/actions/prompt.rb +3 -4
- data/fastlane/lib/fastlane/actions/push_git_tags.rb +1 -1
- data/fastlane/lib/fastlane/actions/puts.rb +1 -2
- data/fastlane/lib/fastlane/actions/register_devices.rb +0 -1
- data/fastlane/lib/fastlane/actions/reset_git_repo.rb +5 -8
- data/fastlane/lib/fastlane/actions/reset_simulator_contents.rb +0 -2
- data/fastlane/lib/fastlane/actions/resign.rb +2 -9
- data/fastlane/lib/fastlane/actions/rsync.rb +3 -6
- data/fastlane/lib/fastlane/actions/run_tests.rb +1 -1
- data/fastlane/lib/fastlane/actions/s3.rb +1 -1
- data/fastlane/lib/fastlane/actions/say.rb +2 -3
- data/fastlane/lib/fastlane/actions/scp.rb +4 -10
- data/fastlane/lib/fastlane/actions/set_build_number_repository.rb +1 -1
- data/fastlane/lib/fastlane/actions/set_changelog.rb +1 -1
- data/fastlane/lib/fastlane/actions/set_github_release.rb +2 -8
- data/fastlane/lib/fastlane/actions/set_info_plist_value.rb +1 -1
- data/fastlane/lib/fastlane/actions/set_pod_key.rb +3 -4
- data/fastlane/lib/fastlane/actions/setup_ci.rb +1 -2
- data/fastlane/lib/fastlane/actions/setup_circle_ci.rb +1 -1
- data/fastlane/lib/fastlane/actions/setup_jenkins.rb +7 -12
- data/fastlane/lib/fastlane/actions/setup_travis.rb +1 -1
- data/fastlane/lib/fastlane/actions/sh.rb +2 -4
- data/fastlane/lib/fastlane/actions/slack.rb +6 -8
- data/fastlane/lib/fastlane/actions/slather.rb +3 -19
- data/fastlane/lib/fastlane/actions/sonar.rb +12 -19
- data/fastlane/lib/fastlane/actions/sourcedocs.rb +62 -98
- data/fastlane/lib/fastlane/actions/splunkmint.rb +2 -2
- data/fastlane/lib/fastlane/actions/spm.rb +3 -3
- data/fastlane/lib/fastlane/actions/ssh.rb +5 -10
- data/fastlane/lib/fastlane/actions/testfairy.rb +0 -1
- data/fastlane/lib/fastlane/actions/tryouts.rb +2 -3
- data/fastlane/lib/fastlane/actions/twitter.rb +0 -5
- data/fastlane/lib/fastlane/actions/unlock_keychain.rb +3 -3
- data/fastlane/lib/fastlane/actions/update_app_group_identifiers.rb +1 -4
- data/fastlane/lib/fastlane/actions/update_code_signing_settings.rb +8 -15
- data/fastlane/lib/fastlane/actions/update_fastlane.rb +2 -2
- data/fastlane/lib/fastlane/documentation/docs_generator.rb +1 -1
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +1 -1
- data/fastlane/swift/Fastlane.swift +57 -57
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/GymfileProtocol.swift +1 -1
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +1 -1
- data/fastlane/swift/Precheckfile.swift +1 -1
- data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
- data/fastlane/swift/Scanfile.swift +1 -1
- data/fastlane/swift/ScanfileProtocol.swift +1 -1
- data/fastlane/swift/Screengrabfile.swift +1 -1
- data/fastlane/swift/ScreengrabfileProtocol.swift +4 -4
- data/fastlane/swift/Snapshotfile.swift +1 -1
- data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
- data/fastlane/swift/formatting/Brewfile.lock.json +11 -11
- data/produce/lib/produce/commands_generator.rb +99 -27
- data/produce/lib/produce/developer_center.rb +42 -4
- data/produce/lib/produce/options.rb +1 -1
- data/produce/lib/produce/service.rb +270 -179
- data/screengrab/lib/screengrab/android_environment.rb +2 -52
- data/screengrab/lib/screengrab/dependency_checker.rb +0 -20
- data/screengrab/lib/screengrab/options.rb +5 -2
- data/screengrab/lib/screengrab/runner.rb +108 -106
- data/snapshot/lib/assets/SnapfileTemplate +2 -1
- data/snapshot/lib/assets/SnapfileTemplate.swift +2 -1
- data/snapshot/lib/assets/SnapshotHelper.swift +14 -10
- data/snapshot/lib/snapshot/reports_generator.rb +3 -1
- data/snapshot/lib/snapshot/test_command_generator.rb +16 -2
- data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +8 -0
- data/spaceship/lib/spaceship/connect_api/models/bundle_id_capability.rb +58 -17
- data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +41 -1
- metadata +20 -21
- data/fastlane/lib/fastlane/helper/.git_helper.rb.swp +0 -0
@@ -4,31 +4,21 @@ require 'fastlane_core/command_executor'
|
|
4
4
|
module Screengrab
|
5
5
|
class AndroidEnvironment
|
6
6
|
attr_reader :android_home
|
7
|
-
attr_reader :build_tools_version
|
8
7
|
|
9
8
|
# android_home - the String path to the install location of the Android SDK
|
10
|
-
# build_tools_version - the String version of the Android build tools that should be used
|
11
|
-
def initialize(android_home, build_tools_version)
|
9
|
+
# build_tools_version - the String version of the Android build tools that should be used, ignored
|
10
|
+
def initialize(android_home, build_tools_version = nil)
|
12
11
|
@android_home = android_home
|
13
|
-
@build_tools_version = build_tools_version
|
14
12
|
end
|
15
13
|
|
16
14
|
def platform_tools_path
|
17
15
|
@platform_tools_path ||= find_platform_tools(android_home)
|
18
16
|
end
|
19
17
|
|
20
|
-
def build_tools_path
|
21
|
-
@build_tools_path ||= find_build_tools(android_home, build_tools_version)
|
22
|
-
end
|
23
|
-
|
24
18
|
def adb_path
|
25
19
|
@adb_path ||= find_adb(platform_tools_path)
|
26
20
|
end
|
27
21
|
|
28
|
-
def aapt_path
|
29
|
-
@aapt_path ||= find_aapt(build_tools_path)
|
30
|
-
end
|
31
|
-
|
32
22
|
private
|
33
23
|
|
34
24
|
def find_platform_tools(android_home)
|
@@ -38,38 +28,6 @@ module Screengrab
|
|
38
28
|
File.directory?(platform_tools_path) ? platform_tools_path : nil
|
39
29
|
end
|
40
30
|
|
41
|
-
def find_build_tools(android_home, build_tools_version)
|
42
|
-
return nil unless android_home
|
43
|
-
|
44
|
-
build_tools_dir = Helper.localize_file_path(File.join(android_home, 'build-tools'))
|
45
|
-
|
46
|
-
return nil unless build_tools_dir && File.directory?(build_tools_dir)
|
47
|
-
|
48
|
-
return Helper.localize_file_path(File.join(build_tools_dir, build_tools_version)) if build_tools_version
|
49
|
-
|
50
|
-
version = select_build_tools_version(build_tools_dir)
|
51
|
-
|
52
|
-
return version ? Helper.localize_file_path(File.join(build_tools_dir, version)) : nil
|
53
|
-
end
|
54
|
-
|
55
|
-
def select_build_tools_version(build_tools_dir)
|
56
|
-
# Collect the sub-directories of the build_tools_dir, rejecting any that start with '.' to remove . and ..
|
57
|
-
dir_names = Dir.entries(build_tools_dir).select { |e| !e.start_with?('.') && File.directory?(File.join(build_tools_dir, e)) }
|
58
|
-
|
59
|
-
# Collect a sorted array of Version objects from the directory names, handling the possibility that some
|
60
|
-
# entries may not be valid version names
|
61
|
-
versions = dir_names.map do |d|
|
62
|
-
begin
|
63
|
-
Gem::Version.new(d)
|
64
|
-
rescue
|
65
|
-
nil
|
66
|
-
end
|
67
|
-
end.reject(&:nil?).sort
|
68
|
-
|
69
|
-
# We'll take the last entry (highest version number) as the directory name we want
|
70
|
-
versions.last.to_s
|
71
|
-
end
|
72
|
-
|
73
31
|
def find_adb(platform_tools_path)
|
74
32
|
return FastlaneCore::CommandExecutor.which('adb') unless platform_tools_path
|
75
33
|
|
@@ -78,14 +36,6 @@ module Screengrab
|
|
78
36
|
return executable_command?(adb_path) ? adb_path : nil
|
79
37
|
end
|
80
38
|
|
81
|
-
def find_aapt(build_tools_path)
|
82
|
-
return FastlaneCore::CommandExecutor.which('aapt') unless build_tools_path
|
83
|
-
|
84
|
-
aapt_path = Helper.get_executable_path(File.join(build_tools_path, 'aapt'))
|
85
|
-
aapt_path = Helper.localize_file_path(aapt_path)
|
86
|
-
return executable_command?(aapt_path) ? aapt_path : nil
|
87
|
-
end
|
88
|
-
|
89
39
|
def executable_command?(cmd_path)
|
90
40
|
Helper.executable?(cmd_path)
|
91
41
|
end
|
@@ -6,7 +6,6 @@ module Screengrab
|
|
6
6
|
return if Helper.test?
|
7
7
|
|
8
8
|
check_adb(android_env)
|
9
|
-
check_aapt(android_env)
|
10
9
|
end
|
11
10
|
|
12
11
|
def self.check_adb(android_env)
|
@@ -30,25 +29,6 @@ module Screengrab
|
|
30
29
|
UI.user_error!('adb command not found')
|
31
30
|
end
|
32
31
|
|
33
|
-
def self.check_aapt(android_env)
|
34
|
-
android_home = android_env.android_home
|
35
|
-
aapt_path = android_env.aapt_path
|
36
|
-
|
37
|
-
warn_if_command_path_not_relative_to_android_home('aapt', android_home, aapt_path)
|
38
|
-
# aapt is not required in order to function, so we'll only warn if we can't find it.
|
39
|
-
warn_missing_aapt(android_home) unless aapt_path
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.warn_missing_aapt(android_home)
|
43
|
-
if android_home
|
44
|
-
UI.important("The `aapt` command could not be found relative to your provided ANDROID_HOME at #{android_home}")
|
45
|
-
UI.important("Please ensure that the Android SDK is installed and you have the build tools downloaded")
|
46
|
-
else
|
47
|
-
UI.important("The `aapt` command could not be found on your PATH")
|
48
|
-
UI.important("Please ensure that the Android SDK is installed and you have the build tools downloaded and present on your PATH")
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
32
|
def self.warn_if_command_path_not_relative_to_android_home(cmd_name, android_home, cmd_path)
|
53
33
|
if android_home && cmd_path && !cmd_path.start_with?(android_home)
|
54
34
|
UI.important("Using `#{cmd_name}` found at #{cmd_path} which is not within the specified ANDROID_HOME at #{android_home}")
|
@@ -22,7 +22,8 @@ module Screengrab
|
|
22
22
|
FastlaneCore::ConfigItem.new(key: :build_tools_version,
|
23
23
|
short_option: "-i",
|
24
24
|
optional: true,
|
25
|
-
description: "The Android build tools version to use, e.g. '23.0.2'"
|
25
|
+
description: "The Android build tools version to use, e.g. '23.0.2'",
|
26
|
+
deprecated: true),
|
26
27
|
FastlaneCore::ConfigItem.new(key: :locales,
|
27
28
|
description: "A list of locales which should be used",
|
28
29
|
short_option: "-q",
|
@@ -82,10 +83,12 @@ module Screengrab
|
|
82
83
|
env_name: 'SCREENGRAB_ENDING_LOCALE',
|
83
84
|
optional: true,
|
84
85
|
default_value: 'en-US',
|
85
|
-
description: "Return the device to this locale after running tests"
|
86
|
+
description: "Return the device to this locale after running tests",
|
87
|
+
deprecated: true),
|
86
88
|
FastlaneCore::ConfigItem.new(key: :use_adb_root,
|
87
89
|
env_name: 'SCREENGRAB_USE_ADB_ROOT',
|
88
90
|
description: "Restarts the adb daemon using `adb root` to allow access to screenshots directories on device. Use if getting 'Permission denied' errors",
|
91
|
+
deprecated: true,
|
89
92
|
default_value: false,
|
90
93
|
type: Boolean),
|
91
94
|
FastlaneCore::ConfigItem.new(key: :app_apk_path,
|
@@ -6,12 +6,6 @@ require_relative 'module'
|
|
6
6
|
|
7
7
|
module Screengrab
|
8
8
|
class Runner
|
9
|
-
NEEDED_PERMISSIONS = [
|
10
|
-
'android.permission.READ_EXTERNAL_STORAGE',
|
11
|
-
'android.permission.WRITE_EXTERNAL_STORAGE',
|
12
|
-
'android.permission.CHANGE_CONFIGURATION'
|
13
|
-
].freeze
|
14
|
-
|
15
9
|
attr_accessor :number_of_retries
|
16
10
|
|
17
11
|
def initialize(executor = FastlaneCore::CommandExecutor,
|
@@ -25,7 +19,6 @@ module Screengrab
|
|
25
19
|
|
26
20
|
def run
|
27
21
|
# Standardize the locales
|
28
|
-
@config[:locales].map! { |locale| locale.gsub("_", "-") }
|
29
22
|
FastlaneCore::PrintTable.print_values(config: @config, hide_keys: [], title: "Summary for screengrab #{Fastlane::VERSION}")
|
30
23
|
|
31
24
|
app_apk_path = @config.fetch(:app_apk_path, ask: false)
|
@@ -59,14 +52,14 @@ module Screengrab
|
|
59
52
|
device_serial = select_device
|
60
53
|
|
61
54
|
device_screenshots_paths = [
|
62
|
-
determine_external_screenshots_path(device_serial, @config[:locales]),
|
63
|
-
determine_internal_screenshots_paths(@config[:app_package_name], @config[:locales])
|
55
|
+
determine_external_screenshots_path(device_serial, @config[:app_package_name], @config[:locales]),
|
56
|
+
determine_internal_screenshots_paths(device_serial, @config[:app_package_name], @config[:locales])
|
64
57
|
].flatten
|
65
58
|
|
66
59
|
# Root is needed to access device paths at /data
|
67
60
|
if @config[:use_adb_root]
|
68
|
-
run_adb_command("-s #{device_serial} root", print_all: false, print_command: true)
|
69
|
-
run_adb_command("-s #{device_serial} wait-for-device", print_all: false, print_command: true)
|
61
|
+
run_adb_command("-s #{device_serial.shellescape} root", print_all: false, print_command: true)
|
62
|
+
run_adb_command("-s #{device_serial.shellescape} wait-for-device", print_all: false, print_command: true)
|
70
63
|
end
|
71
64
|
|
72
65
|
clear_device_previous_screenshots(@config[:app_package_name], device_serial, device_screenshots_paths)
|
@@ -74,9 +67,7 @@ module Screengrab
|
|
74
67
|
app_apk_path ||= select_app_apk(discovered_apk_paths)
|
75
68
|
tests_apk_path ||= select_tests_apk(discovered_apk_paths)
|
76
69
|
|
77
|
-
|
78
|
-
|
79
|
-
number_of_screenshots = run_tests(device_type_dir_name, device_screenshots_paths, device_serial, app_apk_path, tests_apk_path, test_classes_to_use, test_packages_to_use, @config[:launch_arguments])
|
70
|
+
number_of_screenshots = run_tests(device_type_dir_name, device_serial, app_apk_path, tests_apk_path, test_classes_to_use, test_packages_to_use, @config[:launch_arguments])
|
80
71
|
|
81
72
|
ReportsGenerator.new.generate
|
82
73
|
|
@@ -133,72 +124,71 @@ module Screengrab
|
|
133
124
|
Dir.glob(File.join(output_directory, '**', device_type, '*.png'), File::FNM_CASEFOLD)
|
134
125
|
end
|
135
126
|
|
136
|
-
def
|
127
|
+
def get_device_environment_variable(device_serial, variable_name)
|
137
128
|
# macOS evaluates $foo in `echo $foo` before executing the command,
|
138
129
|
# Windows doesn't - hence the double backslash vs. single backslash
|
139
|
-
command = Helper.windows? ? "shell echo
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
130
|
+
command = Helper.windows? ? "shell echo \$#{variable_name.shellescape.shellescape}" : "shell echo \\$#{variable_name.shellescape.shellescape}"
|
131
|
+
value = run_adb_command("-s #{device_serial.shellescape} #{command}",
|
132
|
+
print_all: true,
|
133
|
+
print_command: true)
|
134
|
+
return value.strip
|
135
|
+
end
|
136
|
+
|
137
|
+
# Don't need to use to use run-as if external
|
138
|
+
def use_adb_run_as?(path, device_serial)
|
139
|
+
device_ext_storage = get_device_environment_variable(device_serial, "EXTERNAL_STORAGE")
|
140
|
+
return !path.start_with?(device_ext_storage)
|
141
|
+
end
|
142
|
+
|
143
|
+
def determine_external_screenshots_path(device_serial, app_package_name, locales)
|
144
|
+
device_ext_storage = get_device_environment_variable(device_serial, "EXTERNAL_STORAGE")
|
144
145
|
return locales.map do |locale|
|
145
|
-
|
146
|
-
|
146
|
+
[
|
147
|
+
File.join(device_ext_storage, app_package_name, 'screengrab', locale, "images", "screenshots"),
|
148
|
+
File.join(device_ext_storage, "Android", "data", app_package_name, 'files', 'screengrab', locale, "images", "screenshots")
|
149
|
+
]
|
150
|
+
end.flatten.map { |path| [path, false] }
|
147
151
|
end
|
148
152
|
|
149
|
-
def determine_internal_screenshots_paths(app_package_name, locales)
|
153
|
+
def determine_internal_screenshots_paths(device_serial, app_package_name, locales)
|
154
|
+
device_data = get_device_environment_variable(device_serial, "ANDROID_DATA")
|
150
155
|
return locales.map do |locale|
|
151
156
|
[
|
152
|
-
"/
|
157
|
+
"#{device_data}/user/0/#{app_package_name}/files/#{app_package_name}/screengrab/#{locale}/images/screenshots",
|
153
158
|
|
154
159
|
# https://github.com/fastlane/fastlane/issues/15653#issuecomment-578541663
|
155
|
-
"/data
|
160
|
+
"#{device_data}/data/#{app_package_name}/files/#{app_package_name}/screengrab/#{locale}/images/screenshots",
|
156
161
|
|
157
|
-
"/data
|
158
|
-
"/data
|
162
|
+
"#{device_data}/data/#{app_package_name}/app_screengrab/#{locale}/images/screenshots",
|
163
|
+
"#{device_data}/data/#{app_package_name}/screengrab/#{locale}/images/screenshots"
|
159
164
|
]
|
160
|
-
end.flatten
|
165
|
+
end.flatten.map { |path| [path, true] }
|
161
166
|
end
|
162
167
|
|
163
168
|
def clear_device_previous_screenshots(app_package_name, device_serial, device_screenshots_paths)
|
164
169
|
UI.message('Cleaning screenshots on device')
|
165
170
|
|
166
|
-
device_screenshots_paths.each do |device_path|
|
167
|
-
if_device_path_exists(app_package_name, device_serial, device_path) do |path|
|
168
|
-
|
171
|
+
device_screenshots_paths.each do |(device_path, needs_run_as)|
|
172
|
+
if_device_path_exists(app_package_name, device_serial, device_path, needs_run_as) do |path|
|
173
|
+
# Determine if path needs the run-as permission
|
174
|
+
run_as = needs_run_as ? " run-as #{app_package_name.shellescape.shellescape}" : ""
|
175
|
+
|
176
|
+
run_adb_command("-s #{device_serial.shellescape} shell#{run_as} rm -rf #{path.shellescape.shellescape}",
|
169
177
|
print_all: true,
|
170
178
|
print_command: true)
|
171
179
|
end
|
172
180
|
end
|
173
181
|
end
|
174
182
|
|
175
|
-
def validate_apk(app_apk_path)
|
176
|
-
unless @android_env.aapt_path
|
177
|
-
UI.important("The `aapt` command could not be found on your system, so your app APK could not be validated")
|
178
|
-
return
|
179
|
-
end
|
180
|
-
|
181
|
-
UI.message('Validating app APK')
|
182
|
-
apk_permissions = @executor.execute(command: "#{@android_env.aapt_path} dump permissions #{app_apk_path}",
|
183
|
-
print_all: true,
|
184
|
-
print_command: true)
|
185
|
-
|
186
|
-
missing_permissions = NEEDED_PERMISSIONS.reject { |needed| apk_permissions.include?(needed) }
|
187
|
-
|
188
|
-
if missing_permissions.any?
|
189
|
-
UI.user_error!("The needed permission(s) #{missing_permissions.join(', ')} could not be found in your app APK")
|
190
|
-
end
|
191
|
-
end
|
192
|
-
|
193
183
|
def install_apks(device_serial, app_apk_path, tests_apk_path)
|
194
184
|
UI.message('Installing app APK')
|
195
|
-
apk_install_output = run_adb_command("-s #{device_serial} install -t -r #{app_apk_path.shellescape}",
|
185
|
+
apk_install_output = run_adb_command("-s #{device_serial.shellescape} install -t -r #{app_apk_path.shellescape}",
|
196
186
|
print_all: true,
|
197
187
|
print_command: true)
|
198
188
|
UI.user_error!("App APK could not be installed") if apk_install_output.include?("Failure [")
|
199
189
|
|
200
190
|
UI.message('Installing tests APK')
|
201
|
-
apk_install_output = run_adb_command("-s #{device_serial} install -t -r #{tests_apk_path.shellescape}",
|
191
|
+
apk_install_output = run_adb_command("-s #{device_serial.shellescape} install -t -r #{tests_apk_path.shellescape}",
|
202
192
|
print_all: true,
|
203
193
|
print_command: true)
|
204
194
|
UI.user_error!("Tests APK could not be installed") if apk_install_output.include?("Failure [")
|
@@ -209,14 +199,14 @@ module Screengrab
|
|
209
199
|
|
210
200
|
if packages.include?(app_package_name.to_s)
|
211
201
|
UI.message('Uninstalling app APK')
|
212
|
-
run_adb_command("-s #{device_serial} uninstall #{app_package_name}",
|
202
|
+
run_adb_command("-s #{device_serial.shellescape} uninstall #{app_package_name.shellescape}",
|
213
203
|
print_all: true,
|
214
204
|
print_command: true)
|
215
205
|
end
|
216
206
|
|
217
207
|
if packages.include?(tests_package_name.to_s)
|
218
208
|
UI.message('Uninstalling tests APK')
|
219
|
-
run_adb_command("-s #{device_serial} uninstall #{tests_package_name}",
|
209
|
+
run_adb_command("-s #{device_serial.shellescape} uninstall #{tests_package_name.shellescape}",
|
220
210
|
print_all: true,
|
221
211
|
print_command: true)
|
222
212
|
end
|
@@ -224,26 +214,37 @@ module Screengrab
|
|
224
214
|
|
225
215
|
def grant_permissions(device_serial)
|
226
216
|
UI.message('Granting the permission necessary to change locales on the device')
|
227
|
-
run_adb_command("-s #{device_serial} shell pm grant #{@config[:app_package_name]} android.permission.CHANGE_CONFIGURATION",
|
217
|
+
run_adb_command("-s #{device_serial.shellescape} shell pm grant #{@config[:app_package_name].shellescape.shellescape} android.permission.CHANGE_CONFIGURATION",
|
228
218
|
print_all: true,
|
229
|
-
print_command: true
|
219
|
+
print_command: true,
|
220
|
+
raise_errors: false)
|
230
221
|
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
222
|
+
UI.message('Granting the permissions necessary to access device external storage')
|
223
|
+
run_adb_command("-s #{device_serial.shellescape} shell pm grant #{@config[:app_package_name].shellescape.shellescape} android.permission.WRITE_EXTERNAL_STORAGE",
|
224
|
+
print_all: true,
|
225
|
+
print_command: true,
|
226
|
+
raise_errors: false)
|
227
|
+
run_adb_command("-s #{device_serial.shellescape} shell pm grant #{@config[:app_package_name].shellescape.shellescape} android.permission.READ_EXTERNAL_STORAGE",
|
228
|
+
print_all: true,
|
229
|
+
print_command: true,
|
230
|
+
raise_errors: false)
|
231
|
+
end
|
232
|
+
|
233
|
+
def kill_app(device_serial, package_name)
|
234
|
+
run_adb_command("-s #{device_serial.shellescape} shell am force-stop #{package_name.shellescape.shellescape}.test",
|
235
|
+
print_all: true,
|
236
|
+
print_command: true)
|
237
|
+
run_adb_command("-s #{device_serial.shellescape} shell am force-stop #{package_name.shellescape.shellescape}",
|
238
|
+
print_all: true,
|
239
|
+
print_command: true)
|
240
240
|
end
|
241
241
|
|
242
|
-
def run_tests(device_type_dir_name,
|
242
|
+
def run_tests(device_type_dir_name, device_serial, app_apk_path, tests_apk_path, test_classes_to_use, test_packages_to_use, launch_arguments)
|
243
|
+
sdk_version = device_api_version(device_serial)
|
243
244
|
unless @config[:reinstall_app]
|
244
245
|
install_apks(device_serial, app_apk_path, tests_apk_path)
|
245
246
|
grant_permissions(device_serial)
|
246
|
-
enable_clean_status_bar(device_serial,
|
247
|
+
enable_clean_status_bar(device_serial, sdk_version)
|
247
248
|
end
|
248
249
|
|
249
250
|
number_of_screenshots = 0
|
@@ -253,25 +254,28 @@ module Screengrab
|
|
253
254
|
uninstall_apks(device_serial, @config[:app_package_name], @config[:tests_package_name])
|
254
255
|
install_apks(device_serial, app_apk_path, tests_apk_path)
|
255
256
|
grant_permissions(device_serial)
|
256
|
-
|
257
|
+
else
|
258
|
+
kill_app(device_serial, @config[:app_package_name])
|
257
259
|
end
|
258
|
-
number_of_screenshots += run_tests_for_locale(device_type_dir_name,
|
260
|
+
number_of_screenshots += run_tests_for_locale(device_type_dir_name, locale, device_serial, test_classes_to_use, test_packages_to_use, launch_arguments, sdk_version)
|
259
261
|
end
|
260
262
|
|
261
263
|
number_of_screenshots
|
262
264
|
end
|
263
265
|
|
264
|
-
def run_tests_for_locale(device_type_dir_name,
|
266
|
+
def run_tests_for_locale(device_type_dir_name, locale, device_serial, test_classes_to_use, test_packages_to_use, launch_arguments, sdk_version)
|
265
267
|
UI.message("Running tests for locale: #{locale}")
|
266
268
|
|
267
|
-
instrument_command = ["-s #{device_serial} shell am instrument --no-window-animation -w",
|
268
|
-
"-e testLocale #{locale.
|
269
|
-
|
269
|
+
instrument_command = ["-s #{device_serial.shellescape} shell am instrument --no-window-animation -w",
|
270
|
+
"-e testLocale #{locale.shellescape.shellescape}"]
|
271
|
+
if sdk_version >= 28
|
272
|
+
instrument_command << "--no-hidden-api-checks"
|
273
|
+
end
|
270
274
|
instrument_command << "-e appendTimestamp #{@config[:use_timestamp_suffix]}"
|
271
|
-
instrument_command << "-e class #{test_classes_to_use.join(',')}" if test_classes_to_use
|
272
|
-
instrument_command << "-e package #{test_packages_to_use.join(',')}" if test_packages_to_use
|
275
|
+
instrument_command << "-e class #{test_classes_to_use.join(',').shellescape.shellescape}" if test_classes_to_use
|
276
|
+
instrument_command << "-e package #{test_packages_to_use.join(',').shellescape.shellescape}" if test_packages_to_use
|
273
277
|
instrument_command << launch_arguments.map { |item| '-e ' + item }.join(' ') if launch_arguments
|
274
|
-
instrument_command << "#{@config[:tests_package_name]}/#{@config[:test_instrumentation_runner]}"
|
278
|
+
instrument_command << "#{@config[:tests_package_name].shellescape.shellescape}/#{@config[:test_instrumentation_runner].shellescape.shellescape}"
|
275
279
|
|
276
280
|
test_output = run_adb_command(instrument_command.join(" \\\n"),
|
277
281
|
print_all: true,
|
@@ -285,30 +289,40 @@ module Screengrab
|
|
285
289
|
end
|
286
290
|
end
|
287
291
|
|
288
|
-
pull_screenshots_from_device(locale, device_serial,
|
292
|
+
pull_screenshots_from_device(locale, device_serial, device_type_dir_name)
|
289
293
|
end
|
290
294
|
|
291
|
-
def pull_screenshots_from_device(locale, device_serial,
|
295
|
+
def pull_screenshots_from_device(locale, device_serial, device_type_dir_name)
|
292
296
|
UI.message("Pulling captured screenshots for locale #{locale} from the device")
|
293
297
|
starting_screenshot_count = screenshot_file_names_in(@config[:output_directory], device_type_dir_name).length
|
294
298
|
|
295
299
|
UI.verbose("Starting screenshot count is: #{starting_screenshot_count}")
|
296
300
|
|
301
|
+
device_screenshots_paths = [
|
302
|
+
determine_external_screenshots_path(device_serial, @config[:app_package_name], [locale]),
|
303
|
+
determine_internal_screenshots_paths(device_serial, @config[:app_package_name], [locale])
|
304
|
+
].flatten
|
305
|
+
|
297
306
|
# Make a temp directory into which to pull the screenshots before they are moved to their final location.
|
298
307
|
# This makes directory cleanup easier, as the temp directory will be removed when the block completes.
|
299
308
|
|
300
309
|
Dir.mktmpdir do |tempdir|
|
301
|
-
device_screenshots_paths.each do |device_path|
|
302
|
-
if_device_path_exists(@config[:app_package_name], device_serial, device_path) do |path|
|
310
|
+
device_screenshots_paths.each do |(device_path, needs_run_as)|
|
311
|
+
if_device_path_exists(@config[:app_package_name], device_serial, device_path, needs_run_as) do |path|
|
312
|
+
UI.message(path)
|
303
313
|
next unless path.include?(locale)
|
304
|
-
out = run_adb_command("-s #{device_serial} pull #{path} #{tempdir}",
|
314
|
+
out = run_adb_command("-s #{device_serial.shellescape} pull #{path.shellescape} #{tempdir.shellescape}",
|
305
315
|
print_all: false,
|
306
316
|
print_command: true,
|
307
317
|
raise_errors: false)
|
308
318
|
if out =~ /Permission denied/
|
309
319
|
dir = File.dirname(path)
|
310
320
|
base = File.basename(path)
|
311
|
-
|
321
|
+
|
322
|
+
# Determine if path needs the run-as permission
|
323
|
+
run_as = needs_run_as ? " run-as #{@config[:app_package_name].shellescape.shellescape}" : ""
|
324
|
+
|
325
|
+
run_adb_command("-s #{device_serial.shellescape} shell#{run_as} \"tar -cC #{dir} #{base}\" | tar -xv -f- -C #{tempdir}",
|
312
326
|
print_all: false,
|
313
327
|
print_command: true)
|
314
328
|
end
|
@@ -372,8 +386,11 @@ module Screengrab
|
|
372
386
|
|
373
387
|
# Some device commands fail if executed against a device path that does not exist, so this helper method
|
374
388
|
# provides a way to conditionally execute a block only if the provided path exists on the device.
|
375
|
-
def if_device_path_exists(app_package_name, device_serial, device_path)
|
376
|
-
|
389
|
+
def if_device_path_exists(app_package_name, device_serial, device_path, needs_run_as)
|
390
|
+
# Determine if path needs the run-as permission
|
391
|
+
run_as = needs_run_as ? " run-as #{app_package_name.shellescape.shellescape}" : ""
|
392
|
+
|
393
|
+
return if run_adb_command("-s #{device_serial.shellescape} shell#{run_as} ls #{device_path.shellescape.shellescape}",
|
377
394
|
print_all: false,
|
378
395
|
print_command: false).include?('No such file')
|
379
396
|
|
@@ -385,7 +402,7 @@ module Screengrab
|
|
385
402
|
|
386
403
|
# Return an array of packages that are installed on the device
|
387
404
|
def installed_packages(device_serial)
|
388
|
-
packages = run_adb_command("-s #{device_serial} shell pm list packages",
|
405
|
+
packages = run_adb_command("-s #{device_serial.shellescape} shell pm list packages",
|
389
406
|
print_all: true,
|
390
407
|
print_command: true)
|
391
408
|
packages.split("\n").map { |package| package.gsub("package:", "") }
|
@@ -393,7 +410,7 @@ module Screengrab
|
|
393
410
|
|
394
411
|
def run_adb_command(command, print_all: false, print_command: false, raise_errors: true)
|
395
412
|
adb_host = @config[:adb_host]
|
396
|
-
host = adb_host.nil? ? '' : "-H #{adb_host} "
|
413
|
+
host = adb_host.nil? ? '' : "-H #{adb_host.shellescape} "
|
397
414
|
output = ''
|
398
415
|
begin
|
399
416
|
errout = nil
|
@@ -414,36 +431,21 @@ module Screengrab
|
|
414
431
|
end
|
415
432
|
|
416
433
|
def device_api_version(device_serial)
|
417
|
-
run_adb_command("-s #{device_serial} shell getprop ro.build.version.sdk",
|
434
|
+
run_adb_command("-s #{device_serial.shellescape} shell getprop ro.build.version.sdk",
|
418
435
|
print_all: true, print_command: true).to_i
|
419
436
|
end
|
420
437
|
|
421
|
-
def enable_clean_status_bar(device_serial,
|
422
|
-
return unless
|
423
|
-
|
424
|
-
unless @android_env.aapt_path
|
425
|
-
UI.error("The `aapt` command could not be found, so status bar could not be cleaned. Make sure android_home is configured for screengrab or ANDROID_HOME is set in the environment")
|
426
|
-
return
|
427
|
-
end
|
428
|
-
|
429
|
-
# Check if the app wants to use the clean status bar feature
|
430
|
-
badging_dump = @executor.execute(command: "#{@android_env.aapt_path} dump badging #{app_apk_path}",
|
431
|
-
print_all: true, print_command: true)
|
432
|
-
return unless badging_dump.include?('uses-feature: name=\'tools.fastlane.screengrab.cleanstatusbar\'')
|
438
|
+
def enable_clean_status_bar(device_serial, sdk_version)
|
439
|
+
return unless sdk_version >= 23
|
433
440
|
|
434
441
|
UI.message('Enabling clean status bar')
|
435
442
|
|
436
|
-
# Make sure the app requests the DUMP permission
|
437
|
-
unless badging_dump.include?('uses-permission: name=\'android.permission.DUMP\'')
|
438
|
-
UI.user_error!("The clean status bar feature requires the android.permission.DUMP permission but it could not be found in your app APK")
|
439
|
-
end
|
440
|
-
|
441
443
|
# Grant the DUMP permission
|
442
|
-
run_adb_command("-s #{device_serial} shell pm grant #{@config[:app_package_name]} android.permission.DUMP",
|
443
|
-
print_all: true, print_command: true)
|
444
|
+
run_adb_command("-s #{device_serial.shellescape} shell pm grant #{@config[:app_package_name].shellescape.shellescape} android.permission.DUMP",
|
445
|
+
print_all: true, print_command: true, raise_errors: false)
|
444
446
|
|
445
447
|
# Enable the SystemUI demo mode
|
446
|
-
run_adb_command("-s #{device_serial} shell settings put global sysui_demo_allowed 1",
|
448
|
+
run_adb_command("-s #{device_serial.shellescape} shell settings put global sysui_demo_allowed 1",
|
447
449
|
print_all: true, print_command: true)
|
448
450
|
end
|
449
451
|
end
|