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 +4 -4
- data/README.md +76 -76
- data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +38 -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 +36 -6
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/Matchfile.swift +1 -1
- 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 +22 -2
- data/fastlane/swift/Snapshotfile.swift +1 -1
- data/screengrab/lib/screengrab/module.rb +2 -0
- data/screengrab/lib/screengrab/options.rb +33 -11
- data/screengrab/lib/screengrab/runner.rb +64 -24
- data/supply/lib/supply/.uploader.rb.swp +0 -0
- data/supply/lib/supply/uploader.rb +32 -12
- metadata +16 -17
- data/supply/lib/supply/.options.rb.swp +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8c1652cb1f5fa0d2fbd567e4d4721fc85be17dae9506afcf4fe8c9bd80c3ec6
|
4
|
+
data.tar.gz: d257b400a19b96ccb7a0803af98f71cc6af521b8745a27e4a5083e547a7387bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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='
|
38
|
-
<a href='https://github.com/
|
39
|
-
<img src='https://github.com/
|
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/
|
41
|
+
<h4 align='center'><a href='https://twitter.com/KrauseFx'>Felix Krause</a></h4>
|
42
42
|
</td>
|
43
|
-
<td id='
|
44
|
-
<a href='https://github.com/
|
45
|
-
<img src='https://github.com/
|
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/
|
47
|
+
<h4 align='center'><a href='https://twitter.com/mellis1995'>Matthew Ellis</a></h4>
|
48
48
|
</td>
|
49
|
-
<td id='
|
50
|
-
<a href='https://github.com/
|
51
|
-
<img src='https://github.com/
|
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/
|
53
|
+
<h4 align='center'><a href='https://twitter.com/lmirosevic'>Luka Mirosevic</a></h4>
|
54
54
|
</td>
|
55
|
-
<td id='
|
56
|
-
<a href='https://github.com/
|
57
|
-
<img src='https://github.com/
|
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/
|
59
|
+
<h4 align='center'><a href='https://twitter.com/getaaron'>Aaron Brager</a></h4>
|
60
60
|
</td>
|
61
|
-
<td id='
|
62
|
-
<a href='https://github.com/
|
63
|
-
<img src='https://github.com/
|
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/
|
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='
|
70
|
-
<a href='https://github.com/
|
71
|
-
<img src='https://github.com/
|
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/
|
73
|
+
<h4 align='center'><a href='https://twitter.com/acrooow'>Manu Wallner</a></h4>
|
74
74
|
</td>
|
75
|
-
<td id='
|
76
|
-
<a href='https://github.com/
|
77
|
-
<img src='https://github.com/
|
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/
|
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='
|
88
|
-
<a href='https://github.com/
|
89
|
-
<img src='https://github.com/
|
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/
|
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='
|
108
|
-
<a href='https://github.com/
|
109
|
-
<img src='https://github.com/
|
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/
|
117
|
+
<h4 align='center'><a href='https://twitter.com/aligatr'>Olivier Halligon</a></h4>
|
118
118
|
</td>
|
119
|
-
<td id='
|
120
|
-
<a href='https://github.com/
|
121
|
-
<img src='https://github.com/
|
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/
|
123
|
+
<h4 align='center'><a href='https://twitter.com/minuscorp'>Jorge Revuelta H</a></h4>
|
124
124
|
</td>
|
125
|
-
<td id='
|
126
|
-
<a href='https://github.com/
|
127
|
-
<img src='https://github.com/
|
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/
|
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='
|
134
|
-
<a href='https://github.com/
|
135
|
-
<img src='https://github.com/
|
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/
|
137
|
+
<h4 align='center'><a href='https://twitter.com/endocrimes'>Danielle Tomlinson</a></h4>
|
138
138
|
</td>
|
139
|
-
<td id='
|
140
|
-
<a href='https://github.com/
|
141
|
-
<img src='https://github.com/
|
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/
|
143
|
+
<h4 align='center'><a href='https://twitter.com/lacostej'>Jérôme Lacoste</a></h4>
|
144
144
|
</td>
|
145
|
-
<td id='
|
146
|
-
<a href='https://github.com/
|
147
|
-
<img src='https://github.com/
|
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'>
|
149
|
+
<h4 align='center'><a href='https://twitter.com/taquitos'>Joshua Liebowitz</a></h4>
|
150
150
|
</td>
|
151
|
-
<td id='
|
152
|
-
<a href='https://github.com/
|
153
|
-
<img src='https://github.com/
|
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/
|
155
|
+
<h4 align='center'><a href='https://twitter.com/Sujan'>Jan Piotrowski</a></h4>
|
156
156
|
</td>
|
157
|
-
<td id='
|
158
|
-
<a href='https://github.com/
|
159
|
-
<img src='https://github.com/
|
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'
|
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
|
-
|
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
|
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
|
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
|
-
|
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
|
|
@@ -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
|
|
@@ -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 = "
|
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.
|
8359
|
+
// FastlaneRunnerAPIVersion [0.9.64]
|
@@ -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 "
|
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.
|
105
|
+
// FastlaneRunnerAPIVersion [0.9.12]
|
@@ -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,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
|
-
|
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),
|
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
|
-
|
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("
|
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("
|
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
|
150
|
-
|
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("
|
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("
|
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("
|
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("
|
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("
|
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("
|
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
|
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("
|
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("
|
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 = ["
|
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("
|
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("
|
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("
|
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
|
-
|
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
|
Binary file
|
@@ -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
|
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,
|
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 =
|
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,
|
178
|
-
UI.user_error!("Cannot find changelog because no version
|
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, "#{
|
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 '#{
|
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 '#{
|
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.
|
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
|
-
-
|
15
|
-
- Luka Mirosevic
|
8
|
+
- Jimmy Dee
|
16
9
|
- Helmut Januschka
|
10
|
+
- Olivier Halligon
|
11
|
+
- Joshua Liebowitz
|
17
12
|
- Josh Holtz
|
18
|
-
-
|
19
|
-
-
|
13
|
+
- Manu Wallner
|
14
|
+
- Jan Piotrowski
|
15
|
+
- Kohki Miki
|
20
16
|
- Stefan Natchev
|
21
|
-
-
|
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
|
-
-
|
26
|
-
-
|
24
|
+
- Aaron Brager
|
25
|
+
- Luka Mirosevic
|
26
|
+
- Andrew McBurney
|
27
27
|
autorequire:
|
28
28
|
bindir: bin
|
29
29
|
cert_chain: []
|
30
|
-
date: 2019-11-
|
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
|
Binary file
|