master
py 141 lines 4.95 KB
Raw
1 import os
2 import re
3 import requests
4 from itertools import groupby
5 from github import Github
6 from github.GithubException import GithubException
7
8 repos_URL = {
9 "stable": "netdata/netdata",
10 "nightly": "netdata/netdata-nightlies"
11 }
12
13 GH_TOKEN = os.getenv("GH_TOKEN")
14 if GH_TOKEN is None or GH_TOKEN != "":
15 print("Token is not defined or empty, continuing with limitation on requests per sec towards Github API")
16
17
18 def identify_channel(_version):
19 nightly_pattern = r'v(\d+)\.(\d+)\.(\d+)-(\d+)-nightly'
20 stable_pattern = r'v(\d+)\.(\d+)\.(\d+)'
21 if re.match(nightly_pattern, _version):
22 _channel = "nightly"
23 _pattern = nightly_pattern
24 elif re.match(stable_pattern, _version):
25 _channel = "stable"
26 _pattern = stable_pattern
27 else:
28 print("Invalid version format.")
29 return None
30 return _channel, _pattern
31
32
33 def padded_version(item):
34 key_value = '10000'
35 for value in item[1:]:
36 key_value += f'{value:05}'
37 return int(key_value)
38
39
40 def extract_version(title):
41 if identify_channel(title):
42 _, _pattern = identify_channel(title)
43 try:
44 match = re.match(_pattern, title)
45 if match:
46 return tuple(map(int, match.groups()))
47 except Exception as e:
48 print(f"Unexpected error: {e}")
49 return None
50
51
52 def get_release_path_and_filename(_version):
53 nightly_pattern = r'v(\d+)\.(\d+)\.(\d+)-(\d+)-nightly'
54 stable_pattern = r'v(\d+)\.(\d+)\.(\d+)'
55 if match := re.match(nightly_pattern, _version):
56 msb = match.group(1)
57 _path = "nightly"
58 _filename = f"v{msb}"
59 elif match := re.match(stable_pattern, _version):
60 msb = match.group(1)
61 _path = "stable"
62 _filename = f"v{msb}"
63 else:
64 print("Invalid version format.")
65 exit(1)
66 return (_path, _filename)
67
68
69 def compare_version_with_remote(version):
70 """
71 If the version = fun (version) you need to update the version in the
72 remote. If the version remote doesn't exist, returns the version
73 :param channel: any version of the agent
74 :return: the greater from version and version remote.
75 """
76
77 prefix = "https://packages.netdata.cloud/releases"
78 path, filename = get_release_path_and_filename(version)
79
80 remote_url = f"{prefix}/{path}/{filename}"
81 response = requests.get(remote_url)
82
83 if response.status_code == 200:
84 version_remote = response.text.rstrip()
85
86 version_components = extract_version(version)
87 remote_version_components = extract_version(version_remote)
88
89 absolute_version = padded_version(version_components)
90 absolute_remote_version = padded_version(remote_version_components)
91
92 if absolute_version > absolute_remote_version:
93 print(f"Version in the remote: {version_remote}, is older than the current: {version}, I need to update")
94 return (version)
95 else:
96 print(f"Version in the remote: {version_remote}, is newer than the current: {version}, no action needed")
97 return (None)
98 else:
99 # Remote version not found
100 print(f"Version in the remote not found, updating the predefined latest path with the version: {version}")
101 return (version)
102
103
104 def sort_and_grouby_major_agents_of_channel(channel):
105 """
106 Fetches the GH API and read either netdata/netdata or netdata/netdata-nightlies repo. It fetches all of their
107 releases implements a grouping by their major release number.
108 Every k,v in this dictionary is in the form; "vX": [descending ordered list of Agents in this major release].
109 :param channel: "nightly" or "stable"
110 :return: None or dict() with the Agents grouped by major version # (vX)
111 """
112 try:
113 G = Github(GH_TOKEN)
114 repo = G.get_repo(repos_URL[channel])
115 releases = repo.get_releases()
116 except GithubException as e:
117 print(f"GitHub API request failed: {e}")
118 return None
119
120 except Exception as e:
121 print(f"An unexpected error occurred: {e}")
122 return None
123
124 extracted_titles = [extract_version(item.title) for item in releases if
125 extract_version(item.title) is not None]
126 # Necessary sorting for implement the group by
127 extracted_titles.sort(key=lambda x: x[0])
128 # Group titles by major version
129 grouped_by_major = {major: list(group) for major, group in groupby(extracted_titles, key=lambda x: x[0])}
130 sorted_grouped_by_major = {}
131 for key, values in grouped_by_major.items():
132 sorted_values = sorted(values, key=padded_version, reverse=True)
133 sorted_grouped_by_major[key] = sorted_values
134 # Transform them in the correct form
135 if channel == "stable":
136 result_dict = {f"v{key}": [f"v{a}.{b}.{c}" for a, b, c in values] for key, values in
137 sorted_grouped_by_major.items()}
138 else:
139 result_dict = {f"v{key}": [f"v{a}.{b}.{c}-{d}-nightly" for a, b, c, d in values] for key, values in
140 sorted_grouped_by_major.items()}
141 return result_dict