Skip to content

Commit 35ae5bf

Browse files
committed
iOS and Android browserstack workflow fixes
1 parent aa5e3d0 commit 35ae5bf

File tree

2 files changed

+141
-0
lines changed

2 files changed

+141
-0
lines changed

.github/workflows/ios-browserstack.yml

+5
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,11 @@ jobs:
4040
- name: Make build dir
4141
run: mkdir ddp
4242

43+
- name: Install resource script dependency
44+
run: |
45+
brew update
46+
brew install convmv
47+
4348
- name: Copy test_resources
4449
run: ./copy_test_resources.sh
4550

script/automation/browserstack.py

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import argparse
2+
import requests
3+
import time
4+
5+
APP_URI = 'https://api-cloud.browserstack.com/app-automate/{}/v2/app'
6+
TEST_URI = 'https://api-cloud.browserstack.com/app-automate/{}/v2/test-suite'
7+
BUILD_URI = 'https://api-cloud.browserstack.com/app-automate/{}/v2/build'
8+
STATUS_URI = 'https://api-cloud.browserstack.com/app-automate/{}/v2/builds/{}'
9+
10+
devices_dict = {
11+
'android-min-max': [
12+
'Samsung Galaxy S8-7.0',
13+
'Samsung Galaxy M52-11.0',
14+
'Google Pixel 9-15.0'
15+
],
16+
'android-perf': [
17+
'Google Pixel 6 Pro-15.0'
18+
],
19+
'ios-min-max': [
20+
'iPhone SE 2022-15',
21+
'iPhone 14 Plus-16',
22+
'iPhone 14-18'
23+
],
24+
'ios-perf': [
25+
'iPhone 13-18',
26+
]
27+
}
28+
29+
30+
def main(args: argparse.Namespace) -> None:
31+
app_files = {
32+
'file': open(args.app_path, 'rb')
33+
}
34+
35+
app_response = requests.post(
36+
APP_URI.format(args.type),
37+
files=app_files,
38+
auth=(args.username, args.access_key)
39+
)
40+
app_response_json = app_response.json()
41+
42+
if not app_response.ok:
43+
print('App Upload Failed', app_response_json)
44+
exit(1)
45+
46+
test_files = {
47+
'file': open(args.test_path, 'rb')
48+
}
49+
test_response = requests.post(
50+
TEST_URI.format(args.type),
51+
files=test_files,
52+
auth=(args.username, args.access_key)
53+
)
54+
test_response_json = test_response.json()
55+
56+
if not test_response.ok:
57+
print('Test Upload Failed', test_response_json)
58+
exit(1)
59+
60+
build_headers = {
61+
'Content-Type': 'application/json'
62+
}
63+
build_data = {
64+
'app': app_response_json['app_url'],
65+
'testSuite': test_response_json['test_suite_url'],
66+
'project': args.project_name,
67+
'devices': devices_dict[args.devices],
68+
'deviceLogs': True
69+
}
70+
71+
while True:
72+
build_response = requests.post(
73+
BUILD_URI.format(args.type),
74+
headers=build_headers,
75+
json=build_data,
76+
auth=(args.username, args.access_key)
77+
)
78+
if (build_response is not None and 'message' in build_response.json() and '[BROWSERSTACK_ALL_PARALLELS_IN_USE]'
79+
in build_response.json()['message']):
80+
print('Parallel threads limit reached. Waiting...', flush=True)
81+
time.sleep(60)
82+
else:
83+
break
84+
85+
if build_response is None:
86+
print('Build Failed')
87+
exit(1)
88+
89+
build_response_json = build_response.json()
90+
91+
if not build_response.ok:
92+
print('Build Failed', build_response.json())
93+
exit(1)
94+
95+
if build_response_json['message'] != 'Success':
96+
print('Build Unsuccessful')
97+
exit(1)
98+
99+
print(
100+
'View build results at https://app-automate.browserstack.com/dashboard/v2/builds/{}'
101+
.format(build_response_json['build_id']))
102+
103+
while True:
104+
time.sleep(60)
105+
status_response = requests.get(
106+
STATUS_URI.format(args.type, build_response_json['build_id']),
107+
auth=(args.username, args.access_key)
108+
)
109+
status_response_json = status_response.json()
110+
status = status_response_json['status']
111+
112+
if not status_response.ok:
113+
print('Status Request Failed', status_response_json)
114+
exit(1)
115+
116+
if status != 'queued' and status != 'running':
117+
break
118+
119+
print('Status:', status)
120+
if status != 'passed':
121+
exit(1)
122+
123+
124+
if __name__ == '__main__':
125+
parser = argparse.ArgumentParser()
126+
parser.add_argument('--type', choices=['espresso', 'xcuitest'], required=True)
127+
parser.add_argument('--username', required=True)
128+
parser.add_argument('--access_key', required=True)
129+
130+
parser.add_argument('--project_name', required=True)
131+
parser.add_argument('--devices', choices=devices_dict.keys(), required=True)
132+
parser.add_argument('--app_path', required=True)
133+
parser.add_argument('--test_path', required=True)
134+
args = parser.parse_args()
135+
136+
main(args)

0 commit comments

Comments
 (0)