* Add PEP 723 metadata for various `bin` scripts * Use a subprocess to install chromium * Regenerate image * Update shebangs Co-Authored-By: Henry Schreiner <HenrySchreinerIII@gmail.com> * Add cibuildwheel local dependency for some scripts Co-Authored-By: Henry Schreiner <HenrySchreinerIII@gmail.com> * Remove `bin` dependency group fully * Add CSS for styling the diagram Co-Authored-By: Joe Rickerby <1244307+joerick@users.noreply.github.com> * Restore image to original * Install `uv` for PyLint to find it * Drop setup-python too in favour of setup-uv * Revert "Drop setup-python too in favour of setup-uv" This reverts commit 663db5c253f18bd09229ea5dbf92f7f6aa8ebf1c. * Make `uv` venv backend for nox optional again --------- Co-authored-by: Henry Schreiner <HenrySchreinerIII@gmail.com> Co-authored-by: Joe Rickerby <1244307+joerick@users.noreply.github.com>
154 lines
4.4 KiB
Python
Executable File
154 lines
4.4 KiB
Python
Executable File
#!/usr/bin/env -S uv run --script
|
|
|
|
# /// script
|
|
# dependencies = [
|
|
# "packaging",
|
|
# "requests",
|
|
# ]
|
|
# ///
|
|
|
|
import configparser
|
|
import dataclasses
|
|
from pathlib import Path
|
|
|
|
import requests
|
|
from packaging.version import Version
|
|
|
|
DIR = Path(__file__).parent.resolve()
|
|
RESOURCES = DIR.parent / "cibuildwheel/resources"
|
|
|
|
|
|
@dataclasses.dataclass(frozen=True)
|
|
class Image:
|
|
manylinux_version: str
|
|
platforms: list[str]
|
|
image_name: str
|
|
tag: str | None = None # Set this to pin the image
|
|
use_platform_suffix: bool = False
|
|
|
|
|
|
class PyPAImage(Image):
|
|
def __init__(self, manylinux_version: str, platforms: list[str], tag: str | None = None):
|
|
image_name = f"quay.io/pypa/{manylinux_version}"
|
|
super().__init__(manylinux_version, platforms, image_name, tag, True)
|
|
|
|
|
|
images = [
|
|
# manylinux2014 images
|
|
PyPAImage(
|
|
"manylinux2014",
|
|
[
|
|
"x86_64",
|
|
"i686",
|
|
"aarch64",
|
|
"ppc64le",
|
|
"s390x",
|
|
"pypy_x86_64",
|
|
"pypy_i686",
|
|
"pypy_aarch64",
|
|
],
|
|
),
|
|
# manylinux_2_28 images
|
|
PyPAImage(
|
|
"manylinux_2_28",
|
|
[
|
|
"x86_64",
|
|
"i686",
|
|
"aarch64",
|
|
"ppc64le",
|
|
"s390x",
|
|
"pypy_x86_64",
|
|
"pypy_i686",
|
|
"pypy_aarch64",
|
|
],
|
|
),
|
|
# manylinux_2_31 images
|
|
PyPAImage("manylinux_2_31", ["armv7l"]),
|
|
# manylinux_2_34 images
|
|
PyPAImage(
|
|
"manylinux_2_34",
|
|
[
|
|
"x86_64",
|
|
"i686",
|
|
"aarch64",
|
|
"ppc64le",
|
|
"s390x",
|
|
"pypy_x86_64",
|
|
"pypy_i686",
|
|
"pypy_aarch64",
|
|
],
|
|
),
|
|
# manylinux_2_35 images
|
|
PyPAImage("manylinux_2_35", ["armv7l"]),
|
|
# manylinux_2_39 images
|
|
PyPAImage("manylinux_2_39", ["riscv64"]),
|
|
# musllinux_1_2 images
|
|
PyPAImage(
|
|
"musllinux_1_2", ["x86_64", "i686", "aarch64", "ppc64le", "s390x", "armv7l", "riscv64"]
|
|
),
|
|
]
|
|
|
|
config = configparser.ConfigParser()
|
|
|
|
for image in images:
|
|
# get the tag name whose digest matches 'latest'
|
|
if image.tag is not None:
|
|
# image has been pinned, do not update
|
|
tag_name = image.tag
|
|
elif image.image_name.startswith("quay.io/"):
|
|
_, _, repository_name = image.image_name.partition("/")
|
|
response = requests.get(
|
|
f"https://quay.io/api/v1/repository/{repository_name}?includeTags=true"
|
|
)
|
|
response.raise_for_status()
|
|
repo_info = response.json()
|
|
tags_dict = repo_info["tags"]
|
|
|
|
latest_tag = tags_dict.pop("latest")
|
|
# find the tag whose manifest matches 'latest'
|
|
tag_name = next(
|
|
name
|
|
for (name, info) in tags_dict.items()
|
|
if info["manifest_digest"] == latest_tag["manifest_digest"]
|
|
)
|
|
elif image.image_name.startswith("ghcr.io/"):
|
|
repository = image.image_name[8:]
|
|
response = requests.get(
|
|
"https://ghcr.io/token", params={"scope": f"repository:{repository}:pull"}
|
|
)
|
|
response.raise_for_status()
|
|
token = response.json()["token"]
|
|
response = requests.get(
|
|
f"https://ghcr.io/v2/{repository}/tags/list",
|
|
headers={"Authorization": f"Bearer {token}"},
|
|
)
|
|
response.raise_for_status()
|
|
ghcr_tags = [(Version(tag), tag) for tag in response.json()["tags"] if tag != "latest"]
|
|
ghcr_tags.sort(reverse=True)
|
|
tag_name = ghcr_tags[0][1]
|
|
else:
|
|
response = requests.get(f"https://hub.docker.com/v2/repositories/{image.image_name}/tags")
|
|
response.raise_for_status()
|
|
tags = response.json()["results"]
|
|
|
|
latest_tag = next(tag for tag in tags if tag["name"] == "latest")
|
|
# i don't know what it would mean to have multiple images per tag
|
|
assert len(latest_tag["images"]) == 1
|
|
digest = latest_tag["images"][0]["digest"]
|
|
|
|
pinned_tag = next(
|
|
tag for tag in tags if tag != latest_tag and tag["images"][0]["digest"] == digest
|
|
)
|
|
tag_name = pinned_tag["name"]
|
|
|
|
for platform in image.platforms:
|
|
if not config.has_section(platform):
|
|
config[platform] = {}
|
|
suffix = ""
|
|
if image.use_platform_suffix:
|
|
suffix = f"_{platform.removeprefix('pypy_')}"
|
|
config[platform][image.manylinux_version] = f"{image.image_name}{suffix}:{tag_name}"
|
|
|
|
with open(RESOURCES / "pinned_docker_images.cfg", "w") as f:
|
|
config.write(f)
|