Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,16 @@ RUN apt update && apt install -y \
patch \
pkg-config \
python3.12 \
python3-aiohttp \
python3-pip \
libpython3-dev \
texinfo \
wget \
xz-utils

# We require aiohttp >= 3.12 (For client middleware support), which is newer than the currently
# available python3-aiohttp's version in Ubuntu.
RUN python3.12 -m pip install --break-system-packages aiohttp

COPY src/docker_utils/download_musl_toolchains.py .
RUN python3.12 -u download_musl_toolchains.py

Expand Down
30 changes: 28 additions & 2 deletions src/docker_utils/download_musl_toolchains.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3.12

from typing import List
from pathlib import Path
from typing import List

import tarfile
import tempfile
Expand All @@ -10,6 +10,7 @@
import asyncio

import aiohttp
import aiohttp.client_exceptions

# NOTE: To add new architectures, you can use prebuilt toolchains from https://musl.cc/ or https://more.musl.cc/ .
# musl.cc / more.musl.cc are not used here since these websites blacklist Github Actions CI.
Expand All @@ -26,9 +27,34 @@
MUSL_TOOLCHAINS_DIR = Path("/musl-toolchains")
ENTRYPOINT = Path("/entrypoint.sh")

NUM_RETRIES = 3
RETRY_WAIT = 2

async def retry_middleware(req: aiohttp.ClientRequest, handler: aiohttp.ClientHandlerType, max_retries = NUM_RETRIES) -> aiohttp.ClientResponse:
# If every retry ends in a timeoout, resp will not be defined. In such a case we want to raie
# last timeout that has happened as we don't have a valid or invalid response to return.
last_exception = None
resp = None

for _ in range(max_retries):
try:
resp = await handler(req)
if resp.ok:
return resp
except aiohttp.client_exceptions.ConnectionTimeoutError as e:
last_exception = e

await asyncio.sleep(RETRY_WAIT)

if resp is None:
raise last_exception

return resp

async def download_file(url: str, filename: str):
async with aiohttp.ClientSession() as session:
async with aiohttp.ClientSession(middlewares=(retry_middleware,)) as session:
async with session.get(url) as response:
response.raise_for_status()
with open(filename, 'wb') as f:
async for data in response.content.iter_chunked(CHUNK_SIZE):
f.write(data)
Expand Down