Skip to content

Commit 55f91f8

Browse files
committed
Upload Windows SBOM sidecars
1 parent 6e6f19d commit 55f91f8

2 files changed

Lines changed: 82 additions & 2 deletions

File tree

tests/test_windows_merge_upload.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import importlib.util
2+
import json
3+
from pathlib import Path
4+
from typing import Any
5+
6+
import pytest
7+
8+
9+
def load_merge_upload_module(monkeypatch: pytest.MonkeyPatch, tmp_path: Path) -> Any:
10+
for name in (
11+
"INDEX_FILE",
12+
"LOCAL_INDEX",
13+
"MAKECAT",
14+
"MANIFEST_FILE",
15+
"NO_UPLOAD",
16+
"PLINK",
17+
"PSCP",
18+
"SIGN_COMMAND",
19+
"UPLOAD_HOST",
20+
"UPLOAD_HOST_KEY",
21+
"UPLOAD_KEYFILE",
22+
"UPLOAD_PATH_PREFIX",
23+
"UPLOAD_URL_PREFIX",
24+
"UPLOAD_USER",
25+
):
26+
monkeypatch.delenv(name, raising=False)
27+
28+
monkeypatch.chdir(tmp_path)
29+
script = Path(__file__).parents[1] / "windows-release" / "merge-and-upload.py"
30+
spec = importlib.util.spec_from_file_location("merge_and_upload_for_test", script)
31+
assert spec is not None
32+
assert spec.loader is not None
33+
module = importlib.util.module_from_spec(spec)
34+
35+
with pytest.raises(SystemExit) as exc_info:
36+
spec.loader.exec_module(module)
37+
38+
assert exc_info.value.code == 1
39+
return module
40+
41+
42+
def test_calculate_uploads_uses_full_artifact_sbom_name(
43+
monkeypatch: pytest.MonkeyPatch, tmp_path: Path
44+
) -> None:
45+
module = load_merge_upload_module(monkeypatch, tmp_path)
46+
artifact = tmp_path / "python-3.14.0-amd64.exe"
47+
sbom = tmp_path / "python-3.14.0-amd64.exe.spdx.json"
48+
artifact.write_bytes(b"installer")
49+
sbom.write_text("{}", encoding="utf-8")
50+
(tmp_path / "__install__.amd64.json").write_text(
51+
json.dumps(
52+
{
53+
"url": (
54+
"https://www.python.org/ftp/python/3.14.0/python-3.14.0-amd64.exe"
55+
)
56+
}
57+
),
58+
encoding="utf-8",
59+
)
60+
61+
uploads = list(module.calculate_uploads())
62+
63+
assert len(uploads) == 1
64+
_, _, _, upload_sbom, sbom_dest = uploads[0]
65+
assert upload_sbom == sbom
66+
assert (
67+
sbom_dest
68+
== "/srv/www.python.org/ftp/python/3.14.0/python-3.14.0-amd64.exe.spdx.json"
69+
)

windows-release/merge-and-upload.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,17 @@ def validate_new_installs(installs):
150150
print("WARNING: Duplicate id fields:", *sorted(set(ids)))
151151

152152

153+
def sbom_path_for(src):
154+
return src.parent / f"{src.name}.spdx.json"
155+
156+
157+
def sibling_upload_path(dest, filename):
158+
destdir, separator, _ = dest.rpartition("/")
159+
if not separator:
160+
return filename
161+
return f"{destdir}/{filename}"
162+
163+
153164
def purge(url):
154165
if not UPLOAD_HOST or NO_UPLOAD:
155166
print("Skipping purge of", url, "because UPLOAD_HOST is missing")
@@ -176,8 +187,8 @@ def calculate_uploads():
176187
dest = url2path(i["url"])
177188
if LOCAL_INDEX:
178189
i["url"] = str(src.relative_to(Path.cwd())).replace("\\", "/")
179-
sbom = src.with_suffix(".spdx.json")
180-
sbom_dest = dest.rpartition("/")[0] + sbom.name
190+
sbom = sbom_path_for(src)
191+
sbom_dest = sibling_upload_path(dest, sbom.name)
181192
if not sbom.is_file():
182193
sbom = None
183194
sbom_dest = None

0 commit comments

Comments
 (0)