fastlane 2.135.0 → 2.138.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 +4 -4
- data/README.md +78 -78
- data/fastlane/lib/fastlane/actions/app_store_build_number.rb +1 -1
- data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +38 -4
- data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +19 -0
- data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +4 -2
- data/fastlane/lib/fastlane/actions/ensure_bundle_exec.rb +3 -3
- data/fastlane/lib/fastlane/actions/get_version_number.rb +7 -2
- data/fastlane/lib/fastlane/actions/google_play_track_version_codes.rb +5 -1
- data/fastlane/lib/fastlane/actions/gradle.rb +11 -1
- data/fastlane/lib/fastlane/actions/increment_version_number.rb +6 -3
- data/fastlane/lib/fastlane/actions/latest_testflight_build_number.rb +2 -2
- data/fastlane/lib/fastlane/actions/register_devices.rb +5 -1
- data/fastlane/lib/fastlane/actions/ruby_version.rb +1 -1
- data/fastlane/lib/fastlane/actions/testfairy.rb +8 -1
- data/fastlane/lib/fastlane/actions/verify_build.rb +1 -1
- data/fastlane/lib/fastlane/actions/xcode_select.rb +6 -1
- data/fastlane/lib/fastlane/cli_tools_distributor.rb +2 -2
- data/fastlane/lib/fastlane/commands_generator.rb +1 -1
- data/fastlane/lib/fastlane/helper/adb_helper.rb +13 -4
- data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +1 -0
- data/fastlane/lib/fastlane/swift_fastlane_function.rb +9 -0
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/Fastlane.swift +47 -17
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +6 -2
- data/fastlane/swift/Precheckfile.swift +1 -1
- data/fastlane/swift/Scanfile.swift +1 -1
- data/fastlane/swift/Screengrabfile.swift +1 -1
- data/fastlane/swift/ScreengrabfileProtocol.swift +14 -2
- data/fastlane/swift/Snapshotfile.swift +1 -1
- data/fastlane_core/lib/fastlane_core/helper.rb +1 -1
- data/match/lib/match/options.rb +8 -0
- data/match/lib/match/runner.rb +1 -0
- data/match/lib/match/storage/git_storage.rb +7 -2
- data/screengrab/lib/screengrab/module.rb +2 -0
- data/screengrab/lib/screengrab/options.rb +24 -11
- data/screengrab/lib/screengrab/runner.rb +79 -42
- data/spaceship/lib/spaceship/client.rb +9 -4
- data/spaceship/lib/spaceship/connect_api.rb +2 -0
- data/spaceship/lib/spaceship/connect_api/models/app.rb +11 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_feedback.rb +71 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_screenshot.rb +18 -0
- data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +9 -0
- data/spaceship/lib/spaceship/tunes/tunes_client.rb +2 -5
- data/supply/lib/supply/client.rb +1 -0
- data/supply/lib/supply/options.rb +9 -2
- data/supply/lib/supply/uploader.rb +63 -39
- metadata +22 -24
- data/gym/lib/gym/.module.rb.swp +0 -0
- data/supply/lib/supply/.client.rb.swp +0 -0
- data/supply/lib/supply/.options.rb.swp +0 -0
- data/supply/lib/supply/.uploader.rb.swp +0 -0
@@ -48,6 +48,9 @@ protocol MatchfileProtocol: class {
|
|
48
48
|
/// Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64
|
49
49
|
var gitBasicAuthorization: String? { get }
|
50
50
|
|
51
|
+
/// Use a bearer authorization header to access the git repo (e.g.: access to an Azure Devops repository), usually a string in Base64
|
52
|
+
var gitBearerAuthorization: String? { get }
|
53
|
+
|
51
54
|
/// Name of the Google Cloud Storage bucket to use
|
52
55
|
var googleCloudBucketName: String? { get }
|
53
56
|
|
@@ -91,7 +94,7 @@ protocol MatchfileProtocol: class {
|
|
91
94
|
extension MatchfileProtocol {
|
92
95
|
var type: String { return "development" }
|
93
96
|
var readonly: Bool { return false }
|
94
|
-
var generateAppleCerts: Bool { return
|
97
|
+
var generateAppleCerts: Bool { return true }
|
95
98
|
var skipProvisioningProfiles: Bool { return false }
|
96
99
|
var appIdentifier: [String] { return [] }
|
97
100
|
var username: String { return "" }
|
@@ -105,6 +108,7 @@ extension MatchfileProtocol {
|
|
105
108
|
var shallowClone: Bool { return false }
|
106
109
|
var cloneBranchDirectly: Bool { return false }
|
107
110
|
var gitBasicAuthorization: String? { return nil }
|
111
|
+
var gitBearerAuthorization: String? { return nil }
|
108
112
|
var googleCloudBucketName: String? { return nil }
|
109
113
|
var googleCloudKeysFile: String? { return nil }
|
110
114
|
var googleCloudProjectId: String? { return nil }
|
@@ -122,4 +126,4 @@ extension MatchfileProtocol {
|
|
122
126
|
|
123
127
|
// Please don't remove the lines below
|
124
128
|
// They are used to detect outdated files
|
125
|
-
// FastlaneRunnerAPIVersion [0.9.
|
129
|
+
// FastlaneRunnerAPIVersion [0.9.12]
|
@@ -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,12 @@ 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 }
|
59
68
|
}
|
60
69
|
|
61
70
|
extension ScreengrabfileProtocol {
|
@@ -70,16 +79,19 @@ extension ScreengrabfileProtocol {
|
|
70
79
|
var useTestsInPackages: [String]? { return nil }
|
71
80
|
var useTestsInClasses: [String]? { return nil }
|
72
81
|
var launchArguments: [String]? { return nil }
|
73
|
-
var testInstrumentationRunner: String { return "
|
82
|
+
var testInstrumentationRunner: String { return "androidx.test.runner.AndroidJUnitRunner" }
|
74
83
|
var endingLocale: String { return "en-US" }
|
84
|
+
var useAdbRoot: Bool { return false }
|
75
85
|
var appApkPath: String? { return nil }
|
76
86
|
var testsApkPath: String? { return nil }
|
77
87
|
var specificDevice: String? { return nil }
|
78
88
|
var deviceType: String { return "phone" }
|
79
89
|
var exitOnTestFailure: Bool { return true }
|
80
90
|
var reinstallApp: Bool { return false }
|
91
|
+
var useTimestampSuffix: Bool { return true }
|
92
|
+
var adbHost: String? { return nil }
|
81
93
|
}
|
82
94
|
|
83
95
|
// Please don't remove the lines below
|
84
96
|
// They are used to detect outdated files
|
85
|
-
// FastlaneRunnerAPIVersion [0.9.
|
97
|
+
// FastlaneRunnerAPIVersion [0.9.13]
|
@@ -72,7 +72,7 @@ module FastlaneCore
|
|
72
72
|
# @return [boolean] true if building in a known CI environment
|
73
73
|
def self.ci?
|
74
74
|
# Check for Jenkins, Travis CI, ... environment variables
|
75
|
-
['JENKINS_HOME', 'JENKINS_URL', 'TRAVIS', 'CIRCLECI', 'CI', 'APPCENTER_BUILD_ID', 'TEAMCITY_VERSION', 'GO_PIPELINE_NAME', 'bamboo_buildKey', 'GITLAB_CI', 'XCS', 'TF_BUILD', 'GITHUB_ACTION', 'GITHUB_ACTIONS'].each do |current|
|
75
|
+
['JENKINS_HOME', 'JENKINS_URL', 'TRAVIS', 'CIRCLECI', 'CI', 'APPCENTER_BUILD_ID', 'TEAMCITY_VERSION', 'GO_PIPELINE_NAME', 'bamboo_buildKey', 'GITLAB_CI', 'XCS', 'TF_BUILD', 'GITHUB_ACTION', 'GITHUB_ACTIONS', 'BITRISE_IO'].each do |current|
|
76
76
|
return true if ENV.key?(current)
|
77
77
|
end
|
78
78
|
return false
|
data/match/lib/match/options.rb
CHANGED
@@ -125,6 +125,14 @@ module Match
|
|
125
125
|
env_name: "MATCH_GIT_BASIC_AUTHORIZATION",
|
126
126
|
sensitive: true,
|
127
127
|
description: "Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64",
|
128
|
+
conflicting_options: [:git_bearer_authorization],
|
129
|
+
optional: true,
|
130
|
+
default_value: nil),
|
131
|
+
FastlaneCore::ConfigItem.new(key: :git_bearer_authorization,
|
132
|
+
env_name: "MATCH_GIT_BEARER_AUTHORIZATION",
|
133
|
+
sensitive: true,
|
134
|
+
description: "Use a bearer authorization header to access the git repo (e.g.: access to an Azure Devops repository), usually a string in Base64",
|
135
|
+
conflicting_options: [:git_basic_authorization],
|
128
136
|
optional: true,
|
129
137
|
default_value: nil),
|
130
138
|
|
data/match/lib/match/runner.rb
CHANGED
@@ -38,6 +38,7 @@ module Match
|
|
38
38
|
git_user_email: params[:git_user_email],
|
39
39
|
clone_branch_directly: params[:clone_branch_directly],
|
40
40
|
git_basic_authorization: params[:git_basic_authorization],
|
41
|
+
git_bearer_authorization: params[:git_bearer_authorization],
|
41
42
|
type: params[:type].to_s,
|
42
43
|
generate_apple_certs: params[:generate_apple_certs],
|
43
44
|
platform: params[:platform].to_s,
|
@@ -18,6 +18,7 @@ module Match
|
|
18
18
|
attr_accessor :type
|
19
19
|
attr_accessor :platform
|
20
20
|
attr_accessor :git_basic_authorization
|
21
|
+
attr_accessor :git_bearer_authorization
|
21
22
|
|
22
23
|
def self.configure(params)
|
23
24
|
return self.new(
|
@@ -30,7 +31,8 @@ module Match
|
|
30
31
|
git_full_name: params[:git_full_name],
|
31
32
|
git_user_email: params[:git_user_email],
|
32
33
|
clone_branch_directly: params[:clone_branch_directly],
|
33
|
-
git_basic_authorization: params[:git_basic_authorization]
|
34
|
+
git_basic_authorization: params[:git_basic_authorization],
|
35
|
+
git_bearer_authorization: params[:git_bearer_authorization]
|
34
36
|
)
|
35
37
|
end
|
36
38
|
|
@@ -43,7 +45,8 @@ module Match
|
|
43
45
|
git_full_name: nil,
|
44
46
|
git_user_email: nil,
|
45
47
|
clone_branch_directly: false,
|
46
|
-
git_basic_authorization: nil
|
48
|
+
git_basic_authorization: nil,
|
49
|
+
git_bearer_authorization: nil)
|
47
50
|
self.git_url = git_url
|
48
51
|
self.shallow_clone = shallow_clone
|
49
52
|
self.skip_docs = skip_docs
|
@@ -52,6 +55,7 @@ module Match
|
|
52
55
|
self.git_user_email = git_user_email
|
53
56
|
self.clone_branch_directly = clone_branch_directly
|
54
57
|
self.git_basic_authorization = git_basic_authorization
|
58
|
+
self.git_bearer_authorization = git_bearer_authorization
|
55
59
|
|
56
60
|
self.type = type if type
|
57
61
|
self.platform = platform if platform
|
@@ -70,6 +74,7 @@ module Match
|
|
70
74
|
|
71
75
|
command = "git clone #{self.git_url.shellescape} #{self.working_directory.shellescape}"
|
72
76
|
command << " -c http.extraheader='AUTHORIZATION: basic #{self.git_basic_authorization}'" unless self.git_basic_authorization.nil?
|
77
|
+
command << " -c http.extraheader='AUTHORIZATION: bearer #{self.git_bearer_authorization}'" unless self.git_bearer_authorization.nil?
|
73
78
|
|
74
79
|
if self.shallow_clone
|
75
80
|
command << " --depth 1 --no-single-branch"
|
@@ -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
|
-
|
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
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
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: '
|
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,21 @@ 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
|
-
|
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
|
-
|
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)
|
132
145
|
]
|
133
146
|
end
|
134
147
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'fastlane_core/print_table'
|
2
2
|
require 'fastlane_core/command_executor'
|
3
|
+
require 'fastlane/helper/adb_helper'
|
3
4
|
require_relative 'reports_generator'
|
4
5
|
require_relative 'module'
|
5
6
|
|
@@ -57,8 +58,13 @@ module Screengrab
|
|
57
58
|
|
58
59
|
device_screenshots_paths = [
|
59
60
|
determine_external_screenshots_path(device_serial),
|
60
|
-
|
61
|
-
]
|
61
|
+
determine_internal_screenshots_paths(@config[:app_package_name], @config[:locales])
|
62
|
+
].flatten
|
63
|
+
|
64
|
+
# Root is needed to access device paths at /data
|
65
|
+
if @config[:use_adb_root]
|
66
|
+
run_adb_command("root", print_all: false, print_command: true)
|
67
|
+
end
|
62
68
|
|
63
69
|
clear_device_previous_screenshots(device_serial, device_screenshots_paths)
|
64
70
|
|
@@ -67,6 +73,8 @@ module Screengrab
|
|
67
73
|
|
68
74
|
validate_apk(app_apk_path)
|
69
75
|
|
76
|
+
enable_clean_status_bar(device_serial, app_apk_path)
|
77
|
+
|
70
78
|
run_tests(device_serial, app_apk_path, tests_apk_path, test_classes_to_use, test_packages_to_use, @config[:launch_arguments])
|
71
79
|
|
72
80
|
number_of_screenshots = pull_screenshots_from_device(device_serial, device_screenshots_paths, device_type_dir_name)
|
@@ -77,35 +85,26 @@ module Screengrab
|
|
77
85
|
end
|
78
86
|
|
79
87
|
def select_device
|
80
|
-
|
81
|
-
|
82
|
-
devices.reject! do |device|
|
83
|
-
[
|
84
|
-
'server is out of date', # The adb server is out of date and must be restarted
|
85
|
-
'unauthorized', # The device has not yet accepted ADB control
|
86
|
-
'offline', # The device is offline, skip it
|
87
|
-
'* daemon', # Messages printed when the daemon is starting up
|
88
|
-
'List of devices attached', # Header of table for data we want
|
89
|
-
"doesn't match this client" # Message printed when there is an ADB client/server version mismatch
|
90
|
-
].any? { |status| device.include?(status) }
|
91
|
-
end
|
88
|
+
adb = Fastlane::Helper::AdbHelper.new(adb_host: @config[:adb_host])
|
89
|
+
devices = adb.load_all_devices
|
92
90
|
|
93
91
|
UI.user_error!('There are no connected and authorized devices or emulators') if devices.empty?
|
94
92
|
|
95
|
-
|
93
|
+
specific_device = @config[:specific_device]
|
94
|
+
if specific_device
|
95
|
+
devices.select! do |d|
|
96
|
+
d.serial.include?(specific_device)
|
97
|
+
end
|
98
|
+
end
|
96
99
|
|
97
|
-
UI.user_error!("No connected devices matched your criteria: #{
|
100
|
+
UI.user_error!("No connected devices matched your criteria: #{specific_device}") if devices.empty?
|
98
101
|
|
99
102
|
if devices.length > 1
|
100
103
|
UI.important("Multiple connected devices, selecting the first one")
|
101
104
|
UI.important("To specify which connected device to use, use the -s (specific_device) config option")
|
102
105
|
end
|
103
106
|
|
104
|
-
|
105
|
-
# 00c22d4d84aec525 device usb:2148663295X product:bullhead model:Nexus_5X device:bullhead
|
106
|
-
# 192.168.1.100:5555 device usb:2148663295X product:bullhead model:Nexus_5X device:genymotion
|
107
|
-
# emulator-5554 device usb:2148663295X product:bullhead model:Nexus_5X device:emulator
|
108
|
-
devices[0].match(/^\S+/)[0]
|
107
|
+
devices.first.serial
|
109
108
|
end
|
110
109
|
|
111
110
|
def select_app_apk(discovered_apk_paths)
|
@@ -139,15 +138,19 @@ module Screengrab
|
|
139
138
|
# macOS evaluates $foo in `echo $foo` before executing the command,
|
140
139
|
# Windows doesn't - hence the double backslash vs. single backslash
|
141
140
|
command = Helper.windows? ? "shell echo \$EXTERNAL_STORAGE " : "shell echo \\$EXTERNAL_STORAGE"
|
142
|
-
device_ext_storage = run_adb_command("
|
141
|
+
device_ext_storage = run_adb_command("-s #{device_serial} #{command}",
|
143
142
|
print_all: true,
|
144
143
|
print_command: true)
|
145
144
|
device_ext_storage = device_ext_storage.strip
|
146
145
|
File.join(device_ext_storage, @config[:app_package_name], 'screengrab')
|
147
146
|
end
|
148
147
|
|
149
|
-
def
|
150
|
-
|
148
|
+
def determine_internal_screenshots_paths(app_package_name, locales)
|
149
|
+
locale_paths = locales.map do |locale|
|
150
|
+
"/data/user/0/#{app_package_name}/files/#{app_package_name}/screengrab/#{locale}/images/screenshots"
|
151
|
+
end
|
152
|
+
|
153
|
+
return ["/data/data/#{app_package_name}/app_screengrab"] + locale_paths
|
151
154
|
end
|
152
155
|
|
153
156
|
def clear_device_previous_screenshots(device_serial, device_screenshots_paths)
|
@@ -155,7 +158,7 @@ module Screengrab
|
|
155
158
|
|
156
159
|
device_screenshots_paths.each do |device_path|
|
157
160
|
if_device_path_exists(device_serial, device_path) do |path|
|
158
|
-
run_adb_command("
|
161
|
+
run_adb_command("-s #{device_serial} shell rm -rf #{path}",
|
159
162
|
print_all: true,
|
160
163
|
print_command: true)
|
161
164
|
end
|
@@ -182,13 +185,13 @@ module Screengrab
|
|
182
185
|
|
183
186
|
def install_apks(device_serial, app_apk_path, tests_apk_path)
|
184
187
|
UI.message('Installing app APK')
|
185
|
-
apk_install_output = run_adb_command("
|
188
|
+
apk_install_output = run_adb_command("-s #{device_serial} install -t -r #{app_apk_path.shellescape}",
|
186
189
|
print_all: true,
|
187
190
|
print_command: true)
|
188
191
|
UI.user_error!("App APK could not be installed") if apk_install_output.include?("Failure [")
|
189
192
|
|
190
193
|
UI.message('Installing tests APK')
|
191
|
-
apk_install_output = run_adb_command("
|
194
|
+
apk_install_output = run_adb_command("-s #{device_serial} install -t -r #{tests_apk_path.shellescape}",
|
192
195
|
print_all: true,
|
193
196
|
print_command: true)
|
194
197
|
UI.user_error!("Tests APK could not be installed") if apk_install_output.include?("Failure [")
|
@@ -199,14 +202,14 @@ module Screengrab
|
|
199
202
|
|
200
203
|
if packages.include?(app_package_name.to_s)
|
201
204
|
UI.message('Uninstalling app APK')
|
202
|
-
run_adb_command("
|
205
|
+
run_adb_command("-s #{device_serial} uninstall #{app_package_name}",
|
203
206
|
print_all: true,
|
204
207
|
print_command: true)
|
205
208
|
end
|
206
209
|
|
207
210
|
if packages.include?(tests_package_name.to_s)
|
208
211
|
UI.message('Uninstalling tests APK')
|
209
|
-
run_adb_command("
|
212
|
+
run_adb_command("-s #{device_serial} uninstall #{tests_package_name}",
|
210
213
|
print_all: true,
|
211
214
|
print_command: true)
|
212
215
|
end
|
@@ -214,20 +217,16 @@ module Screengrab
|
|
214
217
|
|
215
218
|
def grant_permissions(device_serial)
|
216
219
|
UI.message('Granting the permission necessary to change locales on the device')
|
217
|
-
run_adb_command("
|
220
|
+
run_adb_command("-s #{device_serial} shell pm grant #{@config[:app_package_name]} android.permission.CHANGE_CONFIGURATION",
|
218
221
|
print_all: true,
|
219
222
|
print_command: true)
|
220
223
|
|
221
|
-
device_api_version
|
222
|
-
print_all: true,
|
223
|
-
print_command: true).to_i
|
224
|
-
|
225
|
-
if device_api_version >= 23
|
224
|
+
if device_api_version(device_serial) >= 23
|
226
225
|
UI.message('Granting the permissions necessary to access device external storage')
|
227
|
-
run_adb_command("
|
226
|
+
run_adb_command("-s #{device_serial} shell pm grant #{@config[:app_package_name]} android.permission.WRITE_EXTERNAL_STORAGE",
|
228
227
|
print_all: true,
|
229
228
|
print_command: true)
|
230
|
-
run_adb_command("
|
229
|
+
run_adb_command("-s #{device_serial} shell pm grant #{@config[:app_package_name]} android.permission.READ_EXTERNAL_STORAGE",
|
231
230
|
print_all: true,
|
232
231
|
print_command: true)
|
233
232
|
end
|
@@ -252,9 +251,10 @@ module Screengrab
|
|
252
251
|
def run_tests_for_locale(locale, device_serial, test_classes_to_use, test_packages_to_use, launch_arguments)
|
253
252
|
UI.message("Running tests for locale: #{locale}")
|
254
253
|
|
255
|
-
instrument_command = ["
|
254
|
+
instrument_command = ["-s #{device_serial} shell am instrument --no-window-animation -w",
|
256
255
|
"-e testLocale #{locale.tr('-', '_')}",
|
257
256
|
"-e endingLocale #{@config[:ending_locale].tr('-', '_')}"]
|
257
|
+
instrument_command << "-e appendTimestamp #{@config[:use_timestamp_suffix]}"
|
258
258
|
instrument_command << "-e class #{test_classes_to_use.join(',')}" if test_classes_to_use
|
259
259
|
instrument_command << "-e package #{test_packages_to_use.join(',')}" if test_packages_to_use
|
260
260
|
instrument_command << launch_arguments.map { |item| '-e ' + item }.join(' ') if launch_arguments
|
@@ -281,10 +281,11 @@ module Screengrab
|
|
281
281
|
|
282
282
|
# Make a temp directory into which to pull the screenshots before they are moved to their final location.
|
283
283
|
# This makes directory cleanup easier, as the temp directory will be removed when the block completes.
|
284
|
+
|
284
285
|
Dir.mktmpdir do |tempdir|
|
285
286
|
device_screenshots_paths.each do |device_path|
|
286
287
|
if_device_path_exists(device_serial, device_path) do |path|
|
287
|
-
run_adb_command("
|
288
|
+
run_adb_command("-s #{device_serial} pull #{path} #{tempdir}",
|
288
289
|
print_all: false,
|
289
290
|
print_command: true)
|
290
291
|
end
|
@@ -347,7 +348,7 @@ module Screengrab
|
|
347
348
|
# Some device commands fail if executed against a device path that does not exist, so this helper method
|
348
349
|
# provides a way to conditionally execute a block only if the provided path exists on the device.
|
349
350
|
def if_device_path_exists(device_serial, device_path)
|
350
|
-
return if run_adb_command("
|
351
|
+
return if run_adb_command("-s #{device_serial} shell ls #{device_path}",
|
351
352
|
print_all: false,
|
352
353
|
print_command: false).include?('No such file')
|
353
354
|
|
@@ -359,7 +360,7 @@ module Screengrab
|
|
359
360
|
|
360
361
|
# Return an array of packages that are installed on the device
|
361
362
|
def installed_packages(device_serial)
|
362
|
-
packages = run_adb_command("
|
363
|
+
packages = run_adb_command("-s #{device_serial} shell pm list packages",
|
363
364
|
print_all: true,
|
364
365
|
print_command: true)
|
365
366
|
packages.split("\n").map { |package| package.gsub("package:", "") }
|
@@ -367,7 +368,9 @@ module Screengrab
|
|
367
368
|
|
368
369
|
def run_adb_command(command, print_all: false, print_command: false)
|
369
370
|
adb_path = @android_env.adb_path.chomp("adb")
|
370
|
-
|
371
|
+
adb_host = @config[:adb_host]
|
372
|
+
host = adb_host.nil? ? '' : "-H #{adb_host} "
|
373
|
+
output = @executor.execute(command: adb_path + "adb " + host + command,
|
371
374
|
print_all: print_all,
|
372
375
|
print_command: print_command) || ''
|
373
376
|
output.lines.reject do |line|
|
@@ -375,5 +378,39 @@ module Screengrab
|
|
375
378
|
line.start_with?('adb: ')
|
376
379
|
end.join('') # Lines retain their newline chars
|
377
380
|
end
|
381
|
+
|
382
|
+
def device_api_version(device_serial)
|
383
|
+
run_adb_command("-s #{device_serial} shell getprop ro.build.version.sdk",
|
384
|
+
print_all: true, print_command: true).to_i
|
385
|
+
end
|
386
|
+
|
387
|
+
def enable_clean_status_bar(device_serial, app_apk_path)
|
388
|
+
return unless device_api_version(device_serial) >= 23
|
389
|
+
|
390
|
+
unless @android_env.aapt_path
|
391
|
+
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")
|
392
|
+
return
|
393
|
+
end
|
394
|
+
|
395
|
+
# Check if the app wants to use the clean status bar feature
|
396
|
+
badging_dump = @executor.execute(command: "#{@android_env.aapt_path} dump badging #{app_apk_path}",
|
397
|
+
print_all: true, print_command: true)
|
398
|
+
return unless badging_dump.include?('uses-feature: name=\'tools.fastlane.screengrab.cleanstatusbar\'')
|
399
|
+
|
400
|
+
UI.message('Enabling clean status bar')
|
401
|
+
|
402
|
+
# Make sure the app requests the DUMP permission
|
403
|
+
unless badging_dump.include?('uses-permission: name=\'android.permission.DUMP\'')
|
404
|
+
UI.user_error!("The clean status bar feature requires the android.permission.DUMP permission but it could not be found in your app APK")
|
405
|
+
end
|
406
|
+
|
407
|
+
# Grant the DUMP permission
|
408
|
+
run_adb_command("-s #{device_serial} shell pm grant #{@config[:app_package_name]} android.permission.DUMP",
|
409
|
+
print_all: true, print_command: true)
|
410
|
+
|
411
|
+
# Enable the SystemUI demo mode
|
412
|
+
run_adb_command("-s #{device_serial} shell settings put global sysui_demo_allowed 1",
|
413
|
+
print_all: true, print_command: true)
|
414
|
+
end
|
378
415
|
end
|
379
416
|
end
|