mirror of https://github.com/mongodb/mongo
176 lines
6.3 KiB
Python
Executable File
176 lines
6.3 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
import contextlib
|
|
import os
|
|
import sys
|
|
import re
|
|
import urllib.request
|
|
from pathlib import Path
|
|
import git
|
|
import yaml
|
|
|
|
REQUIREMENTS_PATH = "buildscripts/requirements.txt"
|
|
GIT_ORG = "10gen"
|
|
ENTERPRISE_PATH = "src/mongo/db/modules/enterprise"
|
|
VENV_PATH = "python3-venv/bin/activate"
|
|
# alert user if less than 10gb of space left
|
|
STORAGE_AMOUNT = 10
|
|
# REQUIREMENTS_PATH = "buildscripts/requirements.txt"
|
|
LATEST_RELEASES = "https://raw.githubusercontent.com/mongodb/mongo/master/src/mongo/util/version/releases.yml"
|
|
|
|
# determine the path of the mongo directory
|
|
# this assumes the location of this script is in the buildscripts directory
|
|
buildscripts_path = os.path.dirname(os.path.realpath(__file__))
|
|
mongo_path = os.path.split(buildscripts_path)[0]
|
|
sys.path.append(mongo_path)
|
|
|
|
# pylint: disable=wrong-import-position
|
|
from site_scons.mongo.pip_requirements import verify_requirements, MissingRequirements
|
|
from buildscripts.resmokelib.utils import evergreen_conn
|
|
|
|
|
|
def check_cwd() -> int:
|
|
print("Checking if current directory is mongo root directory...")
|
|
if os.getcwd() != mongo_path:
|
|
print("ERROR: We do not support building outside of the mongo root directory.")
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
|
# checks if the script is being run inside of a python venv or not
|
|
def in_virtualenv() -> bool:
|
|
base_prefix = getattr(sys, "base_prefix", None) or getattr(sys, "real_prefix",
|
|
None) or sys.prefix
|
|
return base_prefix != sys.prefix
|
|
|
|
|
|
def get_git_repo(path: str, repo_name: str) -> git.Repo:
|
|
try:
|
|
return git.Repo(path)
|
|
except git.exc.NoSuchPathError:
|
|
print(f"ERROR: Count not find {repo_name} git repo at {mongo_path}")
|
|
print("Make sure your validate_env.py file is in the buildscripts directory")
|
|
return None
|
|
|
|
|
|
# returns the hash of the most recent commit that is shared between upstream and HEAD
|
|
def get_common_hash(repo: git.Repo, repo_name: str) -> str:
|
|
if not repo:
|
|
return None
|
|
|
|
upstream_remote = None
|
|
|
|
# determine which remote is pointed to the 10gen github repo
|
|
for remote in repo.remotes:
|
|
if remote.url.endswith(f"{GIT_ORG}/{repo_name}.git"):
|
|
upstream_remote = remote
|
|
break
|
|
|
|
if upstream_remote is None:
|
|
print("ERROR: Could not find remote for:", f"{GIT_ORG}/{repo_name}")
|
|
return None
|
|
|
|
upstream_remote.fetch("master")
|
|
common_hash = repo.merge_base("HEAD", f"{upstream_remote.name}/master")
|
|
|
|
if not common_hash or len(common_hash) == 0:
|
|
print(f"ERROR: Could not find common hash for {repo_name}")
|
|
return None
|
|
|
|
return common_hash[0]
|
|
|
|
|
|
def check_git_repos() -> int:
|
|
print("Checking if mongo repo and enterprise module repo are in sync...")
|
|
mongo_repo = get_git_repo(mongo_path, "mongo")
|
|
mongo_hash = get_common_hash(mongo_repo, "mongo")
|
|
enterprise_dir = os.path.join(mongo_path, ENTERPRISE_PATH)
|
|
enterprise_repo = get_git_repo(enterprise_dir, "mongo-enterprise-modules")
|
|
enterprise_hash = get_common_hash(enterprise_repo, "mongo-enterprise-modules")
|
|
|
|
if not mongo_hash or not enterprise_hash:
|
|
return 1
|
|
|
|
evg_api = evergreen_conn.get_evergreen_api(Path.home() / '.evergreen.yml')
|
|
manifest = evg_api.manifest("mongodb-mongo-master", mongo_hash)
|
|
modules = manifest.modules
|
|
if "enterprise" in modules and str(enterprise_hash) != modules["enterprise"].revision:
|
|
synced_enterprise_hash = modules["enterprise"].revision
|
|
print("Error: the mongo repo and enterprise module repo are out of sync")
|
|
print(
|
|
f"Try `git fetch; git rebase --onto {synced_enterprise_hash}` in the enterprise repo directory"
|
|
)
|
|
print(f"Your enterprise repo directory is {enterprise_dir}")
|
|
return 1
|
|
|
|
# Check if the git tag is out of date
|
|
# https://mongodb.stackenterprise.co/questions/145
|
|
print("Checking if your mongo repo git tag is up to date...")
|
|
releases_page = urllib.request.urlopen(LATEST_RELEASES)
|
|
page_bytes = releases_page.read()
|
|
text = page_bytes.decode("utf-8")
|
|
parsed_text = yaml.safe_load(text)
|
|
compat_versions = parsed_text['featureCompatibilityVersions']
|
|
if not compat_versions or len(compat_versions) <= 1:
|
|
print(
|
|
"ERROR: Something went wrong, there are not at least two feature compatibility mongo versions"
|
|
)
|
|
return 1
|
|
else:
|
|
# Hard coded to the second-to-last version because the last version should be the test version
|
|
target_version = compat_versions[-2]
|
|
local_version = mongo_repo.git.describe()
|
|
# get the version info we want out of git describe
|
|
trimmed_local_version = re.search("([0-9]+\\.[0-9]+)(\\.[0-9])?", local_version).group(1)
|
|
if trimmed_local_version != target_version:
|
|
print(
|
|
"ERROR: Your git tag is out of date, run `git config remote.origin.tagOpt '--tags'; git fetch origin master`"
|
|
)
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
|
# check for missing dependencies
|
|
def check_dependencies() -> int:
|
|
print("Checking for missing dependencies...")
|
|
requirements_file_path = os.path.join(mongo_path, REQUIREMENTS_PATH)
|
|
try:
|
|
with contextlib.redirect_stdout(None):
|
|
verify_requirements(requirements_file_path)
|
|
except MissingRequirements as ex:
|
|
print(ex)
|
|
print(
|
|
f"ERROR: Found missing dependencies, run `python -m pip install -r {REQUIREMENTS_PATH}`"
|
|
)
|
|
if not in_virtualenv():
|
|
print(
|
|
"WARNING: you are not in a python venv, we recommend using one to handle your requirements."
|
|
)
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
|
def check_space() -> int:
|
|
print("Checking if there is enough disk space to build...")
|
|
# Get the filesystem information where the mongo directory lies
|
|
statvfs = os.statvfs(mongo_path)
|
|
free_bytes = statvfs.f_frsize * statvfs.f_bfree
|
|
free_gb = (free_bytes // 1000) / 1000
|
|
|
|
# Warn if there is a low amount of space left in the filesystem
|
|
if free_gb < STORAGE_AMOUNT:
|
|
print(f"WARNING: only {free_gb}GB of space left in filesystem")
|
|
|
|
|
|
def main() -> int:
|
|
if any([check_cwd(), check_git_repos(), check_dependencies(), check_space()]):
|
|
exit(1)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|
|
|
|
# More requirements can be added as new issues appear
|