Skip to content

Commit 8eb633e

Browse files
committed
Fix sending mail about EOL status.
Several typos fixed. Also added information in case EOL ticket is present Signed-off-by: Petr "Stone" Hracek <phracek@redhat.com>
1 parent f46d21e commit 8eb633e

13 files changed

Lines changed: 204 additions & 116 deletions

File tree

‎.github/workflows/build-and-push.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
registry_username: ${{ secrets.QUAY_IMAGE_SCLORG_BUILDER_USERNAME }}
2020
registry_token: ${{ secrets.QUAY_IMAGE_SCLORG_BUILDER_TOKEN }}
2121
dockerfile: Dockerfile.daily-tests
22-
tag: "0.10.4"
22+
tag: "0.10.5"
2323
image_name: "upstream-daily-tests"
2424
quay_application_token: ${{ secrets.QUAY_IMAGE_SCLORG_UPDATE_DESC }}
2525

@@ -31,6 +31,6 @@ jobs:
3131
registry_username: ${{ secrets.QUAY_IMAGE_SCLORG_BUILDER_USERNAME }}
3232
registry_token: ${{ secrets.QUAY_IMAGE_SCLORG_BUILDER_TOKEN }}
3333
dockerfile: Dockerfile.eol-checker
34-
tag: "0.10.4"
34+
tag: "0.10.5"
3535
image_name: "upstream-eol-checker"
3636
quay_application_token: ${{ secrets.QUAY_IMAGE_SCLORG_UPDATE_DESC }}

‎Dockerfile.daily-tests‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ FROM quay.io/fedora/fedora:42
22

33
ENV SHARED_DIR="/var/ci-scripts" \
44
VERSION="42" \
5-
RELEASE_UPSTREAM="0.10.4" \
5+
RELEASE_UPSTREAM="0.10.5" \
66
UPSTREAM_TMT_REPO="https://github.com/sclorg/sclorg-testing-farm" \
77
UPSTREAM_TMT_DIR="sclorg-testing-farm" \
88
HOME="/home/nightly" \

‎Dockerfile.eol-checker‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
FROM quay.io/fedora/fedora:42
22

33
ENV VERSION="42" \
4-
RELEASE_UPSTREAM="0.10.4" \
4+
RELEASE_UPSTREAM="0.10.5" \
55
HOME="/home/eol-checker" \
66
SUMMARY="EOL checker for SCL org projects" \
77
DESCRIPTION="This image is used to run EOL checker for SCL org projects in CI." \

‎Makefile‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ shellcheck:
99
build_images: daily_tests eol_checker
1010

1111
daily_tests:
12-
podman build -t quay.io/sclorg/upstream-daily-tests:0.10.4 -f Dockerfile.daily-tests .
12+
podman build -t quay.io/sclorg/upstream-daily-tests:0.10.5 -f Dockerfile.daily-tests .
1313

1414
eol_checker:
15-
podman build -t quay.io/sclorg/upstream-eol-checker:0.10.4 -f Dockerfile.eol-checker .
15+
podman build -t quay.io/sclorg/upstream-eol-checker:0.10.5 -f Dockerfile.eol-checker .

‎eol-checker/eol-checker‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@ def main(args):
6464
Returns:
6565
The exit code. 0 if successful, 1 if error.
6666
"""
67-
print(f"Arguments: {args}")
6867
checker = ContainerEolChecker(debug=args.debug, send_email=args.send_email)
6968
checker.run()
7069
sys.exit(0)

‎eol-checker/eol_checker/checker.py‎

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@
4444
is_eol_version,
4545
get_lifecycles,
4646
load_mails_from_environment,
47-
get_env_variable,
4847
)
4948
from eol_checker.constants import OS_NAMES, CONTAINER_NAMES
5049

@@ -60,21 +59,21 @@ class ContainerEolChecker(object):
6059

6160
def __init__(self, debug: bool = False, send_email: bool = False):
6261
self.today = date.today()
62+
# Used for OpenShift CronJob
63+
env_debug = os.getenv("DEBUG")
64+
debug_enabled = (
65+
debug if env_debug is None else env_debug.strip().lower() in {"1", "true", "yes", "on"}
66+
)
67+
self._setup_logger(debug=debug_enabled)
6368
self.lifecycle_data: Any = None
6469
self.eol_images: dict = {}
6570
self.already_eol_images: dict = {}
6671
self.approaching_eol_images: dict = {}
6772
self.os_name: str = ""
68-
self.default_mails: List[str] = os.getenv("DEFAULT_EMAILS", "").split(",")
73+
self.default_mails: List[str] = os.getenv("DEFAULT_EMAILS").split(",")
6974
self.container_to_analyze: str = ""
7075
self.jira_fetcher = JiraFetcher()
7176
self.eol_sme_mails = load_mails_from_environment()
72-
# Used for OpenShift CronJob
73-
env_debug = os.getenv("DEBUG")
74-
debug_enabled = (
75-
debug if env_debug is None else env_debug.strip().lower() in {"1", "true", "yes", "on"}
76-
)
77-
self._setup_logger(debug=debug_enabled)
7877

7978
env_send_email = os.getenv("SEND_EMAIL")
8079
self.send_email = (
@@ -150,7 +149,7 @@ def analyze_lifecycle_yaml(self, data: Any) -> None:
150149
for lifecycle in get_lifecycles(data):
151150
self.check_enddate(lifecycle)
152151

153-
def _get_jira_msg(self, report_type: str, enddate: str) -> str:
152+
def _get_jira_msg(self, report_type: str, enddate: str, jira_id: str = "") -> str:
154153
"""
155154
Generate a Jira message.
156155
Args:
@@ -159,12 +158,15 @@ def _get_jira_msg(self, report_type: str, enddate: str) -> str:
159158
Returns:
160159
The Jira message.
161160
"""
162-
jira_msg = (
163-
"Connection to Jira not available"
164-
if self.jira_fetcher.jira is None
165-
else "Jira ticket is not filled. Use Jira issue template:"
166-
)
167-
return self.bold_line + f"{report_type} in {enddate}" + self.bold_line_end + f". {jira_msg}"
161+
jira_url = get_jira_ticket_url(jira_issue_id=self.jira_fetcher.jira_deprecation_ticket)
162+
url = f"<a href='{jira_url}'>{jira_url}</a>" if self.send_email else jira_url
163+
msg = "Jira ticket is not filled. Use this template: "
164+
if jira_id != "":
165+
jira_url = get_jira_ticket_url(jira_issue_id=jira_id)
166+
url = f"<a href='{jira_url}'>{jira_url}</a>" if self.send_email else jira_url
167+
msg = "Jira ticket is already filed: "
168+
jira_msg = f"{msg} {url}"
169+
return self.bold_line + f"{report_type} in {enddate}. " + self.bold_line_end + jira_msg
168170

169171
def summary_for_images(self, images: dict, os_name: str, eol_type: bool = True) -> str:
170172
"""
@@ -188,27 +190,25 @@ def summary_for_images(self, images: dict, os_name: str, eol_type: bool = True)
188190
logger.info("Processing container: '%s' with values: '%s'", container_name, values)
189191
stream_name = values["name"]
190192
if self.send_email:
191-
for mail in self.eol_sme_mails[container_name]:
193+
mails = [
194+
self.eol_sme_mails[group]
195+
for group in self.eol_sme_mails.keys()
196+
if container_name.startswith(group)
197+
]
198+
logger.debug("Mails: '%s' for container: '%s'", mails, container_name)
199+
for mail in mails:
192200
if mail and mail not in self.default_mails:
193-
self.default_mails.append(mail)
201+
self.default_mails.extend(mail)
194202
if self.jira_fetcher.jira is None:
195203
logger.error("Connection to Jira failed")
196204
jira_msg = self._get_jira_msg(report_type=report_type, enddate=values["enddate"])
197-
jira_id = self.jira_fetcher.jira_deprecation_ticket
198-
jira_url = get_jira_ticket_url(jira_issue_id=jira_id)
199-
url = f"<a href='{jira_url}'>{jira_url}</a>" if self.send_email else jira_url
200-
report += f"{stream_name} for {os_name} {jira_msg} {url}{self.end_line}"
205+
report += f"{stream_name} for {os_name}.{jira_msg} {self.end_line}"
201206
continue
202-
jira_msg = self._get_jira_msg(report_type=report_type, enddate=values["enddate"])
203-
jira_msg += "Jira ticket is already filed:"
204-
jira_id = self.jira_fetcher.is_jira_filled_for_container(stream_name=stream_name)
205-
if jira_id == "":
206-
jira_msg = self._get_jira_msg(report_type=report_type, enddate=values["enddate"])
207-
jira_id = self.jira_fetcher.jira_deprecation_ticket
208-
jira_url = get_jira_ticket_url(jira_issue_id=jira_id)
209-
url = f"<a href='{jira_url}'>{jira_url}</a>" if self.send_email else jira_url
210-
report += f"{stream_name} for {os_name} {jira_msg} {url}{self.end_line}"
211-
report += "\n"
207+
jira_id = self.jira_fetcher.is_jira_filed_for_container(stream_name=stream_name)
208+
jira_msg = self._get_jira_msg(
209+
report_type=report_type, enddate=values["enddate"], jira_id=jira_id
210+
)
211+
report += f"{stream_name} for {os_name} {jira_msg} {self.end_line}\n"
212212

213213
return report
214214

@@ -265,26 +265,25 @@ def send_emails(self):
265265
Send emails with the container EOL information.
266266
"""
267267
logger.debug("Sending emails is enabled")
268-
logger.debug(", ".join(self.default_mails))
269-
self.smtp_server = get_env_variable("SMTP_SERVER", "smtp.redhat.com")
270-
self.smtp_port = int(get_env_variable("SMTP_PORT", "25"))
268+
logger.debug(self.default_mails)
269+
self.smtp_server = os.getenv("SMTP_SERVER", "smtp.redhat.com")
270+
self.smtp_port = int(os.getenv("SMTP_PORT", "25"))
271271

272272
send_from = "phracek@redhat.com"
273-
send_to = self.default_mails
274273
self.mime_msg["From"] = send_from
275-
self.mime_msg["To"] = ", ".join(send_to)
274+
self.mime_msg["To"] = ",".join(self.default_mails)
276275
self.mime_msg["Subject"] = "Container EOL Checker Report"
277276
logger.debug(
278277
"Sending email with subject: 'Container EOL Checker Report' to: '%s'",
279-
send_to,
278+
self.default_mails,
280279
)
281280
logger.debug("Email body: '%s'", self.body)
282281
logger.debug("Message: '%s'", self.mime_msg)
283282
self.mime_msg.attach(MIMEText(self.body, "html"))
284283
try:
285284
smtp = SMTP(self.smtp_server, int(self.smtp_port))
286285
smtp.set_debuglevel(5)
287-
smtp.sendmail(send_from, send_to, self.mime_msg.as_string())
286+
smtp.sendmail(send_from, self.default_mails, self.mime_msg.as_string())
288287
except smtplib.SMTPRecipientsRefused as e:
289288
logger.error("Error sending email(SMTPRecipientsRefused): %s", e.strerror)
290289
except smtplib.SMTPException as e:
@@ -297,12 +296,13 @@ def run(self):
297296
"""
298297
Run the container EOL checker.
299298
"""
299+
logger.debug("Variables:\n%s", vars(self))
300300
logger.info("Running container EOL checker")
301301
if self.jira_fetcher.jira is None:
302302
logger.error("Connection to Jira failed")
303303
else:
304304
self.jira_fetcher.get_jira_deprecation_details()
305-
self.jira_fetcher.check_if_jira_is_filled()
305+
self.jira_fetcher.check_if_jira_is_filed()
306306
self.analyze_containers()
307307
self.body = self.summary_report()
308308
logger.info(self.body)

‎eol-checker/eol_checker/constants.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
JIRA_URL = "https://redhat.atlassian.net"
2424
OS_NAMES = ["RHEL8", "RHEL9", "RHEL10"]
25-
ALLOWED_STATUSES = ["Open", "In Progress", "To Do"]
25+
ALLOWED_STATUSES = ["New", "Open", "In Progress", "To Do"]
2626
CONTAINER_NAMES = [
2727
"nodejs",
2828
"httpd",
@@ -40,6 +40,7 @@
4040
"python39",
4141
"python311",
4242
"python312",
43+
"python314",
4344
"ruby",
4445
]
4546
JIRA_DEPRECATION_TICKET = "RHELMISC-20810"

‎eol-checker/eol_checker/custom_logger.py‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@
2525

2626

2727
class ColoredFormatter(logging.Formatter):
28+
"""
29+
Colored formatter for the logger.
30+
"""
31+
2832
COLORS = {
2933
"DEBUG": Fore.LIGHTBLUE_EX,
3034
"INFO": Fore.GREEN,
@@ -50,6 +54,14 @@ def format(self, record):
5054

5155

5256
def setup_logger(logger_name: str = "eol_checker", level=logging.INFO):
57+
"""
58+
Setup the logger.
59+
Args:
60+
logger_name: The name of the logger.
61+
level: The level of the logger.
62+
Returns:
63+
The logger.
64+
"""
5365
logger = logging.getLogger(logger_name)
5466

5567
# Check if handlers already exist (to avoid duplicate logs)

‎eol-checker/eol_checker/jira.py‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,17 +55,26 @@ def get_jira_deprecation_details(self):
5555
except HTTPError as e:
5656
logger.error("Error occurred while fetching JIRA issue: %s", e)
5757
self.jira_details = None
58+
logger.debug("JIRA details: '%s'", self.jira_details)
5859

59-
def is_jira_filled_for_container(self, stream_name: str) -> str:
60+
def is_jira_filed_for_container(self, stream_name: str) -> str:
61+
"""
62+
Check if the JIRA ticket is filled for a container.
63+
Args:
64+
stream_name: The stream name.
65+
Returns:
66+
The JIRA issue ID if the JIRA ticket is filled, empty string otherwise.
67+
"""
6068
jira_id = ""
6169
for issue in self.jira_deprecated_opened_issues:
62-
logger.info("Check is stream '%s' in issue '%s'", stream_name, issue)
70+
logger.info("Check if stream '%s' in issue '%s'", stream_name, issue)
6371
if "summary" in issue and stream_name in issue["summary"]:
6472
jira_id = issue["jira_issue_id"]
73+
logger.debug("Jira is already filed for container '%s'", stream_name)
6574
break
6675
return jira_id
6776

68-
def check_if_jira_is_filled(self) -> bool:
77+
def check_if_jira_is_filed(self) -> bool:
6978
"""
7079
Check if the JIRA ticket is filled.
7180
Returns:

‎eol-checker/eol_checker/utils.py‎

Lines changed: 20 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import logging
2424
import os
2525

26-
from typing import Any, Iterable, Dict
26+
from typing import Any, Iterable, Dict, List
2727
from datetime import date
2828

2929
from eol_checker.constants import JIRA_URL
@@ -72,7 +72,7 @@ def get_jira_ticket_url(jira_issue_id: str) -> str:
7272
return f"{JIRA_URL}/browse/{jira_issue_id}"
7373

7474

75-
def get_env_variable(var_name: str, default_value: str = "") -> str:
75+
def get_env_variable(var_name: str, default_value: str = "") -> List[str]:
7676
"""
7777
Get environment variable value or return default value if not set.
7878
:param var_name: Name of the environment variable
@@ -81,33 +81,29 @@ def get_env_variable(var_name: str, default_value: str = "") -> str:
8181
"""
8282
if var_name in os.environ:
8383
value = os.getenv(var_name, default_value)
84-
print(f"Environment variable '{var_name}': '{value}'")
85-
return value
86-
return default_value
84+
if value:
85+
return value.split(",")
86+
return []
8787

8888

8989
def load_mails_from_environment():
9090
"""
9191
Load email addresses from environment variables.
9292
"""
9393
sclorg_mails = {}
94-
sclorg_mails["mariadb"] = get_env_variable("DB_MAILS").split(",")
95-
sclorg_mails["mysql"] = get_env_variable("DB_MAILS").split(",")
96-
sclorg_mails["postgresql"] = get_env_variable("DB_MAILS").split(",")
97-
sclorg_mails["ruby"] = get_env_variable("RUBY_MAILS").split(",")
98-
python_mails = get_env_variable("PYTHON_MAILS").split(",")
99-
sclorg_mails["python"] = python_mails
100-
sclorg_mails["python36"] = python_mails
101-
sclorg_mails["python38"] = python_mails
102-
sclorg_mails["python39"] = python_mails
103-
sclorg_mails["python311"] = python_mails
104-
sclorg_mails["python312"] = python_mails
105-
sclorg_mails["nodejs"] = get_env_variable("NODEJS_MAILS").split(",")
106-
sclorg_mails["perl"] = get_env_variable("PERL_MAILS").split(",")
107-
sclorg_mails["php"] = get_env_variable("PHP_MAILS").split(",")
108-
sclorg_mails["redis"] = get_env_variable("REDIS_MAILS").split(",")
109-
sclorg_mails["varnish"] = get_env_variable("VARNISH_MAILS").split(",")
110-
sclorg_mails["valkey"] = get_env_variable("VALKEY_MAILS").split(",")
111-
sclorg_mails["httpd"] = get_env_variable("HTTPD_MAILS").split(",")
112-
sclorg_mails["nginx"] = get_env_variable("NGINX_MAILS").split(",")
94+
db_mails = get_env_variable("DB_EMAILS")
95+
sclorg_mails["mariadb"] = db_mails
96+
sclorg_mails["mysql"] = db_mails
97+
sclorg_mails["postgresql"] = db_mails
98+
sclorg_mails["ruby"] = get_env_variable("RUBY_EMAILS")
99+
sclorg_mails["python"] = get_env_variable("PYTHON_EMAILS")
100+
sclorg_mails["nodejs"] = get_env_variable("NODEJS_EMAILS")
101+
sclorg_mails["perl"] = get_env_variable("PERL_EMAILS")
102+
sclorg_mails["php"] = get_env_variable("PHP_EMAILS")
103+
sclorg_mails["redis"] = get_env_variable("REDIS_EMAILS")
104+
sclorg_mails["varnish"] = get_env_variable("VARNISH_EMAILS")
105+
sclorg_mails["valkey"] = get_env_variable("VALKEY_EMAILS")
106+
sclorg_mails["httpd"] = get_env_variable("HTTPD_EMAILS")
107+
sclorg_mails["nginx"] = get_env_variable("NGINX_EMAILS")
108+
logger.debug("SCLorg mails: '%s'", sclorg_mails)
113109
return sclorg_mails

0 commit comments

Comments
 (0)