Skip to content

Commit 2bd3f20

Browse files
authored
Swiss Cloud - dashboard scripts (#19)
Swiss Cloud - dashboard scripts Add 5 new scripts for grafana ashboards for Swiss cloud Reviewed-by: Vladimir Vshivkov
1 parent e413e8c commit 2bd3f20

8 files changed

+1288
-239
lines changed

Dockerfile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
FROM registry.access.redhat.com/ubi9/python-39:1-117.1686745331
1+
FROM registry.access.redhat.com/ubi9/python-39:1-133.1690899876
22

33
WORKDIR /app
44

5-
COPY --chown=1001:0 last_commit_info.py gitea_info.py github_info.py open_issues.py failed_zuul.py requirements.txt ./
5+
COPY --chown=1001:0 *.py requirements.txt ./
6+
67
USER 1001
78

89
RUN pip install --no-cache-dir -r requirements.txt

failed_zuul_swiss.py

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
import os
2+
import requests
3+
import json
4+
import re
5+
import psycopg2
6+
from datetime import datetime
7+
import time
8+
9+
start_time = time.time()
10+
11+
print("**FAILED SWISS PRS SCRIPT IS RUNNING**")
12+
13+
gitea_api_endpoint = "https://gitea.eco.tsi-dev.otc-service.com/api/v1"
14+
session = requests.Session()
15+
session.debug = True
16+
org = "docs-swiss"
17+
gitea_token = os.getenv("GITEA_TOKEN")
18+
github_token = os.getenv("GITHUB_TOKEN")
19+
20+
db_host = os.getenv("DB_HOST")
21+
db_port = os.getenv("DB_PORT")
22+
db_name = os.getenv("DB_NAME")
23+
db_user = os.getenv("DB_USER")
24+
db_password = os.getenv("DB_PASSWORD")
25+
26+
27+
def check_env_variables():
28+
required_env_vars = [
29+
"GITHUB_TOKEN", "DB_HOST", "DB_PORT",
30+
"DB_NAME", "DB_USER", "DB_PASSWORD", "GITEA_TOKEN"
31+
]
32+
for var in required_env_vars:
33+
if os.getenv(var) is None:
34+
raise Exception(f"Missing environment variable: {var}")
35+
36+
37+
def connect_to_db():
38+
print("Connecting to Postgres...")
39+
try:
40+
return psycopg2.connect(
41+
host=db_host,
42+
port=db_port,
43+
dbname=db_name,
44+
user=db_user,
45+
password=db_password
46+
)
47+
except psycopg2.Error as e:
48+
print(f"Connecting to Postgres: an error occurred while trying to connect to the database: {e}")
49+
return None
50+
51+
52+
def create_prs_table(conn, cur, table_name):
53+
try:
54+
cur.execute(
55+
f'''CREATE TABLE IF NOT EXISTS {table_name} (
56+
id SERIAL PRIMARY KEY,
57+
"Service Name" VARCHAR(255),
58+
"Failed PR Title" VARCHAR(255),
59+
"Failed PR URL" VARCHAR(255),
60+
"Squad" VARCHAR(255),
61+
"Failed PR State" VARCHAR(255),
62+
"Zuul URL" VARCHAR(255),
63+
"Zuul Check Status" VARCHAR(255),
64+
"Created at" VARCHAR(255),
65+
"Days Passed" INT,
66+
"Parent PR Number" INT
67+
);'''
68+
)
69+
conn.commit()
70+
print(f"Table {table_name} has been created successfully")
71+
except psycopg2.Error as e:
72+
print(f"Create table: an error occurred while trying to create a table {table_name} in the database: {e}")
73+
74+
75+
def get_repos(org, gitea_token):
76+
repos = []
77+
page = 1
78+
while True:
79+
try:
80+
repos_resp = session.get(f"{gitea_api_endpoint}/orgs/{org}/repos?page={page}&limit=50&token={gitea_token}")
81+
repos_resp.raise_for_status()
82+
except requests.exceptions.RequestException as e:
83+
print(f"Get repos: an error occurred while trying to get repos: {e}")
84+
break
85+
86+
try:
87+
repos_dict = json.loads(repos_resp.content.decode())
88+
except json.JSONDecodeError as e:
89+
print(f"Get repos: an error occurred while trying to decode JSON: {e}")
90+
break
91+
92+
for repo in repos_dict:
93+
repos.append(repo["name"])
94+
95+
link_header = repos_resp.headers.get("Link")
96+
if link_header is None or "rel=\"next\"" not in link_header:
97+
break
98+
else:
99+
page += 1
100+
101+
print(len(repos), "repos has been processed")
102+
103+
return repos
104+
105+
106+
def extract_number_from_body(text):
107+
try:
108+
match = re.search(r"#\d+", str(text))
109+
if match:
110+
return int(match.group()[1:])
111+
except ValueError as e:
112+
print(f"Extract number from body: an error occurred while converting match group to int: {e}")
113+
return None
114+
return None
115+
116+
117+
def get_f_pr_commits(org, repo, f_pr_number, gitea_token):
118+
try:
119+
zuul_url = None
120+
status = None
121+
created_at = None
122+
days_passed = None
123+
124+
pull_request_resp = session.get(f"{gitea_api_endpoint}/repos/{org}/{repo}/pulls/{f_pr_number}/commits?token={gitea_token}")
125+
pull_request_resp.raise_for_status()
126+
127+
f_pr_info = json.loads(pull_request_resp.content.decode("utf-8"))
128+
129+
if len(f_pr_info) > 0:
130+
f_commit_sha = f_pr_info[0]["sha"]
131+
commit_status_resp = session.get(f"{gitea_api_endpoint}/repos/{org}/{repo}/statuses/{f_commit_sha}?token={gitea_token}")
132+
commit_status_resp.raise_for_status()
133+
134+
commit_info = json.loads(commit_status_resp.content.decode("utf-8"))
135+
commit_status = commit_info[0]["status"]
136+
if commit_status == "failure":
137+
status = commit_info[0]["status"]
138+
zuul_url = commit_info[0]["target_url"]
139+
created_at = datetime.strptime(commit_info[0]["created_at"], '%Y-%m-%dT%H:%M:%SZ')
140+
now = datetime.utcnow()
141+
days_passed = (now - created_at).days
142+
143+
return zuul_url, status, created_at, days_passed
144+
145+
except requests.exceptions.RequestException as e:
146+
print(f"Get failed PR commits: an error occurred while trying to get pull requests of {repo} repo: {e}")
147+
148+
149+
def get_failed_prs(repo, gitea_token, conn, cur):
150+
try:
151+
if repo != "doc-exports" and repo != "dsf":
152+
page = 1
153+
while True:
154+
repo_resp = session.get(f"{gitea_api_endpoint}/repos/{org}/{repo}/pulls?state=open&page={page}&limit=1000&token={gitea_token}")
155+
pull_requests = []
156+
if repo_resp.status_code == 200:
157+
try:
158+
pull_requests = json.loads(repo_resp.content.decode("utf-8"))
159+
except json.JSONDecodeError as e:
160+
print(f"Get parent PR: an error occurred while decoding JSON: {e}")
161+
if not pull_requests:
162+
break
163+
164+
for pull_req in pull_requests:
165+
body = pull_req["body"]
166+
if body.startswith("This is an automatically created Pull Request"):
167+
if pull_req["merged"] is True:
168+
continue
169+
else:
170+
f_par_pr_num = extract_number_from_body(body)
171+
f_pr_number = pull_req["number"]
172+
service_name = repo
173+
squad = ""
174+
title = pull_req["title"]
175+
f_pr_url = pull_req["url"]
176+
f_pr_state = pull_req["state"]
177+
zuul_url, status, created_at, days_passed = get_f_pr_commits(repo, f_pr_number, gitea_token)
178+
try:
179+
if all(item is not None for item in [zuul_url, status, created_at, days_passed]):
180+
cur.execute("""
181+
INSERT INTO public.failed_zuul_prs_swiss
182+
("Service Name", "Failed PR Title", "Failed PR URL", "Squad", "Failed PR State", "Zuul URL", "Zuul Check Status", "Days Passed", "Parent PR Number")
183+
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
184+
""",
185+
(service_name, title, f_pr_url, squad, f_pr_state, zuul_url, status, days_passed, f_par_pr_num)
186+
)
187+
conn.commit()
188+
except Exception as e:
189+
print(f"Failed PRs: an error occurred while inserting into the failed_zuul_prs_swiss table: {e}")
190+
else:
191+
continue
192+
page += 1
193+
194+
except Exception as e:
195+
print('Failed PRs: an error occurred:', e)
196+
197+
198+
def update_squad_and_title(conn, cur):
199+
print("Updating squads and titles...")
200+
try:
201+
cur.execute("SELECT * FROM failed_zuul_prs_swiss;")
202+
failed_prs_rows = cur.fetchall()
203+
204+
for row in failed_prs_rows:
205+
cur.execute(
206+
"""UPDATE failed_zuul_prs_swiss
207+
SET "Service Name" = rtc."Title", "Squad" = rtc."Category"
208+
FROM repo_title_category AS rtc
209+
WHERE failed_zuul_prs_swiss."Service Name" = rtc."Repository"
210+
AND failed_zuul_prs_swiss.id = %s;""",
211+
(row[0],)
212+
)
213+
cur.execute(
214+
"""UPDATE failed_zuul_prs_swiss
215+
SET "Squad" = 'Other'
216+
WHERE failed_zuul_prs_swiss."Service Name" IN ('doc-exports', 'docs_on_docs', 'docsportal')
217+
AND failed_zuul_prs_swiss.id = %s;""",
218+
(row[0],)
219+
)
220+
conn.commit()
221+
222+
except Exception as e:
223+
print(f"Error updating squad and title: {e}")
224+
conn.rollback()
225+
226+
227+
def main():
228+
check_env_variables()
229+
230+
conn = connect_to_db()
231+
cur = conn.cursor()
232+
233+
cur.execute("DROP TABLE IF EXISTS failed_zuul_prs_swiss")
234+
conn.commit()
235+
236+
create_prs_table(conn, cur, "failed_zuul_prs_swiss")
237+
238+
repos = get_repos(org, gitea_token)
239+
240+
print("Gathering PRs info...")
241+
for repo in repos:
242+
get_failed_prs(repo, gitea_token, conn, cur)
243+
244+
update_squad_and_title(conn, cur)
245+
246+
cur.close()
247+
conn.close()
248+
249+
end_time = time.time()
250+
execution_time = end_time - start_time
251+
minutes, seconds = divmod(execution_time, 60)
252+
print(f"Script failed_zuul.py executed in {int(minutes)} minutes {int(seconds)} seconds! Let's go drink some beer :)")
253+
254+
255+
if __name__ == "__main__":
256+
main()

0 commit comments

Comments
 (0)