[infra] Promote beta to stable when stable is ahead of beta.

Don't promote older releases to latest if promoted out of order.

Fixes: b/227744513
Change-Id: I954c8620897e59ed3caa459e0bd22e446e38d02d
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/283622
Commit-Queue: Jonas Termansen <sortie@google.com>
Reviewed-by: Alexander Thomas <athom@google.com>
This commit is contained in:
Jonas Termansen 2023-02-17 11:20:20 +00:00 committed by Commit Queue
parent 542129731e
commit 48219d6378
2 changed files with 98 additions and 4 deletions

View file

@ -6,6 +6,7 @@
# Dart SDK promote tools.
import json
import optparse
import os
import sys
@ -14,6 +15,7 @@ import urllib
import bots.bot_utils as bot_utils
from os.path import join
from utils import Version
DART_PATH = os.path.abspath(os.path.join(__file__, '..', '..'))
DRY_RUN = False
@ -93,6 +95,18 @@ def main():
_PromoteDartArchiveBuild(options.channel, source, options.revision)
def GetLatestRelease(channel):
release_namer = bot_utils.GCSNamer(channel, bot_utils.ReleaseType.RELEASE)
version_object = release_namer.version_filepath('latest')
global DRY_RUN
was_dry = DRY_RUN
DRY_RUN = False
(stdout, _, _) = Gsutil(['cat', version_object])
DRY_RUN = was_dry
version = json.loads(stdout)['version']
return Version(version=version)
def UpdateDocs():
try:
print('Updating docs')
@ -114,7 +128,6 @@ def _PromoteDartArchiveBuild(channel, source_channel, revision):
release_namer = bot_utils.GCSNamer(channel, bot_utils.ReleaseType.RELEASE)
def promote(to_revision):
def safety_check_on_gs_path(gs_path, revision, channel):
if not (revision != None and len(channel) > 0 and
('%s' % revision) in gs_path and channel in gs_path):
@ -182,7 +195,13 @@ def _PromoteDartArchiveBuild(channel, source_channel, revision):
Gsutil(no_cache + ['cp', from_loc, to_loc])
promote(revision)
promote('latest')
# Promote to latest unless it's an older version.
if GetLatestRelease(channel) <= Version(version=revision):
promote('latest')
# Promote beta to stable if stable becomes ahead of beta.
if channel == 'stable' and \
GetLatestRelease('beta') <= Version(version=revision):
_PromoteDartArchiveBuild('beta', 'stable', revision)
def Gsutil(cmd, throw_on_error=True):

View file

@ -9,6 +9,7 @@ from __future__ import print_function
import contextlib
import datetime
from functools import total_ordering
import glob
import imp
import json
@ -28,6 +29,8 @@ try:
except:
pass
SEMANTIC_VERSION_PATTERN = r'^(?P<major>0|[1-9]\d*)\.(?P<minor>0|[1-9]\d*)\.(?P<patch>0|[1-9]\d*)(?:-(?P<prerelease>(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+(?P<buildmetadata>[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$'
# To eliminate clashing with older archived builds on bleeding edge we add
# a base number bigger the largest svn revision (this also gives us an easy
@ -120,16 +123,88 @@ def GetMinidumpUtils(repo_path=DART_DIR):
os.path.join(repo_path, 'tools', 'minidump.py'))
@total_ordering
class Version(object):
def __init__(self, channel, major, minor, patch, prerelease,
prerelease_patch):
def __init__(self,
channel=None,
major=None,
minor=None,
patch=None,
prerelease=None,
prerelease_patch=None,
version=None):
self.channel = channel
self.major = major
self.minor = minor
self.patch = patch
self.prerelease = prerelease
self.prerelease_patch = prerelease_patch
if version:
self.set_version(version)
def set_version(self, version):
match = re.match(SEMANTIC_VERSION_PATTERN, version)
assert match, '%s must be a valid version' % version
self.channel = 'stable'
self.major = match['major']
self.minor = match['minor']
self.patch = match['patch']
self.prerelease = '0'
self.prerelease_patch = '0'
if match['prerelease']:
subversions = match['prerelease'].split('.')
self.prerelease = subversions[0]
self.prerelease_patch = subversions[1]
self.channel = subversions[2]
def __str__(self):
result = '%s.%s.%s' % (self.major, self.minor, self.patch)
if self.channel != 'stable':
result += '-%s.%s.%s' % (self.prerelease, self.prerelease_patch,
self.channel)
return result
def __eq__(self, other):
return self.channel == other.channel and \
self.major == other.major and \
self.minor == other.minor and \
self.patch == other.patch and \
self.prerelease == other.prerelease and \
self.prerelease_patch == other.prerelease_patch
def __lt__(self, other):
if int(self.major) < int(other.major):
return True
if int(self.major) > int(other.major):
return False
if int(self.minor) < int(other.minor):
return True
if int(self.minor) > int(other.minor):
return False
if int(self.patch) < int(other.patch):
return True
if int(self.patch) > int(other.patch):
return False
# The stable channel is ahead of the other channels on the same triplet.
if self.channel != 'stable' and other.channel == 'stable':
return True
if self.channel == 'stable' and other.channel != 'stable':
return False
# The be channel is ahead of the other channels on the same triplet.
if self.channel != 'be' and other.channel == 'be':
return True
if self.channel == 'be' and other.channel != 'be':
return False
if int(self.prerelease_patch) < int(other.prerelease_patch):
return True
if int(self.prerelease_patch) > int(other.prerelease_patch):
return False
if int(self.prerelease) < int(other.prerelease):
return True
if int(self.prerelease) > int(other.prerelease):
return False
return False
# Try to guess the host operating system.