Skip to content

Commit 2d757b7

Browse files
committed
[tools] Avoid new_release upgrades newer than one week
Along the lines of commit 3da33b0, applied to the `new_release` tool when fetching from GitHub and other sources.
1 parent 9903730 commit 2d757b7

1 file changed

Lines changed: 48 additions & 12 deletions

File tree

tools/workspace/new_release.py

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232

3333
import argparse
3434
from dataclasses import dataclass
35+
from datetime import datetime, timedelta, timezone
36+
import functools
3537
import getpass
3638
import hashlib
3739
import json
@@ -84,6 +86,7 @@
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
189213
def _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

Comments
 (0)