1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
|
#!/usr/bin/env python3
# This script has tests. Run pytest on the tools directory if you make changes
import json
import os
import re
import subprocess
import sys
from shutil import which
repo_base_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), ".."))
sys.path.insert(0, repo_base_dir)
from cloudinit import version as ci_version # noqa: E402
def tiny_p(cmd):
stderr = subprocess.PIPE
return subprocess.check_output(
cmd, stderr=stderr, stdin=None, universal_newlines=True
)
def is_gitdir(path):
return False
def get_version_details(version, version_long, is_release_branch_ci):
release = None
extra = None
commit = None
distance = None
# Should match upstream version number. E.g., 23.1 or 23.1.2
short_regex = r"(\d+\.\d+\.?\d*)"
# Should match version including upstream version, distance, and commit
# E.g., 23.1.2-10-g12ab34cd
long_regex = r"(\d+\.\d+\.?\d*){1}.*-(\d+)+-g([a-f0-9]{8}){1}.*"
short_match = re.search(short_regex, version)
long_match = re.search(long_regex, version_long)
if long_match:
release, distance, commit = long_match.groups()
extra = f"-{distance}-g{commit}"
elif short_match:
release = short_match.groups()[0]
return {
"release": release,
"version": version,
"version_long": version_long,
"extra": extra,
"commit": commit,
"distance": distance,
"is_release_branch_ci": is_release_branch_ci,
}
def get_version_from_git(
src_version, major_minor_version, use_tags, is_release_branch_ci
):
if is_gitdir(repo_base_dir) and which("git") and not is_release_branch_ci:
branch_name = tiny_p(
["git", "rev-parse", "--abbrev-ref", "HEAD"]
).strip()
if branch_name.startswith(f"upstream/{major_minor_version}"):
version = src_version
version_long = ""
else:
flags = ["--tags"] if use_tags else []
cmd = [
"git",
"describe",
branch_name,
"--abbrev=8",
] + flags
try:
version = tiny_p(cmd).strip()
version_long = tiny_p(cmd + ["--long"]).strip()
except subprocess.CalledProcessError as e:
if not any(
[
"No tags can describe" in e.stderr,
"cannot describe anything" in e.stderr,
]
):
raise
version = src_version
version_long = ""
else:
version = src_version
version_long = ""
return version, version_long
def main(use_tags: bool = False, output_json: bool = False):
src_version = ci_version.version_string()
# upstream/MM.NN.x tracks our patch level releases so ignore trailing '.x'
major_minor_version = ".".join(src_version.split(".")[:2])
# If we're performing CI for a new release branch (which our tooling
# creates with an "upstream/" prefix), then we don't want to enforce
# strict version matching because we know it will fail.
github_ci_release_br = bool(
os.environ.get("GITHUB_HEAD_REF", "").startswith(
f"upstream/{major_minor_version}"
)
)
travis_ci_release_br = bool(
os.environ.get("TRAVIS_PULL_REQUEST_BRANCH", "").startswith(
"upstream/"
)
)
is_release_branch_ci = github_ci_release_br or travis_ci_release_br
version, version_long = get_version_from_git(
src_version=src_version,
major_minor_version=major_minor_version,
use_tags=use_tags,
is_release_branch_ci=is_release_branch_ci,
)
details = get_version_details(version, version_long, is_release_branch_ci)
if output_json:
return json.dumps(details, indent=1)
output = ""
if details["release"]:
output += details["release"]
if details["extra"]:
output += details["extra"]
if not output:
output = src_version
return output
if __name__ == "__main__":
arg_use_tags = "--tags" in sys.argv or bool(os.environ.get("CI_RV_TAGS"))
arg_output_json = "--json" in sys.argv
output = main(arg_use_tags, arg_output_json)
print(output)
|