@@ -13,27 +13,84 @@ def main():
13
13
with open (Path (__file__ ).parent / "pyproject.toml" , "rb" ) as f :
14
14
pyproject = tomllib .load (f )
15
15
16
- all_versions = get_all_versions ()
16
+ all_releases = get_all_releases ()
17
17
current_version = get_current_version (pyproject = pyproject )
18
- target_versions = [v for v in all_versions if v > current_version ]
18
+ all_non_yanked_versions = sorted ([
19
+ release_version
20
+ for release_version , release in all_releases .items ()
21
+ if not any ([asset ["yanked" ] for asset in release ])
22
+ ])
23
+
24
+ target_versions = [v for v in all_non_yanked_versions if v > current_version ]
25
+
26
+ if not target_versions and not any ([
27
+ asset ["yanked" ] for asset in all_releases [current_version ]
28
+ ]):
29
+ last_valid_version = all_non_yanked_versions [- 1 ]
30
+ paths = process_version (last_valid_version )
31
+ if subprocess .check_output (["git" , "status" , "-s" ]).strip ():
32
+ push_changed_version (paths , f"Mirror: yanked { current_version } " )
33
+
34
+ # Make `last_valid_version` the top tag and release
35
+ subprocess .run (
36
+ [
37
+ "gh" ,
38
+ "release" ,
39
+ "delete" ,
40
+ f"{ last_valid_version } " ,
41
+ "--cleanup-tag" ,
42
+ "--yes" ,
43
+ ],
44
+ check = True ,
45
+ )
46
+ create_tagged_release (last_valid_version )
47
+ return
19
48
20
49
for version in target_versions :
21
50
paths = process_version (version )
22
51
if subprocess .check_output (["git" , "status" , "-s" ]).strip ():
23
- subprocess .run (["git" , "add" , * paths ], check = True )
24
- subprocess .run (["git" , "commit" , "-m" , f"Mirror: { version } " ], check = True )
25
- subprocess .run (["git" , "tag" , f"{ version } " ], check = True )
52
+ push_changed_version (paths , f"Mirror: { version } " )
53
+ create_tagged_release (version )
26
54
else :
27
55
print (f"No change { version } " )
28
56
29
57
30
- def get_all_versions () -> list [Version ]:
58
+ def push_changed_version (paths : typing .Sequence [str ], commit_message : str ) -> None :
59
+ subprocess .run (["git" , "add" , * paths ], check = True )
60
+ subprocess .run (["git" , "commit" , "-m" , commit_message ], check = True )
61
+ subprocess .run (["git" , "push" , "origin" , "HEAD:refs/heads/main" ], check = True )
62
+
63
+
64
+ def create_tagged_release (version : Version ) -> None :
65
+ subprocess .run (["git" , "tag" , f"{ version } " ], check = True )
66
+ subprocess .run (
67
+ ["git" , "push" , "origin" , "HEAD:refs/heads/main" , "--tags" ], check = False
68
+ )
69
+ subprocess .run (
70
+ [
71
+ "gh" ,
72
+ "release" ,
73
+ "create" ,
74
+ f"{ version } " ,
75
+ "--title" ,
76
+ f"{ version } " ,
77
+ "--notes" ,
78
+ f"See: https://github.com/astral-sh/uv/releases/tag/{ version } " ,
79
+ "--latest" ,
80
+ ],
81
+ check = False ,
82
+ )
83
+
84
+
85
+ def get_all_releases () -> dict [Version , list [dict [str , typing .Any ]]]:
31
86
response = urllib3 .request ("GET" , "https://pypi.org/pypi/uv/json" )
32
87
if response .status != 200 :
33
88
raise RuntimeError ("Failed to fetch versions from pypi" )
34
89
35
- versions = [Version (release ) for release in response .json ()["releases" ]]
36
- return sorted (versions )
90
+ return {
91
+ Version (release_version ): release
92
+ for release_version , release in response .json ()["releases" ].items ()
93
+ }
37
94
38
95
39
96
def get_current_version (pyproject : dict ) -> Version :
0 commit comments