Skip to content

Commit f0f4878

Browse files
committed
Python: Update bazel to be able to build both 0.27.1 and 0.26.0a2
1 parent dfe45a8 commit f0f4878

File tree

7 files changed

+150
-54
lines changed

7 files changed

+150
-54
lines changed

.github/workflows/release-python-runtime.yml

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
11
name: Build Python Runtime
22

3-
on:
4-
workflow_dispatch:
5-
inputs:
6-
pyodide:
7-
description: The Pyodide version
8-
pyodideRevision:
9-
description: The Pyodide revision date
10-
backport:
11-
description: The Pyodide release backport number
3+
on: workflow_dispatch
124

135
jobs:
146
build:
@@ -36,17 +28,14 @@ jobs:
3628
# Strip comment in front of WORKERS_MIRROR_URL, then substitute secret to use it.
3729
sed -e '/WORKERS_MIRROR_URL/ { s@# *@@; s@WORKERS_MIRROR_URL@${{ secrets.WORKERS_MIRROR_URL }}@; }' -i.bak WORKSPACE
3830
fi
39-
- name: Bazel build
40-
run: |
41-
bazel build //src/pyodide:pyodide.capnp.bin@rule --disk_cache=~/bazel-disk-cache --strip=always --remote_cache=https://bazel:${{ secrets.BAZEL_CACHE_KEY }}@bazel-remote-cache.devprod.cloudflare.dev --config=ci --config=release_linux
42-
cp bazel-bin/src/pyodide/${{ inputs.pyodide }}/generated/pyodide.capnp.bin .
43-
- name: Upload Pyodide capnproto bundle
31+
- name: Build and upload Pyodide capnproto bundle
4432
env:
4533
R2_ACCOUNT_ID: ${{ secrets.PYODIDE_CAPNP_R2_ACCOUNT_ID }}
4634
R2_ACCESS_KEY_ID: ${{ secrets.PYODIDE_CAPNP_R2_ACCESS_KEY_ID }}
4735
R2_SECRET_ACCESS_KEY: ${{ secrets.PYODIDE_CAPNP_R2_SECRET_ACCESS_KEY }}
4836
run: |
37+
bazel build @workerd//src/pyodide:python_bundles @workerd//src/pyodide:bundle_version_info --remote_cache=https://bazel:${{ secrets.BAZEL_CACHE_KEY }}@bazel-remote-cache.devprod.cloudflare.dev
4938
# boto3 v1.36.0 fails with:
5039
# NotImplemented error occurred in CreateMultipartUpload operation: Header 'x-amz-checksum-algorithm' with value 'CRC32' not implemented
5140
pip install 'boto3<1.36.0'
52-
python3 src/pyodide/upload_bundle.py pyodide.capnp.bin pyodide_${{ inputs.pyodide }}_${{ inputs.pyodideRevision }}_${{ inputs.backport }}.capnp.bin
41+
python3 src/pyodide/upload_bundles.py

build/deps/dep_pyodide.bzl

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive", "http_file")
22
load("//:build/pyodide_bucket.bzl", "PYODIDE_ALL_WHEELS_ZIP_SHA256", "PYODIDE_GITHUB_RELEASE_URL")
3-
load("//:build/python_metadata.bzl", "PYTHON_LOCKFILES")
3+
load("//:build/python_metadata.bzl", "PYODIDE_VERSIONS", "PYTHON_LOCKFILES")
44

55
def dep_pyodide():
66
# Use @workerd prefix on build_file so we can use this from edgeworker too
7-
http_archive(
8-
name = "pyodide",
9-
build_file = "@workerd//:build/BUILD.pyodide",
10-
sha256 = "fbda450a64093a8d246c872bb901ee172a57fe594c9f35bba61f36807c73300d",
11-
urls = ["https://github.com/pyodide/pyodide/releases/download/0.26.0a2/pyodide-core-0.26.0a2.tar.bz2"],
12-
)
7+
for info in PYODIDE_VERSIONS:
8+
version = info["version"]
9+
sha256 = info["sha256"]
10+
http_archive(
11+
name = "pyodide-%s" % version,
12+
build_file = "@workerd//:build/BUILD.pyodide",
13+
sha256 = sha256,
14+
urls = ["https://github.com/pyodide/pyodide/releases/download/%s/pyodide-core-%s.tar.bz2" % (version, version)],
15+
)
1316

1417
for package_date, package_lock_sha in PYTHON_LOCKFILES.items():
1518
http_file(

build/python_metadata.bzl

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,17 @@
11
load("//:build/python/packages_20240829_4.bzl", "PACKAGES_20240829_4")
22
load("//:build/python/packages_20250324_1.bzl", "PACKAGES_20250324_1")
33

4+
PYODIDE_VERSIONS = [
5+
{
6+
"version": "0.26.0a2",
7+
"sha256": "fbda450a64093a8d246c872bb901ee172a57fe594c9f35bba61f36807c73300d",
8+
},
9+
{
10+
"version": "0.27.1",
11+
"sha256": "6e45f93c71ed21bff4a06d6d9d8e27e815269dabf8ab34dc400939fd45edc665",
12+
},
13+
]
14+
415
# This is the list of all the package metadata that we use.
516
#
617
# IMPORTANT: packages that are present here should never be removed after the package version is
@@ -36,12 +47,15 @@ def verify_no_packages_were_removed():
3647

3748
verify_no_packages_were_removed()
3849

50+
def _bundle_id(*, pyodide_version, pyodide_date, backport, **_kwds):
51+
return "%s_%s_%s" % (pyodide_version, pyodide_date, backport)
52+
3953
def make_bundle_version_info(versions):
4054
result = {}
4155
for entry in versions:
4256
name = entry["name"]
4357
if entry["name"] != "development":
44-
entry["id"] = entry["pyodide_version"] + "_" + entry["pyodide_date"] + "_" + entry["backport"]
58+
entry["id"] = _bundle_id(**entry)
4559
result[name] = entry
4660
return result
4761

@@ -53,7 +67,7 @@ BUNDLE_VERSION_INFO = make_bundle_version_info([
5367
"pyodide_version": "0.26.0a2",
5468
"pyodide_date": "2024-03-01",
5569
"packages": "20240829.4",
56-
"backport": "28",
70+
"backport": 28,
5771
"integrity": "sha256-a2F/YpfjuGsVIsx5Z/WSbAaWSHL9vO13puPxX+wKwNI=",
5872
"feature_flags": [],
5973
"emscripten_version": "3.1.52",
@@ -65,7 +79,7 @@ BUNDLE_VERSION_INFO = make_bundle_version_info([
6579
"pyodide_version": "0.27.1",
6680
"pyodide_date": "2025-01-16",
6781
"packages": "20250324.1",
68-
"backport": "16",
82+
"backport": 16,
6983
"integrity": "sha256-znvAe5OAidJcQyeWeMFClJ5LPgP0QPztxZW/sogb1wI=",
7084
"feature_flags": ["pythonWorkers20250116"],
7185
"emscripten_version": "3.1.58",

src/pyodide/BUILD.bazel

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
2+
load("@bazel_skylib//rules:write_file.bzl", "write_file")
23
load("@capnp-cpp//src/capnp:cc_capnp_library.bzl", "cc_capnp_library")
34
load("//:build/capnp_embed.bzl", "capnp_embed")
4-
load("//:build/python_metadata.bzl", "PYTHON_LOCKFILES")
5-
load(":helpers.bzl", "copy_and_capnp_embed", "copy_to_generated", "python_bundle")
5+
load("//:build/python_metadata.bzl", "BUNDLE_VERSION_INFO", "PYTHON_LOCKFILES")
6+
load(":helpers.bzl", "copy_and_capnp_embed", "copy_to_generated", "python_bundles")
67

78
copy_and_capnp_embed("python-entrypoint.js")
89

@@ -47,7 +48,7 @@ cc_capnp_library(
4748
],
4849
)
4950

50-
python_bundle("0.26.0a2")
51+
python_bundles()
5152

5253
alias(
5354
name = "pyodide.capnp.bin",
@@ -66,3 +67,9 @@ alias(
6667
actual = "pyodide@0.26.0a2",
6768
visibility = ["//visibility:public"],
6869
)
70+
71+
write_file(
72+
name = "bundle_version_info",
73+
out = "bundle_version_info.json",
74+
content = [json.encode(BUNDLE_VERSION_INFO)],
75+
)

src/pyodide/helpers.bzl

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ load("@bazel_skylib//rules:expand_template.bzl", "expand_template")
44
load("@bazel_skylib//rules:write_file.bzl", "write_file")
55
load("//:build/capnp_embed.bzl", "capnp_embed")
66
load("//:build/js_file.bzl", "js_file")
7+
load("//:build/python_metadata.bzl", "PYODIDE_VERSIONS", "PYTHON_LOCKFILES")
78
load("//:build/wd_ts_bundle.bzl", "wd_ts_bundle")
89

910
def _out_name(src):
@@ -43,15 +44,28 @@ def copy_and_capnp_embed(src, version = None, out_name = None):
4344
deps = [out_name + "@copy"],
4445
)
4546

46-
def python_bundle(version, pyodide_asm_wasm = None, pyodide_asm_js = None, python_stdlib_zip = None, emscripten_setup_override = None):
47+
def python_bundles(overrides = {}):
48+
srcs = [_python_bundle_helper(info, overrides) for info in PYODIDE_VERSIONS]
49+
native.filegroup(
50+
name = "python_bundles",
51+
srcs = srcs + [":bundle_version_info"],
52+
)
53+
54+
def _python_bundle_helper(info, overrides):
55+
version = info["version"]
56+
override = overrides.get(version, {})
57+
return _python_bundle(version, **override)
58+
59+
def _python_bundle(version, *, pyodide_asm_wasm = None, pyodide_asm_js = None, python_stdlib_zip = None, emscripten_setup_override = None):
60+
pyodide_package = "@pyodide-%s//" % version
4761
if not pyodide_asm_wasm:
48-
pyodide_asm_wasm = "@pyodide//:pyodide/pyodide.asm.wasm"
62+
pyodide_asm_wasm = pyodide_package + ":pyodide/pyodide.asm.wasm"
4963

5064
if not pyodide_asm_js:
51-
pyodide_asm_js = "@pyodide//:pyodide/pyodide.asm.js"
65+
pyodide_asm_js = pyodide_package + ":pyodide/pyodide.asm.js"
5266

5367
if not python_stdlib_zip:
54-
python_stdlib_zip = "@pyodide//:pyodide/python_stdlib.zip"
68+
python_stdlib_zip = pyodide_package + ":pyodide/python_stdlib.zip"
5569

5670
copy_and_capnp_embed("python-entrypoint.js", version = version)
5771

@@ -243,8 +257,9 @@ def python_bundle(version, pyodide_asm_wasm = None, pyodide_asm_js = None, pytho
243257
out_dir = _out_path("", version),
244258
)
245259

260+
pyodide_cappn_bin_rule = "pyodide.capnp.bin@rule@" + version
246261
native.genrule(
247-
name = "pyodide.capnp.bin@rule@" + version,
262+
name = pyodide_cappn_bin_rule,
248263
srcs = [
249264
":pyodide@%s.capnp" % version,
250265
"//src/workerd/jsg:modules.capnp",
@@ -287,3 +302,4 @@ def python_bundle(version, pyodide_asm_wasm = None, pyodide_asm_js = None, pytho
287302
tools = ["@capnp-cpp//src/capnp:capnp_tool"],
288303
visibility = ["//visibility:public"],
289304
)
305+
return pyodide_cappn_bin_rule

src/pyodide/upload_bundle.py

Lines changed: 0 additions & 21 deletions
This file was deleted.

src/pyodide/upload_bundles.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import json
2+
import subprocess
3+
import sys
4+
from copy import deepcopy
5+
from functools import cache
6+
from os import environ
7+
from pathlib import Path
8+
9+
import requests
10+
from boto3 import client
11+
12+
13+
def cquery(rule):
14+
res = subprocess.run(
15+
[
16+
"bazel",
17+
"cquery",
18+
rule,
19+
"--output=files",
20+
],
21+
capture_output=True,
22+
text=True,
23+
check=False,
24+
)
25+
if res.returncode:
26+
print(res.stdout)
27+
print(res.stderr)
28+
sys.exit(res.returncode)
29+
return res.stdout.strip()
30+
31+
32+
@cache
33+
def _bundle_version_info():
34+
with Path(cquery("@workerd//src/pyodide:bundle_version_info")).open() as f:
35+
return json.load(f)
36+
37+
38+
def bundle_version_info():
39+
return deepcopy(_bundle_version_info())
40+
41+
42+
def get_pyodide_bin_path(ver):
43+
return cquery(f"@workerd//src/pyodide:pyodide@{ver}.capnp")
44+
45+
46+
def bundle_key(*, pyodide_version, pyodide_date, backport, **_kwds):
47+
return f"pyodide_{pyodide_version}_{pyodide_date}_{backport}.capnp.bin"
48+
49+
50+
def bundle_url(**kwds):
51+
return "https://pyodide-capnp-bin.edgeworker.net/" + bundle_key(**kwds)
52+
53+
54+
def get_backport(ver):
55+
info = bundle_version_info()[ver]
56+
backport = int(info["backport"])
57+
for b in range(backport + 1, backport + 10):
58+
info["backport"] = b
59+
url = bundle_url(**info)
60+
res = requests.head(url)
61+
if res.status_code == 404:
62+
return b
63+
res.raise_for_status()
64+
65+
66+
def main():
67+
s3 = client(
68+
"s3",
69+
endpoint_url=f"https://{environ['R2_ACCOUNT_ID']}.r2.cloudflarestorage.com",
70+
aws_access_key_id=environ["R2_ACCESS_KEY_ID"],
71+
aws_secret_access_key=environ["R2_SECRET_ACCESS_KEY"],
72+
region_name="auto",
73+
)
74+
75+
for ver, info in bundle_version_info().items():
76+
if ver.startswith("dev"):
77+
continue
78+
path = Path(get_pyodide_bin_path(ver)).resolve()
79+
b = get_backport(ver)
80+
info["backport"] = b
81+
key = bundle_key(**info)
82+
print(f"Uploading version {ver} backport {b}")
83+
s3.upload_file(str(path), "pyodide-capnp-bin", key)
84+
return 0
85+
86+
87+
if __name__ == "__main__":
88+
sys.exit(main())

0 commit comments

Comments
 (0)