summaryrefslogtreecommitdiff
path: root/tools/read-version
blob: 5a71e6c7648d3b010442524317b28d1ec5fb0cdf (plain)
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
#!/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)