aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/Tools/build/generate_sbom.py
diff options
context:
space:
mode:
Diffstat (limited to 'Tools/build/generate_sbom.py')
-rw-r--r--Tools/build/generate_sbom.py22
1 files changed, 21 insertions, 1 deletions
diff --git a/Tools/build/generate_sbom.py b/Tools/build/generate_sbom.py
index db01426e972..ecb7b54f6d8 100644
--- a/Tools/build/generate_sbom.py
+++ b/Tools/build/generate_sbom.py
@@ -4,10 +4,13 @@ import glob
import hashlib
import json
import os
+import random
import re
import subprocess
import sys
+import time
import typing
+import urllib.error
import urllib.request
from pathlib import Path, PurePosixPath, PureWindowsPath
@@ -161,6 +164,23 @@ def get_externals() -> list[str]:
return externals
+def download_with_retries(download_location: str,
+ max_retries: int = 7,
+ base_delay: float = 2.25,
+ max_jitter: float = 1.0) -> typing.Any:
+ """Download a file with exponential backoff retry."""
+ for attempt in range(max_retries):
+ try:
+ resp = urllib.request.urlopen(download_location)
+ except urllib.error.URLError as ex:
+ if attempt == max_retries:
+ msg = f"Download from {download_location} failed."
+ raise OSError(msg) from ex
+ time.sleep(base_delay**attempt + random.uniform(0, max_jitter))
+ else:
+ return resp
+
+
def check_sbom_packages(sbom_data: dict[str, typing.Any]) -> None:
"""Make a bunch of assertions about the SBOM package data to ensure it's consistent."""
@@ -175,7 +195,7 @@ def check_sbom_packages(sbom_data: dict[str, typing.Any]) -> None:
# and that the download URL is valid.
if "checksums" not in package or "CI" in os.environ:
download_location = package["downloadLocation"]
- resp = urllib.request.urlopen(download_location)
+ resp = download_with_retries(download_location)
error_if(resp.status != 200, f"Couldn't access URL: {download_location}'")
package["checksums"] = [{