Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/scripts/pinned_browsers.py
2864 views
1
#!/usr/bin/env python
2
3
import hashlib
4
import json
5
import os
6
import sys
7
from pathlib import Path
8
9
import urllib3
10
from packaging.version import parse
11
12
# Find the current stable versions of each browser we
13
# support and the sha256 of these. That's useful for
14
# updating `//common:repositories.bzl`
15
16
http = urllib3.PoolManager()
17
18
19
def calculate_hash(url):
20
print("Calculate hash for %s" % url, file=sys.stderr)
21
h = hashlib.sha256()
22
r = http.request("GET", url, preload_content=False)
23
for b in iter(lambda: r.read(4096), b""):
24
h.update(b)
25
return h.hexdigest()
26
27
28
def get_chrome_info_for_channel(channel):
29
r = http.request(
30
"GET",
31
f"https://chromiumdash.appspot.com/fetch_releases?channel={channel}&num=1&platform=Mac,Linux",
32
)
33
all_versions = json.loads(r.data)
34
# use the same milestone for all chrome releases, so pick the lowest
35
milestone = min(
36
[version["milestone"] for version in all_versions if version["milestone"]]
37
)
38
r = http.request(
39
"GET",
40
"https://googlechromelabs.github.io/chrome-for-testing/known-good-versions-with-downloads.json",
41
)
42
versions = json.loads(r.data)["versions"]
43
44
return sorted(
45
filter(lambda v: v["version"].split(".")[0] == str(milestone), versions),
46
key=lambda v: parse(v["version"]),
47
)[-1]
48
49
50
def chromedriver(selected_version, workspace_prefix=""):
51
content = ""
52
53
drivers = selected_version["downloads"]["chromedriver"]
54
55
url = [d["url"] for d in drivers if d["platform"] == "linux64"][0]
56
sha = calculate_hash(url)
57
58
content += f""" http_archive(
59
name = "linux_{workspace_prefix}chromedriver",
60
url = "{url}",
61
sha256 = "{sha}",
62
strip_prefix = "chromedriver-linux64",
63
build_file_content = \"\"\"
64
load("@aspect_rules_js//js:defs.bzl", "js_library")
65
package(default_visibility = ["//visibility:public"])
66
67
exports_files(["chromedriver"])
68
69
js_library(
70
name = "chromedriver-js",
71
data = ["chromedriver"],
72
)
73
\"\"\",
74
)
75
"""
76
77
url = [d["url"] for d in drivers if d["platform"] == "mac-x64"][0]
78
sha = calculate_hash(url)
79
80
content += f"""
81
http_archive(
82
name = "mac_{workspace_prefix}chromedriver",
83
url = "{url}",
84
sha256 = "{sha}",
85
strip_prefix = "chromedriver-mac-x64",
86
build_file_content = \"\"\"
87
load("@aspect_rules_js//js:defs.bzl", "js_library")
88
package(default_visibility = ["//visibility:public"])
89
90
exports_files(["chromedriver"])
91
92
js_library(
93
name = "chromedriver-js",
94
data = ["chromedriver"],
95
)
96
\"\"\",
97
)
98
"""
99
100
return content
101
102
103
def chrome(selected_version, workspace_prefix=""):
104
content = ""
105
chrome_downloads = selected_version["downloads"]["chrome"]
106
107
url = [d["url"] for d in chrome_downloads if d["platform"] == "linux64"][0]
108
sha = calculate_hash(url)
109
110
content += f"""
111
http_archive(
112
name = "linux_{workspace_prefix}chrome",
113
url = "{url}",
114
sha256 = "{sha}",
115
build_file_content = \"\"\"
116
load("@aspect_rules_js//js:defs.bzl", "js_library")
117
package(default_visibility = ["//visibility:public"])
118
119
filegroup(
120
name = "files",
121
srcs = glob(["**/*"]),
122
)
123
124
exports_files(["chrome-linux64/chrome"])
125
126
js_library(
127
name = "chrome-js",
128
data = [":files"],
129
)
130
\"\"\",
131
)
132
"""
133
134
url = [d["url"] for d in chrome_downloads if d["platform"] == "mac-x64"][0]
135
sha = calculate_hash(url) # Calculate SHA for Mac chrome
136
137
content += f""" http_archive(
138
name = "mac_{workspace_prefix}chrome",
139
url = "{url}",
140
sha256 = "{sha}",
141
strip_prefix = "chrome-mac-x64",
142
patch_cmds = [
143
"mv 'Google Chrome for Testing.app' Chrome.app",
144
"mv 'Chrome.app/Contents/MacOS/Google Chrome for Testing' Chrome.app/Contents/MacOS/Chrome",
145
],
146
build_file_content = \"\"\"
147
load("@aspect_rules_js//js:defs.bzl", "js_library")
148
package(default_visibility = ["//visibility:public"])
149
150
exports_files(["Chrome.app"])
151
152
js_library(
153
name = "chrome-js",
154
data = glob(["Chrome.app/**/*"]),
155
)
156
\"\"\",
157
)
158
"""
159
160
return content
161
162
163
def convert_keys_to_lowercase(obj):
164
if isinstance(obj, dict):
165
return {k.lower(): convert_keys_to_lowercase(v) for k, v in obj.items()}
166
elif isinstance(obj, list):
167
return [convert_keys_to_lowercase(i) for i in obj]
168
else:
169
return obj
170
171
172
def case_insensitive_json_loads(json_str):
173
data = json.loads(json_str)
174
return convert_keys_to_lowercase(data)
175
176
177
def edge():
178
content = ""
179
r = http.request("GET", "https://edgeupdates.microsoft.com/api/products")
180
all_data = case_insensitive_json_loads(r.data)
181
182
linux = None
183
linux_hash = None
184
mac = None
185
mac_hash = None
186
187
for data in all_data:
188
if not "Stable" == data.get("product"):
189
continue
190
for release in data["releases"]:
191
if "MacOS" == release.get("platform"):
192
for artifact in release["artifacts"]:
193
if "pkg" == artifact["artifactname"]:
194
mac = artifact["location"]
195
mac_hash = artifact["hash"]
196
mac_version = release["productversion"]
197
elif "Linux" == release.get("platform"):
198
for artifact in release["artifacts"]:
199
if "deb" == artifact["artifactname"]:
200
linux = artifact["location"]
201
linux_hash = artifact["hash"]
202
203
if mac and mac_hash:
204
content += """
205
pkg_archive(
206
name = "mac_edge",
207
url = "%s",
208
sha256 = "%s",
209
move = {
210
"MicrosoftEdge-%s.pkg/Payload/Microsoft Edge.app": "Edge.app",
211
},
212
build_file_content = \"\"\"
213
load("@aspect_rules_js//js:defs.bzl", "js_library")
214
package(default_visibility = ["//visibility:public"])
215
216
exports_files(["Edge.app"])
217
218
js_library(
219
name = "edge-js",
220
data = glob(["Edge.app/**/*"]),
221
)
222
\"\"\",
223
)
224
""" % (
225
mac,
226
mac_hash.lower(),
227
mac_version,
228
)
229
230
if linux and linux_hash:
231
content += """
232
deb_archive(
233
name = "linux_edge",
234
url = "%s",
235
sha256 = "%s",
236
build_file_content = \"\"\"
237
load("@aspect_rules_js//js:defs.bzl", "js_library")
238
package(default_visibility = ["//visibility:public"])
239
240
filegroup(
241
name = "files",
242
srcs = glob(["**/*"]),
243
)
244
245
exports_files(["opt/microsoft/msedge/microsoft-edge"])
246
247
js_library(
248
name = "edge-js",
249
data = [":files"],
250
)
251
\"\"\",
252
)
253
""" % (linux, linux_hash.lower())
254
255
return content
256
257
258
def edgedriver():
259
r_stable = http.request("GET", "https://msedgedriver.microsoft.com/LATEST_STABLE")
260
stable_version = r_stable.data.decode("utf-16").strip()
261
major_version = stable_version.split(".")[0]
262
r = http.request(
263
"GET",
264
f"https://msedgedriver.microsoft.com/LATEST_RELEASE_{major_version}_LINUX",
265
)
266
linux_version = r.data.decode("utf-16").strip()
267
268
content = ""
269
270
linux = (
271
"https://msedgedriver.microsoft.com/%s/edgedriver_linux64.zip" % linux_version
272
)
273
sha = calculate_hash(linux)
274
content = (
275
content
276
+ """
277
http_archive(
278
name = "linux_edgedriver",
279
url = "%s",
280
sha256 = "%s",
281
build_file_content = \"\"\"
282
load("@aspect_rules_js//js:defs.bzl", "js_library")
283
package(default_visibility = ["//visibility:public"])
284
285
exports_files(["msedgedriver"])
286
287
js_library(
288
name = "msedgedriver-js",
289
data = ["msedgedriver"],
290
)
291
\"\"\",
292
)
293
"""
294
% (linux, sha)
295
)
296
297
r = http.request(
298
"GET",
299
f"https://msedgedriver.microsoft.com/LATEST_RELEASE_{major_version}_MACOS",
300
)
301
macos_version = r.data.decode("utf-16").strip()
302
mac = "https://msedgedriver.microsoft.com/%s/edgedriver_mac64.zip" % macos_version
303
sha = calculate_hash(mac)
304
content = (
305
content
306
+ """
307
http_archive(
308
name = "mac_edgedriver",
309
url = "%s",
310
sha256 = "%s",
311
build_file_content = \"\"\"
312
load("@aspect_rules_js//js:defs.bzl", "js_library")
313
package(default_visibility = ["//visibility:public"])
314
315
exports_files(["msedgedriver"])
316
317
js_library(
318
name = "msedgedriver-js",
319
data = ["msedgedriver"],
320
)
321
\"\"\",
322
)
323
"""
324
% (mac, sha)
325
)
326
return content
327
328
329
def geckodriver():
330
content = ""
331
332
r = http.request(
333
"GET", "https://api.github.com/repos/mozilla/geckodriver/releases/latest"
334
)
335
for a in json.loads(r.data)["assets"]:
336
if a["name"].endswith("-linux64.tar.gz"):
337
url = a["browser_download_url"]
338
sha = calculate_hash(url)
339
content = (
340
content
341
+ """ http_archive(
342
name = "linux_geckodriver",
343
url = "%s",
344
sha256 = "%s",
345
build_file_content = \"\"\"
346
load("@aspect_rules_js//js:defs.bzl", "js_library")
347
package(default_visibility = ["//visibility:public"])
348
349
exports_files(["geckodriver"])
350
351
js_library(
352
name = "geckodriver-js",
353
data = ["geckodriver"],
354
)
355
\"\"\",
356
)
357
"""
358
% (url, sha)
359
)
360
361
if a["name"].endswith("-macos.tar.gz"):
362
url = a["browser_download_url"]
363
sha = calculate_hash(url)
364
content = (
365
content
366
+ """
367
http_archive(
368
name = "mac_geckodriver",
369
url = "%s",
370
sha256 = "%s",
371
build_file_content = \"\"\"
372
load("@aspect_rules_js//js:defs.bzl", "js_library")
373
package(default_visibility = ["//visibility:public"])
374
375
exports_files(["geckodriver"])
376
377
js_library(
378
name = "geckodriver-js",
379
data = ["geckodriver"],
380
)
381
\"\"\",
382
)
383
"""
384
% (url, sha)
385
)
386
return content
387
388
389
def firefox():
390
firefox_versions = json.loads(firefox_version_data())
391
392
latest_firefox = firefox_versions["LATEST_FIREFOX_VERSION"]
393
sha_linux = calculate_hash(firefox_linux(latest_firefox))
394
sha_mac = calculate_hash(firefox_mac(latest_firefox))
395
content = print_firefox(latest_firefox, "", sha_linux, sha_mac)
396
397
beta_firefox = firefox_versions["LATEST_FIREFOX_RELEASED_DEVEL_VERSION"]
398
if latest_firefox != beta_firefox:
399
sha_linux = calculate_hash(firefox_linux(beta_firefox))
400
sha_mac = calculate_hash(firefox_mac(beta_firefox))
401
return content + print_firefox(beta_firefox, "beta_", sha_linux, sha_mac)
402
403
404
def firefox_version_data():
405
versions = http.request(
406
"GET", "https://product-details.mozilla.org/1.0/firefox_versions.json"
407
)
408
return versions.data
409
410
411
def firefox_linux(version):
412
if int(version.split(".")[0]) < 135:
413
return (
414
"https://ftp.mozilla.org/pub/firefox/releases/%s/linux-x86_64/en-US/firefox-%s.tar.bz2"
415
% (version, version)
416
)
417
else:
418
return (
419
"https://ftp.mozilla.org/pub/firefox/releases/%s/linux-x86_64/en-US/firefox-%s.tar.xz"
420
% (version, version)
421
)
422
423
424
def firefox_mac(version):
425
return (
426
"https://ftp.mozilla.org/pub/firefox/releases/%s/mac/en-US/Firefox%%20%s.dmg"
427
% (version, version)
428
)
429
430
431
def print_firefox(version, workspace_name, sha_linux, sha_mac):
432
content = ""
433
434
content = (
435
content
436
+ f""" http_archive(
437
name = "linux_{workspace_name}firefox",
438
url = "{firefox_linux(version)}",
439
sha256 = "{sha_linux}",
440
build_file_content = \"\"\"
441
load("@aspect_rules_js//js:defs.bzl", "js_library")
442
package(default_visibility = ["//visibility:public"])
443
444
filegroup(
445
name = "files",
446
srcs = glob(["**/*"]),
447
)
448
449
exports_files(["firefox/firefox"])
450
451
js_library(
452
name = "firefox-js",
453
data = [":files"],
454
)
455
\"\"\",
456
)
457
458
"""
459
)
460
461
content = (
462
content
463
+ f""" dmg_archive(
464
name = "mac_{workspace_name}firefox",
465
url = "{firefox_mac(version)}",
466
sha256 = "{sha_mac}",
467
build_file_content = \"\"\"
468
load("@aspect_rules_js//js:defs.bzl", "js_library")
469
package(default_visibility = ["//visibility:public"])
470
471
exports_files(["Firefox.app"])
472
473
js_library(
474
name = "firefox-js",
475
data = glob(["Firefox.app/**/*"]),
476
)
477
\"\"\",
478
)
479
480
"""
481
)
482
483
return content
484
485
486
if __name__ == "__main__":
487
content = """# This file has been generated using `bazel run scripts:pinned_browsers`
488
489
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
490
load("//common/private:deb_archive.bzl", "deb_archive")
491
load("//common/private:dmg_archive.bzl", "dmg_archive")
492
load("//common/private:drivers.bzl", "local_drivers")
493
load("//common/private:pkg_archive.bzl", "pkg_archive")
494
495
def pin_browsers():
496
local_drivers(name = "local_drivers")
497
498
"""
499
content = content + firefox()
500
content = content + geckodriver()
501
content = content + edge()
502
content = content + edgedriver()
503
504
# Stable Chrome
505
stable_chrome_info = get_chrome_info_for_channel(channel="Stable")
506
content = content + chrome(stable_chrome_info, workspace_prefix="")
507
content = content + chromedriver(stable_chrome_info, workspace_prefix="")
508
509
# Beta Chrome
510
beta_chrome_info = get_chrome_info_for_channel(channel="Beta")
511
content = content + chrome(beta_chrome_info, workspace_prefix="beta_")
512
content = content + chromedriver(beta_chrome_info, workspace_prefix="beta_")
513
514
content += """
515
def _pin_browsers_extension_impl(_ctx):
516
pin_browsers()
517
518
pin_browsers_extension = module_extension(
519
implementation = _pin_browsers_extension_impl,
520
)
521
"""
522
523
current_script_dir = Path(os.path.realpath(__file__)).parent
524
target_file_path = current_script_dir.parent / "common/repositories.bzl"
525
526
with open(target_file_path, "w") as file:
527
file.write(content)
528
529