fastlane 2.135.2 → 2.136.0

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: bc8a348892470f7c95c046a30e878eeb46a3364e29266d6e2eede8820cda60c9
4
- data.tar.gz: a33412ac7217f0dfe530dcbee955c80c3290cdacabaef708ae9a755008470863
3
+ metadata.gz: b8c1652cb1f5fa0d2fbd567e4d4721fc85be17dae9506afcf4fe8c9bd80c3ec6
4
+ data.tar.gz: d257b400a19b96ccb7a0803af98f71cc6af521b8745a27e4a5083e547a7387bd
5
5
  SHA512:
6
- metadata.gz: f1eb4a8112757f60290d56eb206f26039b5c47abf1999cd09fcfe29eb308596aa8e117057c4ea09e651c2d63526effae43ff9e0b8d577ce155fe9ff36a110e83
7
- data.tar.gz: f071dcaa3f3a11baa944d5c6408a544a3f7f42d76ec9bdfa32d2a962717242587583e958d8bbd4c2dade656d0b95779c971ddaaabdb0f49da42a3ebcd4171b0b
6
+ metadata.gz: a83e00a94cac8a0ac90f1273f70c1676dc1ddee5190599b84c1b2759b09d6f79054cbf13e9b1c3c1c7c928ccb941ec322a35ff9f479c7324db1ff9c71f541917
7
+ data.tar.gz: 1a70fc80b4d8bfddec51d92044dbc36d806629ae03e8d3b55be3832d5694ecb06391f1c2e6df47477c439c61522a4849317fac988f360e7407bd206caac96bfb
data/README.md CHANGED
@@ -34,49 +34,55 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
34
34
  <!-- This table is regenerated and resorted on each release -->
35
35
  <table id='team'>
36
36
  <tr>
37
- <td id='iulian-onofrei'>
38
- <a href='https://github.com/revolter'>
39
- <img src='https://github.com/revolter.png?size=140'>
37
+ <td id='felix-krause'>
38
+ <a href='https://github.com/KrauseFx'>
39
+ <img src='https://github.com/KrauseFx.png?size=140'>
40
40
  </a>
41
- <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
41
+ <h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
42
42
  </td>
43
- <td id='stefan-natchev'>
44
- <a href='https://github.com/snatchev'>
45
- <img src='https://github.com/snatchev.png?size=140'>
43
+ <td id='matthew-ellis'>
44
+ <a href='https://github.com/matthewellis'>
45
+ <img src='https://github.com/matthewellis.png?size=140'>
46
46
  </a>
47
- <h4 align='center'><a href='https://twitter.com/snatchev'>Stefan Natchev</a></h4>
47
+ <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
48
48
  </td>
49
- <td id='jorge-revuelta-h'>
50
- <a href='https://github.com/minuscorp'>
51
- <img src='https://github.com/minuscorp.png?size=140'>
49
+ <td id='luka-mirosevic'>
50
+ <a href='https://github.com/lmirosevic'>
51
+ <img src='https://github.com/lmirosevic.png?size=140'>
52
52
  </a>
53
- <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
53
+ <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
54
54
  </td>
55
- <td id='josh-holtz'>
56
- <a href='https://github.com/joshdholtz'>
57
- <img src='https://github.com/joshdholtz.png?size=140'>
55
+ <td id='aaron-brager'>
56
+ <a href='https://github.com/getaaron'>
57
+ <img src='https://github.com/getaaron.png?size=140'>
58
58
  </a>
59
- <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
59
+ <h4 align='center'><a href='https://twitter.com/getaaron'>Aaron Brager</a></h4>
60
60
  </td>
61
- <td id='danielle-tomlinson'>
62
- <a href='https://github.com/endocrimes'>
63
- <img src='https://github.com/endocrimes.png?size=140'>
61
+ <td id='fumiya-nakamura'>
62
+ <a href='https://github.com/nafu'>
63
+ <img src='https://github.com/nafu.png?size=140'>
64
64
  </a>
65
- <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
65
+ <h4 align='center'><a href='https://twitter.com/nafu003'>Fumiya Nakamura</a></h4>
66
66
  </td>
67
67
  </tr>
68
68
  <tr>
69
- <td id='joshua-liebowitz'>
70
- <a href='https://github.com/taquitos'>
71
- <img src='https://github.com/taquitos.png?size=140'>
69
+ <td id='manu-wallner'>
70
+ <a href='https://github.com/milch'>
71
+ <img src='https://github.com/milch.png?size=140'>
72
72
  </a>
73
- <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
73
+ <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
74
74
  </td>
75
- <td id='olivier-halligon'>
76
- <a href='https://github.com/AliSoftware'>
77
- <img src='https://github.com/AliSoftware.png?size=140'>
75
+ <td id='helmut-januschka'>
76
+ <a href='https://github.com/hjanuschka'>
77
+ <img src='https://github.com/hjanuschka.png?size=140'>
78
78
  </a>
79
- <h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
79
+ <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
80
+ </td>
81
+ <td id='kohki-miki'>
82
+ <a href='https://github.com/giginet'>
83
+ <img src='https://github.com/giginet.png?size=140'>
84
+ </a>
85
+ <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
80
86
  </td>
81
87
  <td id='maksym-grebenets'>
82
88
  <a href='https://github.com/mgrebenets'>
@@ -84,81 +90,75 @@ If the above doesn't help, please [submit an issue](https://github.com/fastlane/
84
90
  </a>
85
91
  <h4 align='center'><a href='https://twitter.com/mgrebenets'>Maksym Grebenets</a></h4>
86
92
  </td>
87
- <td id='jérôme-lacoste'>
88
- <a href='https://github.com/lacostej'>
89
- <img src='https://github.com/lacostej.png?size=140'>
90
- </a>
91
- <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
92
- </td>
93
- <td id='kohki-miki'>
94
- <a href='https://github.com/giginet'>
95
- <img src='https://github.com/giginet.png?size=140'>
93
+ <td id='stefan-natchev'>
94
+ <a href='https://github.com/snatchev'>
95
+ <img src='https://github.com/snatchev.png?size=140'>
96
96
  </a>
97
- <h4 align='center'><a href='https://twitter.com/giginet'>Kohki Miki</a></h4>
97
+ <h4 align='center'><a href='https://twitter.com/snatchev'>Stefan Natchev</a></h4>
98
98
  </td>
99
99
  </tr>
100
100
  <tr>
101
+ <td id='iulian-onofrei'>
102
+ <a href='https://github.com/revolter'>
103
+ <img src='https://github.com/revolter.png?size=140'>
104
+ </a>
105
+ <h4 align='center'><a href='https://twitter.com/Revolt666'>Iulian Onofrei</a></h4>
106
+ </td>
101
107
  <td id='andrew-mcburney'>
102
108
  <a href='https://github.com/armcburney'>
103
109
  <img src='https://github.com/armcburney.png?size=140'>
104
110
  </a>
105
111
  <h4 align='center'><a href='https://twitter.com/armcburney'>Andrew McBurney</a></h4>
106
112
  </td>
107
- <td id='luka-mirosevic'>
108
- <a href='https://github.com/lmirosevic'>
109
- <img src='https://github.com/lmirosevic.png?size=140'>
110
- </a>
111
- <h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
112
- </td>
113
- <td id='jan-piotrowski'>
114
- <a href='https://github.com/janpio'>
115
- <img src='https://github.com/janpio.png?size=140'>
113
+ <td id='olivier-halligon'>
114
+ <a href='https://github.com/AliSoftware'>
115
+ <img src='https://github.com/AliSoftware.png?size=140'>
116
116
  </a>
117
- <h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
117
+ <h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
118
118
  </td>
119
- <td id='fumiya-nakamura'>
120
- <a href='https://github.com/nafu'>
121
- <img src='https://github.com/nafu.png?size=140'>
119
+ <td id='jorge-revuelta-h'>
120
+ <a href='https://github.com/minuscorp'>
121
+ <img src='https://github.com/minuscorp.png?size=140'>
122
122
  </a>
123
- <h4 align='center'><a href='https://twitter.com/nafu003'>Fumiya Nakamura</a></h4>
123
+ <h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
124
124
  </td>
125
- <td id='felix-krause'>
126
- <a href='https://github.com/KrauseFx'>
127
- <img src='https://github.com/KrauseFx.png?size=140'>
125
+ <td id='josh-holtz'>
126
+ <a href='https://github.com/joshdholtz'>
127
+ <img src='https://github.com/joshdholtz.png?size=140'>
128
128
  </a>
129
- <h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
129
+ <h4 align='center'><a href='https://twitter.com/joshdholtz'>Josh Holtz</a></h4>
130
130
  </td>
131
131
  </tr>
132
132
  <tr>
133
- <td id='manu-wallner'>
134
- <a href='https://github.com/milch'>
135
- <img src='https://github.com/milch.png?size=140'>
133
+ <td id='danielle-tomlinson'>
134
+ <a href='https://github.com/endocrimes'>
135
+ <img src='https://github.com/endocrimes.png?size=140'>
136
136
  </a>
137
- <h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
137
+ <h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
138
138
  </td>
139
- <td id='helmut-januschka'>
140
- <a href='https://github.com/hjanuschka'>
141
- <img src='https://github.com/hjanuschka.png?size=140'>
139
+ <td id='jérôme-lacoste'>
140
+ <a href='https://github.com/lacostej'>
141
+ <img src='https://github.com/lacostej.png?size=140'>
142
142
  </a>
143
- <h4 align='center'><a href='https://twitter.com/hjanuschka'>Helmut Januschka</a></h4>
143
+ <h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
144
144
  </td>
145
- <td id='jimmy-dee'>
146
- <a href='https://github.com/jdee'>
147
- <img src='https://github.com/jdee.png?size=140'>
145
+ <td id='joshua-liebowitz'>
146
+ <a href='https://github.com/taquitos'>
147
+ <img src='https://github.com/taquitos.png?size=140'>
148
148
  </a>
149
- <h4 align='center'>Jimmy Dee</h4>
149
+ <h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
150
150
  </td>
151
- <td id='aaron-brager'>
152
- <a href='https://github.com/getaaron'>
153
- <img src='https://github.com/getaaron.png?size=140'>
151
+ <td id='jan-piotrowski'>
152
+ <a href='https://github.com/janpio'>
153
+ <img src='https://github.com/janpio.png?size=140'>
154
154
  </a>
155
- <h4 align='center'><a href='https://twitter.com/getaaron'>Aaron Brager</a></h4>
155
+ <h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
156
156
  </td>
157
- <td id='matthew-ellis'>
158
- <a href='https://github.com/matthewellis'>
159
- <img src='https://github.com/matthewellis.png?size=140'>
157
+ <td id='jimmy-dee'>
158
+ <a href='https://github.com/jdee'>
159
+ <img src='https://github.com/jdee.png?size=140'>
160
160
  </a>
161
- <h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
161
+ <h4 align='center'>Jimmy Dee</h4>
162
162
  </td>
163
163
  </tr>
164
164
  </table>
@@ -26,11 +26,13 @@ sudo gem install fastlane
26
26
 
27
27
  ##### Gradle dependency
28
28
  ```java
29
- androidTestCompile('tools.fastlane:screengrab:x.x.x')
29
+ androidTestImplementation 'tools.fastlane:screengrab:x.x.x'
30
30
  ```
31
31
 
32
32
  The latest version is [ ![Download](https://api.bintray.com/packages/fastlane/fastlane/screengrab/images/download.svg) ](https://bintray.com/fastlane/fastlane/screengrab/_latestVersion)
33
33
 
34
+ As of Screengrab version 2.0.0, all Android test dependencies are AndroidX dependencies. This means a device with API 18+, Android 4.3 or greater is required. If you wish to capture screenshots with an older Android OS, then you must use a 1.x.x version.
35
+
34
36
  ##### Configuring your Manifest Permissions
35
37
 
36
38
  Ensure that the following permissions exist in your **src/debug/AndroidManifest.xml**
@@ -82,10 +84,10 @@ As of _screengrab_ 0.5.0, you can specify different strategies to control the wa
82
84
  * Multi-window situations are correctly captured (dialogs, etc.)
83
85
  * Works on Android N
84
86
 
85
- However, UI Automator requires a device with **API level >= 18**, so it is not yet the default strategy. To enable it for all screenshots by default, make the following call before your tests run:
87
+ UI Automator is the default strategy. However, UI Automator requires a device with **API level >= 18**. If you need to grab screenshots on an older Android version, use the latest 1.x.x version of this library and set the DecorView ScreenshotStrategy.
86
88
 
87
89
  ```java
88
- Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy());
90
+ Screengrab.setDefaultScreenshotStrategy(new DecorViewScreenshotStrategy());
89
91
  ```
90
92
 
91
93
  ## Improved screenshot capture with Falcon
@@ -169,7 +171,39 @@ If you're having trouble getting your device unlocked and the screen activated t
169
171
 
170
172
  ## Clean Status Bar
171
173
 
172
- You can use [QuickDemo](https://github.com/PSPDFKit-labs/QuickDemo) to clean up the status bar for your screenshots.
174
+ Screengrab can clean your status bar to make your screenshots even more beautiful.
175
+ Note: the clean status bar feature is only supported on devices with *API level >= 23*.
176
+
177
+ To use the clean status bar feature add the following lines to your src/debug/AndroidManifest.xml
178
+ ```xml
179
+ <!-- Indicates the use of the clean status bar feature -->
180
+ <uses-feature android:name="tools.fastlane.screengrab.cleanstatusbar"/>
181
+ <!-- Allows for changing the status bar -->
182
+ <uses-permission android:name="android.permission.DUMP"/>
183
+ ```
184
+
185
+ After that you can enable and disable the clean status bar at any moment during your tests.
186
+ In most cases you probably want to do this in the @BeforeClass and @AfterClass methods.
187
+ ```java
188
+ @BeforeClass
189
+ public static void beforeAll() {
190
+ CleanStatusBar.enableWithDefaults();
191
+ }
192
+
193
+ @AfterClass
194
+ public static void afterAll() {
195
+ CleanStatusBar.disable();
196
+ }
197
+ ```
198
+
199
+ Have a look at the methods of the `CleanStatusBar` class to customize the status bar even more.
200
+ You could for example show the Bluetooth icon and the LTE text.
201
+ ```java
202
+ new CleanStatusBar()
203
+ .setBluetoothState(BluetoothState.DISCONNECTED)
204
+ .setMobileNetworkDataType(MobileDataType.LTE)
205
+ .enable();
206
+ ```
173
207
 
174
208
  # Advanced _screengrab_
175
209
 
@@ -158,6 +158,7 @@ CrossPlatform/ForkUsage:
158
158
  Lint/IsStringUsage:
159
159
  Include:
160
160
  - gym/**/*
161
+ - screengrab/**/*
161
162
  - supply/**/*
162
163
  Style/MethodCallWithArgsParentheses:
163
164
  Enabled: true
@@ -147,6 +147,7 @@ module Fastlane
147
147
  unless default_value.nil?
148
148
  if type == "[String : Any]"
149
149
  # we can't handle default values for Hashes, yet
150
+ # see method swift_default_implementations for similar behavior
150
151
  default_value = "[:]"
151
152
  elsif type != "Bool" && type != "[String]" && type != "Int" && type != "((String) -> Void)"
152
153
  default_value = "\"#{default_value}\""
@@ -343,6 +344,10 @@ module Fastlane
343
344
  unless default_value.nil?
344
345
  if type == "Bool" || type == "[String]" || type == "Int" || default_value.kind_of?(Array)
345
346
  default_value = default_value.to_s
347
+ elsif default_value.kind_of?(Hash)
348
+ # we can't handle default values for Hashes, yet
349
+ # see method parameters for similar behavior
350
+ default_value = "[:]"
346
351
  else
347
352
  default_value = "\"#{default_value}\""
348
353
  end
@@ -366,6 +371,10 @@ module Fastlane
366
371
  default_value ||= "[]"
367
372
  end
368
373
 
374
+ if type == "[String : Any]"
375
+ default_value ||= "[:]"
376
+ end
377
+
369
378
  " var #{var_for_parameter_name}: #{type} { return #{default_value} }"
370
379
  end
371
380
 
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
- VERSION = '2.135.2'.freeze
2
+ VERSION = '2.136.0'.freeze
3
3
  DESCRIPTION = "The easiest way to automate beta deployments and releases for your iOS and Android apps".freeze
4
4
  MINIMUM_XCODE_RELEASE = "7.0".freeze
5
5
  RUBOCOP_REQUIREMENT = '0.49.1'.freeze
@@ -18,4 +18,4 @@ class Deliverfile: DeliverfileProtocol {
18
18
 
19
19
 
20
20
 
21
- // Generated with fastlane 2.135.2
21
+ // Generated with fastlane 2.136.0
@@ -1210,12 +1210,17 @@ func bundleInstall(binstubs: String? = nil,
1210
1210
  - launchArguments: Additional launch arguments
1211
1211
  - testInstrumentationRunner: The fully qualified class name of your test instrumentation runner
1212
1212
  - endingLocale: Return the device to this locale after running tests
1213
+ - useAdbRoot: Restarts the adb daemon using `adb root` to allow access to screenshots directories on device. Use if getting 'Permission denied' errors
1213
1214
  - appApkPath: The path to the APK for the app under test
1214
1215
  - testsApkPath: The path to the APK for the the tests bundle
1215
1216
  - specificDevice: Use the device or emulator with the given serial number or qualifier
1216
1217
  - deviceType: Type of device used for screenshots. Matches Google Play Types (phone, sevenInch, tenInch, tv, wear)
1217
1218
  - exitOnTestFailure: Whether or not to exit Screengrab on test failure. Exiting on failure will not copy sceenshots to local machine nor open sceenshots summary
1218
1219
  - reinstallApp: Enabling this option will automatically uninstall the application before running it
1220
+ - useTimestampSuffix: Add timestamp suffix to screenshot filename
1221
+ - adbHost: Configure the host used by adb to connect, allows running on remote devices farm
1222
+ - cleanStatusBar: Enabling this option will clean the status bar
1223
+ - cleanStatusBarConfig: Specifies the configuration for the clean status bar
1219
1224
  */
1220
1225
  func captureAndroidScreenshots(androidHome: String? = nil,
1221
1226
  buildToolsVersion: String? = nil,
@@ -1228,14 +1233,19 @@ func captureAndroidScreenshots(androidHome: String? = nil,
1228
1233
  useTestsInPackages: [String]? = nil,
1229
1234
  useTestsInClasses: [String]? = nil,
1230
1235
  launchArguments: [String]? = nil,
1231
- testInstrumentationRunner: String = "android.support.test.runner.AndroidJUnitRunner",
1236
+ testInstrumentationRunner: String = "androidx.test.runner.AndroidJUnitRunner",
1232
1237
  endingLocale: String = "en-US",
1238
+ useAdbRoot: Bool = false,
1233
1239
  appApkPath: String? = nil,
1234
1240
  testsApkPath: String? = nil,
1235
1241
  specificDevice: String? = nil,
1236
1242
  deviceType: String = "phone",
1237
1243
  exitOnTestFailure: Bool = true,
1238
- reinstallApp: Bool = false) {
1244
+ reinstallApp: Bool = false,
1245
+ useTimestampSuffix: Bool = true,
1246
+ adbHost: String? = nil,
1247
+ cleanStatusBar: Bool = false,
1248
+ cleanStatusBarConfig: [String : Any] = [:]) {
1239
1249
  let command = RubyCommand(commandID: "", methodName: "capture_android_screenshots", className: nil, args: [RubyCommand.Argument(name: "android_home", value: androidHome),
1240
1250
  RubyCommand.Argument(name: "build_tools_version", value: buildToolsVersion),
1241
1251
  RubyCommand.Argument(name: "locales", value: locales),
@@ -1249,12 +1259,17 @@ func captureAndroidScreenshots(androidHome: String? = nil,
1249
1259
  RubyCommand.Argument(name: "launch_arguments", value: launchArguments),
1250
1260
  RubyCommand.Argument(name: "test_instrumentation_runner", value: testInstrumentationRunner),
1251
1261
  RubyCommand.Argument(name: "ending_locale", value: endingLocale),
1262
+ RubyCommand.Argument(name: "use_adb_root", value: useAdbRoot),
1252
1263
  RubyCommand.Argument(name: "app_apk_path", value: appApkPath),
1253
1264
  RubyCommand.Argument(name: "tests_apk_path", value: testsApkPath),
1254
1265
  RubyCommand.Argument(name: "specific_device", value: specificDevice),
1255
1266
  RubyCommand.Argument(name: "device_type", value: deviceType),
1256
1267
  RubyCommand.Argument(name: "exit_on_test_failure", value: exitOnTestFailure),
1257
- RubyCommand.Argument(name: "reinstall_app", value: reinstallApp)])
1268
+ RubyCommand.Argument(name: "reinstall_app", value: reinstallApp),
1269
+ RubyCommand.Argument(name: "use_timestamp_suffix", value: useTimestampSuffix),
1270
+ RubyCommand.Argument(name: "adb_host", value: adbHost),
1271
+ RubyCommand.Argument(name: "clean_status_bar", value: cleanStatusBar),
1272
+ RubyCommand.Argument(name: "clean_status_bar_config", value: cleanStatusBarConfig)])
1258
1273
  _ = runner.executeCommand(command)
1259
1274
  }
1260
1275
 
@@ -5791,12 +5806,17 @@ func scp(username: String,
5791
5806
  - launchArguments: Additional launch arguments
5792
5807
  - testInstrumentationRunner: The fully qualified class name of your test instrumentation runner
5793
5808
  - endingLocale: Return the device to this locale after running tests
5809
+ - useAdbRoot: Restarts the adb daemon using `adb root` to allow access to screenshots directories on device. Use if getting 'Permission denied' errors
5794
5810
  - appApkPath: The path to the APK for the app under test
5795
5811
  - testsApkPath: The path to the APK for the the tests bundle
5796
5812
  - specificDevice: Use the device or emulator with the given serial number or qualifier
5797
5813
  - deviceType: Type of device used for screenshots. Matches Google Play Types (phone, sevenInch, tenInch, tv, wear)
5798
5814
  - exitOnTestFailure: Whether or not to exit Screengrab on test failure. Exiting on failure will not copy sceenshots to local machine nor open sceenshots summary
5799
5815
  - reinstallApp: Enabling this option will automatically uninstall the application before running it
5816
+ - useTimestampSuffix: Add timestamp suffix to screenshot filename
5817
+ - adbHost: Configure the host used by adb to connect, allows running on remote devices farm
5818
+ - cleanStatusBar: Enabling this option will clean the status bar
5819
+ - cleanStatusBarConfig: Specifies the configuration for the clean status bar
5800
5820
  */
5801
5821
  func screengrab(androidHome: Any? = screengrabfile.androidHome,
5802
5822
  buildToolsVersion: Any? = screengrabfile.buildToolsVersion,
@@ -5811,12 +5831,17 @@ func screengrab(androidHome: Any? = screengrabfile.androidHome,
5811
5831
  launchArguments: [String]? = screengrabfile.launchArguments,
5812
5832
  testInstrumentationRunner: Any = screengrabfile.testInstrumentationRunner,
5813
5833
  endingLocale: Any = screengrabfile.endingLocale,
5834
+ useAdbRoot: Bool = screengrabfile.useAdbRoot,
5814
5835
  appApkPath: Any? = screengrabfile.appApkPath,
5815
5836
  testsApkPath: Any? = screengrabfile.testsApkPath,
5816
5837
  specificDevice: Any? = screengrabfile.specificDevice,
5817
5838
  deviceType: Any = screengrabfile.deviceType,
5818
5839
  exitOnTestFailure: Bool = screengrabfile.exitOnTestFailure,
5819
- reinstallApp: Bool = screengrabfile.reinstallApp) {
5840
+ reinstallApp: Bool = screengrabfile.reinstallApp,
5841
+ useTimestampSuffix: Bool = screengrabfile.useTimestampSuffix,
5842
+ adbHost: Any? = screengrabfile.adbHost,
5843
+ cleanStatusBar: Bool = screengrabfile.cleanStatusBar,
5844
+ cleanStatusBarConfig: [String : Any] = screengrabfile.cleanStatusBarConfig) {
5820
5845
  let command = RubyCommand(commandID: "", methodName: "screengrab", className: nil, args: [RubyCommand.Argument(name: "android_home", value: androidHome),
5821
5846
  RubyCommand.Argument(name: "build_tools_version", value: buildToolsVersion),
5822
5847
  RubyCommand.Argument(name: "locales", value: locales),
@@ -5830,12 +5855,17 @@ func screengrab(androidHome: Any? = screengrabfile.androidHome,
5830
5855
  RubyCommand.Argument(name: "launch_arguments", value: launchArguments),
5831
5856
  RubyCommand.Argument(name: "test_instrumentation_runner", value: testInstrumentationRunner),
5832
5857
  RubyCommand.Argument(name: "ending_locale", value: endingLocale),
5858
+ RubyCommand.Argument(name: "use_adb_root", value: useAdbRoot),
5833
5859
  RubyCommand.Argument(name: "app_apk_path", value: appApkPath),
5834
5860
  RubyCommand.Argument(name: "tests_apk_path", value: testsApkPath),
5835
5861
  RubyCommand.Argument(name: "specific_device", value: specificDevice),
5836
5862
  RubyCommand.Argument(name: "device_type", value: deviceType),
5837
5863
  RubyCommand.Argument(name: "exit_on_test_failure", value: exitOnTestFailure),
5838
- RubyCommand.Argument(name: "reinstall_app", value: reinstallApp)])
5864
+ RubyCommand.Argument(name: "reinstall_app", value: reinstallApp),
5865
+ RubyCommand.Argument(name: "use_timestamp_suffix", value: useTimestampSuffix),
5866
+ RubyCommand.Argument(name: "adb_host", value: adbHost),
5867
+ RubyCommand.Argument(name: "clean_status_bar", value: cleanStatusBar),
5868
+ RubyCommand.Argument(name: "clean_status_bar_config", value: cleanStatusBarConfig)])
5839
5869
  _ = runner.executeCommand(command)
5840
5870
  }
5841
5871
 
@@ -8326,4 +8356,4 @@ let snapshotfile: Snapshotfile = Snapshotfile()
8326
8356
 
8327
8357
  // Please don't remove the lines below
8328
8358
  // They are used to detect outdated files
8329
- // FastlaneRunnerAPIVersion [0.9.63]
8359
+ // FastlaneRunnerAPIVersion [0.9.64]
@@ -18,4 +18,4 @@ class Gymfile: GymfileProtocol {
18
18
 
19
19
 
20
20
 
21
- // Generated with fastlane 2.135.2
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.135.2
21
+ // Generated with fastlane 2.136.0
@@ -18,4 +18,4 @@ class Precheckfile: PrecheckfileProtocol {
18
18
 
19
19
 
20
20
 
21
- // Generated with fastlane 2.135.2
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.135.2
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.135.2
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.135.2
21
+ // Generated with fastlane 2.136.0
@@ -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
@@ -19,12 +19,12 @@ module Supply
19
19
  # Updating a track with empty version codes can completely clear out a track
20
20
  update_track(apk_version_codes) unless apk_version_codes.empty?
21
21
 
22
- if !Supply.config[:rollout].nil? && Supply.config[:track].to_s != ""
22
+ if Supply.config[:track_promote_to]
23
+ promote_track
24
+ elsif !Supply.config[:rollout].nil? && Supply.config[:track].to_s != ""
23
25
  update_rollout
24
26
  end
25
27
 
26
- promote_track if Supply.config[:track_promote_to]
27
-
28
28
  if Supply.config[:validate_only]
29
29
  UI.message("Validating all track and release changes with Google Play...")
30
30
  client.validate_current_edit!
@@ -42,7 +42,12 @@ module Supply
42
42
  client.begin_edit(package_name: Supply.config[:package_name])
43
43
 
44
44
  if (!Supply.config[:skip_upload_metadata] || !Supply.config[:skip_upload_images] || !Supply.config[:skip_upload_changelogs] || !Supply.config[:skip_upload_screenshots]) && metadata_path
45
+ # Use version code from config if version codes is empty and no nil or empty string
45
46
  version_codes = [Supply.config[:version_code]] if version_codes.empty?
47
+ version_codes = version_codes.reject do |version_code|
48
+ version_codes.to_s == ""
49
+ end
50
+
46
51
  version_codes.each do |version_code|
47
52
  UI.user_error!("Could not find folder #{metadata_path}") unless File.directory?(metadata_path)
48
53
 
@@ -60,7 +65,7 @@ module Supply
60
65
  upload_metadata(language, listing) unless Supply.config[:skip_upload_metadata]
61
66
  upload_images(language) unless Supply.config[:skip_upload_images]
62
67
  upload_screenshots(language) unless Supply.config[:skip_upload_screenshots]
63
- release_notes << upload_changelog(language, release.name) unless Supply.config[:skip_upload_changelogs]
68
+ release_notes << upload_changelog(language, version_code) unless Supply.config[:skip_upload_changelogs]
64
69
  end
65
70
 
66
71
  upload_changelogs(release_notes, release, track) unless release_notes.empty?
@@ -84,8 +89,9 @@ module Supply
84
89
 
85
90
  track = tracks.first
86
91
  releases = track.releases
92
+
87
93
  releases = releases.select { |r| r.status == status } if status
88
- releases = releases.select { |r| r.version_codes.map(&:to_s).include?(version_code.to_s) }
94
+ releases = releases.select { |r| r.version_codes.map(&:to_s).include?(version_code.to_s) } if version_code
89
95
 
90
96
  if releases.size > 1
91
97
  UI.user_error!("More than one release found in this track. Please specify with the :version_code option to select a release.")
@@ -96,10 +102,12 @@ module Supply
96
102
 
97
103
  def update_rollout
98
104
  track, release = fetch_track_and_release!(Supply.config[:track], Supply.config[:version_code], Supply::ReleaseStatus::IN_PROGRESS)
105
+ UI.user_error!("Unable to find the requested track - '#{Supply.config[:track]}'") unless track
106
+ UI.user_error!("Unable to find the requested release on track - '#{Supply.config[:track]}'") unless release
107
+
99
108
  version_code = release.version_codes.first
100
109
 
101
110
  UI.message("Updating #{version_code}'s rollout to '#{Supply.config[:rollout]}' on track '#{Supply.config[:track]}'...")
102
- UI.user_error!("Unable to find the requested track - '#{Supply.config[:track]}'") unless track
103
111
 
104
112
  if track && release
105
113
  completed = Supply.config[:rollout].to_f == 1
@@ -149,6 +157,10 @@ module Supply
149
157
  releases = releases.select do |release|
150
158
  release.version_codes.include?(Supply.config[:version_code].to_s)
151
159
  end
160
+ else
161
+ releases = releases.select do |release|
162
+ release.status == Supply::ReleaseStatus::COMPLETED
163
+ end
152
164
  end
153
165
 
154
166
  if releases.size == 0
@@ -157,9 +169,17 @@ module Supply
157
169
  UI.user_error!("Track '#{Supply.config[:track]}' has more than one release - use :version_code to filter the release to promote")
158
170
  end
159
171
 
160
- release = track_from.releases.first
172
+ release = releases.first
161
173
  track_to = client.tracks(Supply.config[:track_promote_to]).first
162
174
 
175
+ if Supply.config[:rollout]
176
+ release.status = Supply::ReleaseStatus::IN_PROGRESS
177
+ release.user_fraction = Supply.config[:rollout]
178
+ else
179
+ release.status = Supply::ReleaseStatus::COMPLETED
180
+ release.user_fraction = nil
181
+ end
182
+
163
183
  if track_to
164
184
  # Its okay to set releases to an array containing the newest release
165
185
  # Google Play will keep previous releases there this release is a partial rollout
@@ -174,16 +194,16 @@ module Supply
174
194
  client.update_track(Supply.config[:track_promote_to], track_to)
175
195
  end
176
196
 
177
- def upload_changelog(language, version_name)
178
- UI.user_error!("Cannot find changelog because no version name given - please specify :version_name") unless version_name
197
+ def upload_changelog(language, version_code)
198
+ UI.user_error!("Cannot find changelog because no version code given - please specify :version_code") unless version_code
179
199
 
180
- path = File.join(Supply.config[:metadata_path], language, Supply::CHANGELOGS_FOLDER_NAME, "#{version_name}.txt")
200
+ path = File.join(Supply.config[:metadata_path], language, Supply::CHANGELOGS_FOLDER_NAME, "#{version_code}.txt")
181
201
  changelog_text = ''
182
202
  if File.exist?(path)
183
- UI.message("Updating changelog for '#{version_name}' and language '#{language}'...")
203
+ UI.message("Updating changelog for '#{version_code}' and language '#{language}'...")
184
204
  changelog_text = File.read(path, encoding: 'UTF-8')
185
205
  else
186
- UI.message("Could not find changelog for '#{version_name}' and language '#{language}' at path #{path}...")
206
+ UI.message("Could not find changelog for '#{version_code}' and language '#{language}' at path #{path}...")
187
207
  end
188
208
 
189
209
  AndroidPublisher::LocalizedText.new({
metadata CHANGED
@@ -1,33 +1,33 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.135.2
4
+ version: 2.136.0
5
5
  platform: ruby
6
6
  authors:
7
- - Andrew McBurney
8
- - Jan Piotrowski
9
- - Maksym Grebenets
10
- - Olivier Halligon
11
- - Kohki Miki
12
- - Iulian Onofrei
13
7
  - Danielle Tomlinson
14
- - Manu Wallner
15
- - Luka Mirosevic
8
+ - Jimmy Dee
16
9
  - Helmut Januschka
10
+ - Olivier Halligon
11
+ - Joshua Liebowitz
17
12
  - Josh Holtz
18
- - Felix Krause
19
- - Jérôme Lacoste
13
+ - Manu Wallner
14
+ - Jan Piotrowski
15
+ - Kohki Miki
20
16
  - Stefan Natchev
21
- - Aaron Brager
22
- - Jimmy Dee
17
+ - Jorge Revuelta H
23
18
  - Fumiya Nakamura
19
+ - Jérôme Lacoste
20
+ - Felix Krause
21
+ - Maksym Grebenets
22
+ - Iulian Onofrei
24
23
  - Matthew Ellis
25
- - Jorge Revuelta H
26
- - Joshua Liebowitz
24
+ - Aaron Brager
25
+ - Luka Mirosevic
26
+ - Andrew McBurney
27
27
  autorequire:
28
28
  bindir: bin
29
29
  cert_chain: []
30
- date: 2019-11-11 00:00:00.000000000 Z
30
+ date: 2019-11-15 00:00:00.000000000 Z
31
31
  dependencies:
32
32
  - !ruby/object:Gem::Dependency
33
33
  name: slack-notifier
@@ -1731,7 +1731,6 @@ files:
1731
1731
  - spaceship/lib/spaceship/ui.rb
1732
1732
  - supply/README.md
1733
1733
  - supply/lib/supply.rb
1734
- - supply/lib/supply/.options.rb.swp
1735
1734
  - supply/lib/supply/.uploader.rb.swp
1736
1735
  - supply/lib/supply/apk_listing.rb
1737
1736
  - supply/lib/supply/client.rb