3232
3333import argparse
3434from dataclasses import dataclass
35+ from datetime import datetime , timedelta , timezone
36+ import functools
3537import getpass
3638import hashlib
3739import json
8486
8587# For these repositories, ignore any tags that match the specified regex.
8688_IGNORED_TAGS = {
89+ "dm_control_internal" : r"[^0-9]" ,
8790 "gymnasium_py_internal" : r"v[0-9.]+a[0-9]+" ,
8891 "libpng_internal" : r"v[0-9.]+(alpha|beta)[0-9]+" ,
8992 "msgpack_internal" : r"c-[0-9.]+" ,
@@ -167,9 +170,22 @@ def _smells_like_a_git_commit(revision):
167170 return len (revision ) == 40
168171
169172
170- def _is_ignored_tag (commit , workspace ):
171- """Returns true iff commit matches an ignore rule or seems to be a
172- pre-release.
173+ @functools .cache
174+ def _get_commit_date (gh_repo , commit ):
175+ """Returns the date of the given commit, or the start of the epoch if the
176+ date is not available."""
177+ committer_obj = gh_repo .commit (commit ).commit .get ("committer" , {})
178+ commit_date = datetime .fromisoformat (
179+ committer_obj .get ("date" , "1970-01-01T00:00:00Z" )
180+ )
181+ return commit_date
182+
183+
184+ def _is_ignored_tag (commit , date , workspace ):
185+ """Returns true iff any of the following are true of the input tag/release:
186+ * it matches an ignore rule (see _IGNORED_TAGS)
187+ * it seems to be a pre-release (ignored for lack of stability)
188+ * it is newer than one week (ignored for security reasons)
173189 """
174190 ignore_re = _IGNORED_TAGS .get (workspace )
175191 if ignore_re and re .match (ignore_re , commit ):
@@ -178,17 +194,26 @@ def _is_ignored_tag(commit, workspace):
178194 return True
179195
180196 development_stages = ["alpha" , "beta" , "pre" , "rc" , "unstable" ]
181- prerelease = any (stage in commit for stage in development_stages )
182- if prerelease :
197+ if any (stage in commit for stage in development_stages ):
183198 # Heuristically looks like a pre-release; ignore it, but log it for the
184199 # user to check.
185200 warn (f"Skipping prerelease { commit } for { workspace } " )
186- return prerelease
201+ return True
187202
203+ if date > datetime .now (timezone .utc ) - timedelta (days = 7 ):
204+ # This is a bleeding-edge release; ignore it (as potential for
205+ # malware), but log it for the user to check.
206+ warn (f"Skipping too-recent { commit } for { workspace } " )
207+ return True
208+
209+ return False
188210
211+
212+ @functools .cache
189213def _latest_tag (gh_repo , workspace ):
190214 for tag in gh_repo .tags ():
191- if _is_ignored_tag (tag .name , workspace ):
215+ tag_date = _get_commit_date (gh_repo , tag .name )
216+ if _is_ignored_tag (tag .name , tag_date , workspace ):
192217 continue
193218 return tag .name
194219 warn (f"Could not find any matching tags for { workspace } " )
@@ -223,17 +248,28 @@ def _handle_github(workspace_name, gh, data):
223248 if match :
224249 (new_hit ,) = match .groups ()
225250 if old_hit == new_hit :
226- if _is_ignored_tag (tag .name , workspace_name ):
251+ tag_date = _get_commit_date (gh_repo , tag .name )
252+ if _is_ignored_tag (tag .name , tag_date , workspace_name ):
227253 continue
228254 new_commit = tag .name
229255 break
230256 return old_commit , new_commit
231257
232- # By default, use the latest release if there is one. Otherwise, use the
233- # latest tag .
258+ # Check the latest few releases (in case the latest meets one of our
259+ # exclusion criteria), and fallback to tags if releases are unavailable .
234260 try :
235- new_commit = gh_repo .latest_release ().tag_name
236- if _is_ignored_tag (new_commit , workspace_name ):
261+ new_commit = None
262+ for release in gh_repo .releases (number = 3 ):
263+ # Use the time at which the release was published, rather than the
264+ # time of the commit tagged to the release. In practice, these may
265+ # not substantially differ often, but it is semantically closer
266+ # to what we're trying to capture.
267+ if not _is_ignored_tag (
268+ release .tag_name , release .published_at , workspace_name
269+ ):
270+ new_commit = release .tag_name
271+ break
272+ if new_commit is None :
237273 new_commit = _latest_tag (gh_repo , workspace_name )
238274 except github3 .exceptions .NotFoundError :
239275 new_commit = _latest_tag (gh_repo , workspace_name )
0 commit comments