summaryrefslogtreecommitdiffstats
path: root/.github/scripts/modules/version_manipulation.py
blob: cc346fb54d28da1b71129efa357b0c591c463082 (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
137
138
139
140
141
import os
import re
import requests
from itertools import groupby
from github import Github
from github.GithubException import GithubException

repos_URL = {
    "stable": "netdata/netdata",
    "nightly": "netdata/netdata-nightlies"
}

GH_TOKEN = os.getenv("GH_TOKEN")
if GH_TOKEN is None or GH_TOKEN != "":
    print("Token is not defined or empty, continuing with limitation on requests per sec towards Github API")


def identify_channel(_version):
    nightly_pattern = r'v(\d+)\.(\d+)\.(\d+)-(\d+)-nightly'
    stable_pattern = r'v(\d+)\.(\d+)\.(\d+)'
    if re.match(nightly_pattern, _version):
        _channel = "nightly"
        _pattern = nightly_pattern
    elif re.match(stable_pattern, _version):
        _channel = "stable"
        _pattern = stable_pattern
    else:
        print("Invalid version format.")
        return None
    return _channel, _pattern


def padded_version(item):
    key_value = '10000'
    for value in item[1:]:
        key_value += f'{value:05}'
    return int(key_value)


def extract_version(title):
    if identify_channel(title):
        _, _pattern = identify_channel(title)
    try:
        match = re.match(_pattern, title)
        if match:
            return tuple(map(int, match.groups()))
    except Exception as e:
        print(f"Unexpected error: {e}")
        return None


def get_release_path_and_filename(_version):
    nightly_pattern = r'v(\d+)\.(\d+)\.(\d+)-(\d+)-nightly'
    stable_pattern = r'v(\d+)\.(\d+)\.(\d+)'
    if match := re.match(nightly_pattern, _version):
        msb = match.group(1)
        _path = "nightly"
        _filename = f"v{msb}"
    elif match := re.match(stable_pattern, _version):
        msb = match.group(1)
        _path = "stable"
        _filename = f"v{msb}"
    else:
        print("Invalid version format.")
        exit(1)
    return (_path, _filename)


def compare_version_with_remote(version):
    """
    If the version = fun (version) you need to update the version in the
    remote. If the version remote doesn't exist, returns the version
    :param channel: any version of the agent
    :return: the greater from version and version remote.
    """

    prefix = "https://packages.netdata.cloud/releases"
    path, filename = get_release_path_and_filename(version)

    remote_url = f"{prefix}/{path}/{filename}"
    response = requests.get(remote_url)

    if response.status_code == 200:
        version_remote = response.text.rstrip()

        version_components = extract_version(version)
        remote_version_components = extract_version(version_remote)

        absolute_version = padded_version(version_components)
        absolute_remote_version = padded_version(remote_version_components)

        if absolute_version > absolute_remote_version:
            print(f"Version in the remote: {version_remote}, is older than the current: {version}, I need to update")
            return (version)
        else:
            print(f"Version in the remote: {version_remote}, is newer than the current: {version}, no action needed")
            return (None)
    else:
        # Remote version not found
        print(f"Version in the remote not found, updating the predefined latest path with the version: {version}")
        return (version)


def sort_and_grouby_major_agents_of_channel(channel):
    """
    Fetches the GH API and read either netdata/netdata or netdata/netdata-nightlies repo. It fetches all of their
    releases implements a grouping by their major release number.
    Every k,v in this dictionary is in the form; "vX": [descending ordered list of Agents in this major release].
    :param channel: "nightly" or "stable"
    :return: None or dict() with the Agents grouped by major version # (vX)
    """
    try:
        G = Github(GH_TOKEN)
        repo = G.get_repo(repos_URL[channel])
        releases = repo.get_releases()
    except GithubException as e:
        print(f"GitHub API request failed: {e}")
        return None

    except Exception as e:
        print(f"An unexpected error occurred: {e}")
        return None

    extracted_titles = [extract_version(item.title) for item in releases if
                        extract_version(item.title) is not None]
    # Necessary sorting for implement the group by
    extracted_titles.sort(key=lambda x: x[0])
    # Group titles by major version
    grouped_by_major = {major: list(group) for major, group in groupby(extracted_titles, key=lambda x: x[0])}
    sorted_grouped_by_major = {}
    for key, values in grouped_by_major.items():
        sorted_values = sorted(values, key=padded_version, reverse=True)
        sorted_grouped_by_major[key] = sorted_values
    # Transform them in the correct form
    if channel == "stable":
        result_dict = {f"v{key}": [f"v{a}.{b}.{c}" for a, b, c in values] for key, values in
                       sorted_grouped_by_major.items()}
    else:
        result_dict = {f"v{key}": [f"v{a}.{b}.{c}-{d}-nightly" for a, b, c, d in values] for key, values in
                       sorted_grouped_by_major.items()}
    return result_dict