From: Ɓukasz Langa Date: Mon, 12 Jan 2026 23:01:01 +0000 (+0100) Subject: Bump automatic certificate update on Windows during builds (GH-143741) X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d5882c5b7057b1b0a9dfd7b797a44d27e12d7ad3;p=thirdparty%2FPython%2Fcpython.git Bump automatic certificate update on Windows during builds (GH-143741) Without this, OpenSSL that we use to download external dependencies might use a stale certificate store and be unable to connect to servers. We need to use a Windows-specific HTTP client that uses CryptoAPI directly to trigger certificate updates. We only do it on failure to avoid hitting servers twice. And we only do it once per each URL. --- diff --git a/PCbuild/get_external.py b/PCbuild/get_external.py index 27fbc311bbc1..494b22809e08 100755 --- a/PCbuild/get_external.py +++ b/PCbuild/get_external.py @@ -1,9 +1,11 @@ #!/usr/bin/env python3 import argparse +import functools import os import pathlib import platform +import subprocess import sys import tarfile import time @@ -12,6 +14,27 @@ import urllib.request import zipfile +@functools.cache +def trigger_automatic_root_certificate_update(url: str, timeout: int = 30) -> None: + escaped_url = url.replace("'", "''") + try: + subprocess.run( + [ + "powershell", + "-NoProfile", + "-Command", + f"Invoke-WebRequest -Uri '{escaped_url}'" + f" -UseBasicParsing -Method HEAD -MaximumRedirection 0" + f" -TimeoutSec {timeout}", + ], + check=True, + capture_output=True, + timeout=timeout + 5, + ) + except (subprocess.CalledProcessError, subprocess.TimeoutExpired) as e: + print(e) + + def retrieve_with_retries(download_location, output_path, reporthook, max_retries=7): """Download a file with exponential backoff retry and save to disk.""" @@ -25,6 +48,7 @@ def retrieve_with_retries(download_location, output_path, reporthook, except (urllib.error.URLError, ConnectionError) as ex: if attempt == max_retries: raise OSError(f'Download from {download_location} failed.') from ex + trigger_automatic_root_certificate_update(download_location) time.sleep(2.25**attempt) else: return resp