#!/usr/bin/env python3 import os import json import subprocess import sys _tdir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) sys.path.insert(0, _tdir) 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 which(program): # Return path of program for execution if found in path def is_exe(fpath): return os.path.isfile(fpath) and os.access(fpath, os.X_OK) _fpath, _ = os.path.split(program) if _fpath: if is_exe(program): return program else: for path in os.environ.get("PATH", "").split(os.pathsep): path = path.strip('"') exe_file = os.path.join(path, program) if is_exe(exe_file): return exe_file return None def is_gitdir(path): # Return boolean indicating if path is a git tree. git_meta = os.path.join(path, ".git") if os.path.isdir(git_meta): return True if os.path.exists(git_meta): # in a git worktree, .git is a file with 'gitdir: x' with open(git_meta, "rb") as fp: if b"gitdir:" in fp.read(): return True return False use_long = "--long" in sys.argv or os.environ.get("CI_RV_LONG") use_tags = "--tags" in sys.argv or os.environ.get("CI_RV_TAGS") output_json = "--json" in sys.argv 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]) version_long = "" # 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 = bool(github_ci_release_br or travis_ci_release_br) if is_gitdir(_tdir) and which("git") and not is_release_branch_ci: # This cmd can be simplified to ["git", "branch", "--show-current"] # after bionic EOL. 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 = [] if use_tags: flags = ["--tags"] cmd = [ "git", "describe", branch_name, ] + flags try: version = tiny_p(cmd).strip() version_long = tiny_p(cmd + ["--long"]).strip() except subprocess.CalledProcessError as e: if "No tags can describe" in e.stderr: print(f"{cmd} found no tags. Using cloudinit.verison.py ") version = src_version version_long = "" else: raise else: version = src_version version_long = "" # version is X.Y.Z[+xxx.gHASH] # version_long is None or X.Y.Z-xxx-gHASH release = version.partition("-")[0] extra = None commit = None distance = None if version_long: info = version_long.partition("-")[2] extra = f"-{info}" distance, commit = info.split("-") # remove the 'g' from gHASH commit = commit[1:] data = { "release": release, "version": version, "version_long": version_long, "extra": extra, "commit": commit, "distance": distance, "is_release_branch_ci": is_release_branch_ci, } if output_json: sys.stdout.write(json.dumps(data, indent=1) + "\n") else: sys.stdout.write(version + "\n") sys.exit(0)