Skip to content

Commit 2d2cd94

Browse files
hugovkpablogsal
andauthored
Only wait for Linux files for security releases (#303)
Co-authored-by: Pablo Galindo <[email protected]>
1 parent d8077ea commit 2d2cd94

File tree

3 files changed

+73
-9
lines changed

3 files changed

+73
-9
lines changed

release.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import datetime
1212
import glob
1313
import hashlib
14+
import json
1415
import optparse
1516
import os
1617
import re
@@ -31,6 +32,7 @@
3132
Self,
3233
overload,
3334
)
35+
from urllib.request import urlopen
3436

3537
COMMASPACE = ", "
3638
SPACE = " "
@@ -68,6 +70,11 @@ def get(
6870
@overload
6971
def get(self, key: Literal["sign_gpg"], default: bool | None = None) -> bool: ...
7072

73+
@overload
74+
def get(
75+
self, key: Literal["security_release"], default: bool | None = None
76+
) -> bool: ...
77+
7178
@overload
7279
def get(self, key: Literal["release"], default: Tag | None = None) -> Tag: ...
7380

@@ -95,6 +102,9 @@ def __getitem__(self, key: Literal["ssh_key"]) -> str | None: ...
95102
@overload
96103
def __getitem__(self, key: Literal["sign_gpg"]) -> bool: ...
97104

105+
@overload
106+
def __getitem__(self, key: Literal["security_release"]) -> bool: ...
107+
98108
@overload
99109
def __getitem__(self, key: Literal["release"]) -> Tag: ...
100110

@@ -124,6 +134,9 @@ def __setitem__(self, key: Literal["ssh_key"], value: str | None) -> None: ...
124134
@overload
125135
def __setitem__(self, key: Literal["sign_gpg"], value: bool) -> None: ...
126136

137+
@overload
138+
def __setitem__(self, key: Literal["security_release"], value: bool) -> None: ...
139+
127140
@overload
128141
def __setitem__(self, key: Literal["release"], value: Tag) -> None: ...
129142

@@ -193,6 +206,13 @@ def is_release_candidate(self) -> bool:
193206
def is_feature_freeze_release(self) -> bool:
194207
return self.level == "b" and self.serial == 1
195208

209+
@property
210+
def is_security_release(self) -> bool:
211+
url = "https://peps.python.org/api/release-cycle.json"
212+
with urlopen(url) as response:
213+
data = json.loads(response.read())
214+
return str(data[self.basic_version]["status"]) == "security"
215+
196216
@property
197217
def nickname(self) -> str:
198218
return self.text.replace(".", "")

run_release.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -248,9 +248,10 @@ def __init__(
248248
self.db["ssh_key"] = ssh_key
249249
if not self.db.get("sign_gpg"):
250250
self.db["sign_gpg"] = sign_gpg
251-
252251
if not self.db.get("release"):
253252
self.db["release"] = release_tag
253+
if not self.db.get("security_release"):
254+
self.db["security_release"] = self.db["release"].is_security_release
254255

255256
print("Release data: ")
256257
print(f"- Branch: {release_tag.branch}")
@@ -260,6 +261,7 @@ def __init__(
260261
print(f"- SSH username: {self.db['ssh_user']}")
261262
print(f"- SSH key: {self.db['ssh_key'] or 'Default'}")
262263
print(f"- Sign with GPG: {self.db['sign_gpg']}")
264+
print(f"- Security release: {self.db['security_release']}")
263265
print()
264266

265267
def checkpoint(self) -> None:
@@ -1000,18 +1002,29 @@ def wait_until_all_files_are_in_folder(db: ReleaseShelf) -> None:
10001002
are_windows_files_there = f"python-{release}.exe" in all_files
10011003
are_macos_files_there = f"python-{release}-macos11.pkg" in all_files
10021004
are_linux_files_there = f"Python-{release}.tgz" in all_files
1003-
are_all_files_there = (
1004-
are_linux_files_there and are_windows_files_there and are_macos_files_there
1005-
)
1005+
1006+
if db["security_release"]:
1007+
# For security releases, only check Linux files
1008+
are_all_files_there = are_linux_files_there
1009+
else:
1010+
# For regular releases, check all platforms
1011+
are_all_files_there = (
1012+
are_linux_files_there
1013+
and are_windows_files_there
1014+
and are_macos_files_there
1015+
)
1016+
10061017
if not are_all_files_there:
10071018
linux_tick = "✅" if are_linux_files_there else "❌"
10081019
windows_tick = "✅" if are_windows_files_there else "❌"
10091020
macos_tick = "✅" if are_macos_files_there else "❌"
1010-
print(
1011-
f"\rWaiting for files: Linux {linux_tick} Windows {windows_tick} Mac {macos_tick} ",
1012-
flush=True,
1013-
end="",
1014-
)
1021+
1022+
if db["security_release"]:
1023+
waiting = f"\rWaiting for files: Linux {linux_tick} (security release - only checking Linux)"
1024+
else:
1025+
waiting = f"\rWaiting for files: Linux {linux_tick} Windows {windows_tick} Mac {macos_tick} "
1026+
1027+
print(waiting, flush=True, end="")
10151028
time.sleep(1)
10161029
print()
10171030

tests/test_release_tag.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import io
12
from subprocess import CompletedProcess
23

34
import pytest
@@ -140,3 +141,33 @@ def test_tag_long_name() -> None:
140141
assert rc.long_name == "3.13.0 release candidate 3"
141142
assert final_zero.long_name == "3.13.0"
142143
assert final_3.long_name == "3.13.3"
144+
145+
146+
@pytest.mark.parametrize(
147+
["version", "expected"],
148+
[
149+
("3.12.10", True),
150+
("3.13.3", False),
151+
],
152+
)
153+
def test_tag_is_security_release(
154+
version: str, expected: str, mocker: MockerFixture
155+
) -> None:
156+
# Arrange
157+
mock_response = b"""
158+
{
159+
"3.13": {
160+
"status": "bugfix"
161+
},
162+
"3.12": {
163+
"status": "security"
164+
}
165+
}
166+
"""
167+
mocker.patch("urllib.request.urlopen", return_value=io.BytesIO(mock_response))
168+
169+
# Act
170+
tag = release.Tag(version)
171+
172+
# Assert
173+
assert tag.is_security_release is expected

0 commit comments

Comments
 (0)