File: read-version

package info (click to toggle)
cloud-init 25.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 12,412 kB
  • sloc: python: 135,894; sh: 3,883; makefile: 141; javascript: 30; xml: 22
file content (144 lines) | stat: -rwxr-xr-x 4,358 bytes parent folder | download | duplicates (2)
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)