33from __future__ import annotations
44
55import argparse
6+ from dataclasses import dataclass
67import json
78import os
89from pathlib import Path
1920)
2021VERSION_RE = re .compile (r'^version\s*=\s*"([^"]+)"' , re .MULTILINE )
2122SEMVER_RE = re .compile (r"^(\d+)\.(\d+)\.(\d+)(?:rc\d+)?$" )
23+ CURRENT = "current"
24+ BEHIND = "behind"
25+ AHEAD = "ahead"
26+ UNKNOWN = "unknown"
27+
28+
29+ @dataclass (frozen = True )
30+ class ReleaseVersionState :
31+ package_version : str
32+ finalized_release_version : str
33+ release_version_relation : str
2234
2335
2436def stable_version_tuple (version : str ) -> tuple [int , int , int ]:
@@ -28,7 +40,22 @@ def stable_version_tuple(version: str) -> tuple[int, int, int]:
2840 return tuple (int (part ) for part in match .groups ())
2941
3042
31- def pyproject_version (root : Path = REPO_ROOT ) -> str :
43+ def release_version_relation (
44+ * ,
45+ package_version : str ,
46+ finalized_release_version : str ,
47+ ) -> str :
48+ package_tuple = stable_version_tuple (package_version )
49+ finalized_tuple = stable_version_tuple (finalized_release_version )
50+ if package_tuple < finalized_tuple :
51+ return BEHIND
52+ if package_tuple > finalized_tuple :
53+ return AHEAD
54+ return CURRENT
55+
56+
57+ def pyproject_version (root : Path | None = None ) -> str :
58+ root = root or REPO_ROOT
3259 text = (root / "pyproject.toml" ).read_text ()
3360 match = VERSION_RE .search (text )
3461 if not match :
@@ -58,8 +85,12 @@ def version_violations(
5885 package_version : str ,
5986 finalized_release_version : str ,
6087) -> list [str ]:
61- if stable_version_tuple (package_version ) >= stable_version_tuple (
62- finalized_release_version
88+ if (
89+ release_version_relation (
90+ package_version = package_version ,
91+ finalized_release_version = finalized_release_version ,
92+ )
93+ != BEHIND
6394 ):
6495 return []
6596 return [
@@ -70,22 +101,55 @@ def version_violations(
70101 ]
71102
72103
73- def check_repository (
74- root : Path = REPO_ROOT ,
104+ def check_repository_state (
105+ root : Path | None = None ,
75106 * ,
76107 finalized_release_version : str | None = None ,
77108 version_manifest_url : str = DEFAULT_VERSION_MANIFEST_URL ,
78- ) -> list [str ]:
109+ ) -> ReleaseVersionState :
110+ root = root or REPO_ROOT
79111 package_version = pyproject_version (root )
80112 finalized_release_version = finalized_release_version or latest_hf_release_version (
81113 version_manifest_url
82114 )
83- return version_violations (
115+ relation = release_version_relation (
116+ package_version = package_version ,
117+ finalized_release_version = finalized_release_version ,
118+ )
119+ return ReleaseVersionState (
84120 package_version = package_version ,
85121 finalized_release_version = finalized_release_version ,
122+ release_version_relation = relation ,
86123 )
87124
88125
126+ def check_repository (
127+ root : Path | None = None ,
128+ * ,
129+ finalized_release_version : str | None = None ,
130+ version_manifest_url : str = DEFAULT_VERSION_MANIFEST_URL ,
131+ ) -> list [str ]:
132+ state = check_repository_state (
133+ root ,
134+ finalized_release_version = finalized_release_version ,
135+ version_manifest_url = version_manifest_url ,
136+ )
137+ return version_violations (
138+ package_version = state .package_version ,
139+ finalized_release_version = state .finalized_release_version ,
140+ )
141+
142+
143+ def write_github_outputs (state : ReleaseVersionState ) -> None :
144+ output_path = os .environ .get ("GITHUB_OUTPUT" )
145+ if not output_path :
146+ return
147+ with Path (output_path ).open ("a" ) as output :
148+ output .write (f"package_version={ state .package_version } \n " )
149+ output .write (f"finalized_release_version={ state .finalized_release_version } \n " )
150+ output .write (f"release_version_relation={ state .release_version_relation } \n " )
151+
152+
89153def main (argv : list [str ] | None = None ) -> int :
90154 parser = argparse .ArgumentParser (description = __doc__ )
91155 parser .add_argument (
@@ -103,17 +167,58 @@ def main(argv: list[str] | None = None) -> int:
103167 args = parser .parse_args (argv )
104168
105169 try :
106- violations = check_repository (
107- version_manifest_url = args .version_manifest_url ,
170+ package_version = pyproject_version ()
171+ stable_version_tuple (package_version )
172+ except (OSError , ValueError ) as exc :
173+ write_github_outputs (
174+ ReleaseVersionState (
175+ package_version = "" ,
176+ finalized_release_version = "" ,
177+ release_version_relation = UNKNOWN ,
178+ )
179+ )
180+ print (f"Could not read data package version: { exc } " , file = sys .stderr )
181+ return 1
182+
183+ try :
184+ finalized_release_version = latest_hf_release_version (args .version_manifest_url )
185+ state = ReleaseVersionState (
186+ package_version = package_version ,
187+ finalized_release_version = finalized_release_version ,
188+ release_version_relation = release_version_relation (
189+ package_version = package_version ,
190+ finalized_release_version = finalized_release_version ,
191+ ),
108192 )
109193 except (URLError , OSError , ValueError ) as exc :
194+ write_github_outputs (
195+ ReleaseVersionState (
196+ package_version = package_version ,
197+ finalized_release_version = "" ,
198+ release_version_relation = UNKNOWN ,
199+ )
200+ )
110201 print (
111202 f"Could not check finalized HF data release version: { exc } " , file = sys .stderr
112203 )
113204 return 1 if args .mode == "fail" else 0
114205
206+ write_github_outputs (state )
207+ violations = version_violations (
208+ package_version = state .package_version ,
209+ finalized_release_version = state .finalized_release_version ,
210+ )
115211 if not violations :
116- print ("Data package version is current with the latest finalized HF release." )
212+ if state .release_version_relation == AHEAD :
213+ print (
214+ "Data package version "
215+ f"{ state .package_version } is ahead of finalized HF release "
216+ f"{ state .finalized_release_version } ."
217+ )
218+ else :
219+ print (
220+ "Data package version is current with the latest finalized HF release."
221+ )
117222 return 0
118223
119224 for violation in violations :
0 commit comments