185 lines
7.1 KiB
Python
185 lines
7.1 KiB
Python
"""FCV and Server binary version constants used for multiversion testing."""
|
|
|
|
from bisect import bisect_left, bisect_right
|
|
import os
|
|
import re
|
|
import shutil
|
|
from subprocess import call, CalledProcessError, check_output, STDOUT, DEVNULL
|
|
import structlog
|
|
import yaml
|
|
|
|
from packaging.version import Version
|
|
try:
|
|
# when running resmoke
|
|
from buildscripts.resmokelib.multiversionsetupconstants import USE_EXISTING_RELEASES_FILE
|
|
except ImportError:
|
|
# when running db-contrib-tool
|
|
from multiversionsetupconstants import USE_EXISTING_RELEASES_FILE
|
|
|
|
LOGGER = structlog.getLogger(__name__)
|
|
|
|
# These values must match the include paths for artifacts.tgz in evergreen.yml.
|
|
MONGO_VERSION_YAML = ".resmoke_mongo_version.yml"
|
|
RELEASES_YAML = ".resmoke_mongo_release_values.yml"
|
|
|
|
|
|
def generate_mongo_version_file():
|
|
"""Generate the mongo version data file. Should only be called in the root of the mongo directory."""
|
|
try:
|
|
res = check_output("git describe", shell=True, text=True)
|
|
except CalledProcessError as exp:
|
|
raise ChildProcessError("Failed to run git describe to get the latest tag") from exp
|
|
|
|
# Write the current MONGO_VERSION to a data file.
|
|
with open(MONGO_VERSION_YAML, 'w') as mongo_version_fh:
|
|
# E.g. res = 'r5.1.0-alpha-597-g8c345c6693\n'
|
|
res = res[1:] # Remove the leading "r" character.
|
|
mongo_version_fh.write("mongo_version: " + res)
|
|
|
|
|
|
def generate_releases_file():
|
|
"""Generate the releases constants file."""
|
|
# Copy the 'releases.yml' file from the source tree.
|
|
releases_yaml_path = os.path.join("src", "mongo", "util", "version", "releases.yml")
|
|
if not os.path.isfile(releases_yaml_path):
|
|
LOGGER.info(
|
|
'Skipping yml file generation because file .resmoke_mongo_release_values.yml does not exist at path {}.'
|
|
.format(releases_yaml_path))
|
|
return
|
|
|
|
shutil.copyfile(releases_yaml_path, RELEASES_YAML)
|
|
|
|
|
|
def in_git_root_dir():
|
|
"""Return True if we are in the root of a git directory."""
|
|
if call(["git", "branch"], stderr=STDOUT, stdout=DEVNULL) != 0:
|
|
# We are not in a git directory.
|
|
return False
|
|
|
|
git_root_dir = check_output("git rev-parse --show-toplevel", shell=True, text=True).strip()
|
|
# Always use forward slash for the cwd path to resolve inconsistent formatting with Windows.
|
|
curr_dir = os.getcwd().replace("\\", "/")
|
|
return git_root_dir == curr_dir
|
|
|
|
|
|
if in_git_root_dir():
|
|
generate_mongo_version_file()
|
|
else:
|
|
LOGGER.info("Skipping generating mongo version file since we're not in the root of a git repo")
|
|
|
|
# Avoiding regenerating the releases file if this flag is set. Should only be set if there are
|
|
# multiple processes attempting to set up multiversion concurrently.
|
|
if not USE_EXISTING_RELEASES_FILE:
|
|
generate_releases_file()
|
|
else:
|
|
LOGGER.info(
|
|
"Skipping generating releases file since the --useExistingReleasesFile flag has been set")
|
|
|
|
|
|
class FCVConstantValues(object):
|
|
"""Object to hold the calculated FCV constants."""
|
|
|
|
def __init__(self, latest, last_continuous, last_lts, requires_fcv_tag_list,
|
|
fcvs_less_than_latest):
|
|
"""
|
|
Initialize the object.
|
|
|
|
:param latest: Latest FCV.
|
|
:param last_continuous: Last continuous FCV.
|
|
:param last_lts: Last LTS FCV.
|
|
:param requires_fcv_tag_list: List of FCVs that we need to generate a tag for.
|
|
:param fcvs_less_than_latest: List of all FCVs that are less than latest, starting from v4.0.
|
|
"""
|
|
self.latest = latest
|
|
self.last_continuous = last_continuous
|
|
self.last_lts = last_lts
|
|
self.requires_fcv_tag_list = requires_fcv_tag_list
|
|
self.fcvs_less_than_latest = fcvs_less_than_latest
|
|
|
|
|
|
def calculate_fcv_constants():
|
|
"""Calculate multiversion constants from data files."""
|
|
mongo_version_yml_file = open(MONGO_VERSION_YAML, 'r')
|
|
mongo_version_yml = yaml.safe_load(mongo_version_yml_file)
|
|
mongo_version = mongo_version_yml['mongo_version']
|
|
latest = Version(re.match(r'^[0-9]+\.[0-9]+', mongo_version).group(0))
|
|
|
|
releases_yml_file = open(RELEASES_YAML, 'r')
|
|
releases_yml = yaml.safe_load(releases_yml_file)
|
|
|
|
fcvs = releases_yml['featureCompatibilityVersions']
|
|
fcvs = list(map(Version, fcvs))
|
|
lts = releases_yml['longTermSupportReleases']
|
|
lts = list(map(Version, lts))
|
|
lower_bound_override = releases_yml.get('generateFCVLowerBoundOverride')
|
|
|
|
mongo_version_yml_file.close()
|
|
releases_yml_file.close()
|
|
|
|
# Highest release less than latest.
|
|
last_continuous = fcvs[bisect_left(fcvs, latest) - 1]
|
|
|
|
# Highest LTS release less than latest.
|
|
last_lts = lts[bisect_left(lts, latest) - 1]
|
|
|
|
# Normally, this list includes all FCVs greater than last LTS, up to latest.
|
|
# However, if we have 'generateFCVLowerBoundOverride' set in releases.yml, we will
|
|
# extend the lower bound to also include the prevous value of lastLTS.
|
|
lts_cutoff = last_lts
|
|
if lower_bound_override is not None:
|
|
lts_cutoff = Version(lower_bound_override)
|
|
requires_fcv_tag_list = fcvs[bisect_right(fcvs, lts_cutoff):bisect_right(fcvs, latest)]
|
|
|
|
# All FCVs less than latest.
|
|
fcvs_less_than_latest = fcvs[:bisect_left(fcvs, latest)]
|
|
|
|
return FCVConstantValues(latest, last_continuous, last_lts, requires_fcv_tag_list,
|
|
fcvs_less_than_latest)
|
|
|
|
|
|
def version_str(version):
|
|
"""Return a string of the given version in 'MAJOR.MINOR' form."""
|
|
return '{}.{}'.format(version.major, version.minor)
|
|
|
|
|
|
def tag_str(version):
|
|
"""Return a tag for the given version."""
|
|
return 'requires_fcv_{}{}'.format(version.major, version.minor)
|
|
|
|
|
|
def evg_project_str(version):
|
|
"""Return the evergreen project name for the given version."""
|
|
return 'mongodb-mongo-v{}.{}'.format(version.major, version.minor)
|
|
|
|
|
|
fcv_constants = calculate_fcv_constants()
|
|
|
|
LAST_LTS_BIN_VERSION = version_str(fcv_constants.last_lts)
|
|
LAST_CONTINUOUS_BIN_VERSION = version_str(fcv_constants.last_continuous)
|
|
|
|
LAST_LTS_FCV = version_str(fcv_constants.last_lts)
|
|
LAST_CONTINUOUS_FCV = version_str(fcv_constants.last_continuous)
|
|
LATEST_FCV = version_str(fcv_constants.latest)
|
|
|
|
LAST_CONTINUOUS_MONGO_BINARY = "mongo-" + LAST_CONTINUOUS_BIN_VERSION
|
|
LAST_CONTINUOUS_MONGOD_BINARY = "mongod-" + LAST_CONTINUOUS_BIN_VERSION
|
|
LAST_CONTINUOUS_MONGOS_BINARY = "mongos-" + LAST_CONTINUOUS_BIN_VERSION
|
|
|
|
LAST_LTS_MONGO_BINARY = "mongo-" + LAST_LTS_BIN_VERSION
|
|
LAST_LTS_MONGOD_BINARY = "mongod-" + LAST_LTS_BIN_VERSION
|
|
LAST_LTS_MONGOS_BINARY = "mongos-" + LAST_LTS_BIN_VERSION
|
|
|
|
REQUIRES_FCV_TAG_LATEST = tag_str(fcv_constants.latest)
|
|
|
|
# Generate tags for all FCVS in (lastLTS, latest], or (lowerBoundOverride, latest] if requested.
|
|
# All multiversion tests should be run with these tags excluded.
|
|
REQUIRES_FCV_TAG = ",".join([tag_str(fcv) for fcv in fcv_constants.requires_fcv_tag_list])
|
|
|
|
# Generate evergreen project names for all FCVs less than latest.
|
|
EVERGREEN_PROJECTS = ['mongodb-mongo-master']
|
|
EVERGREEN_PROJECTS.extend([evg_project_str(fcv) for fcv in fcv_constants.fcvs_less_than_latest])
|
|
|
|
OLD_VERSIONS = ["last_lts"]
|
|
if LAST_LTS_FCV != LAST_CONTINUOUS_FCV:
|
|
OLD_VERSIONS.append("last_continuous")
|