Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/build-and-push.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ jobs:
registry_username: ${{ secrets.QUAY_IMAGE_SCLORG_BUILDER_USERNAME }}
registry_token: ${{ secrets.QUAY_IMAGE_SCLORG_BUILDER_TOKEN }}
dockerfile: Dockerfile.daily-tests
tag: "0.10.0"
tag: "0.10.1"
image_name: "upstream-daily-tests"
quay_application_token: ${{ secrets.QUAY_IMAGE_SCLORG_UPDATE_DESC }}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.mypy_cache
.idea
.venv
.vscode
__pycache__

Expand Down
5 changes: 2 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
# pre-commit install

repos:
- repo: https://github.com/ambv/black
rev: 19.3b0
- repo: https://github.com/psf/black
rev: 24.10.0
hooks:
- id: black
language_version: python3.6
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v2.2.3
hooks:
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.daily-tests
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ FROM quay.io/fedora/fedora:42

ENV SHARED_DIR="/var/ci-scripts" \
VERSION="42" \
RELEASE_UPSTREAM="0.10.0" \
RELEASE_UPSTREAM="0.10.1" \
UPSTREAM_TMT_REPO="https://github.com/sclorg/sclorg-testing-farm" \
UPSTREAM_TMT_DIR="sclorg-testing-farm" \
HOME="/home/nightly" \
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ shellcheck:
./run-shellcheck.sh `git ls-files *.sh`

build_images:
podman build -t quay.io/sclorg/upstream-daily-tests:0.10.0 -f Dockerfile.daily-tests .
podman build -t quay.io/sclorg/upstream-daily-tests:0.10.1 -f Dockerfile.daily-tests .
68 changes: 15 additions & 53 deletions eol-checker/eol_checker/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,10 @@ def check_enddate(self, lifecycle: Dict[str, Any]) -> None:
self.eol_images[self.os_name][self.container_to_analyze] = container_struct
if is_eol == 2:
eol_msg = f"Deprecation of image stream {application_stream_name} is approaching next month should be scheduled: enddate is {enddate}"
self.approaching_eol_images[self.os_name][
self.container_to_analyze
] = container_struct
self.approaching_eol_images[self.os_name][self.container_to_analyze] = container_struct
if is_eol == 3:
eol_msg = f"Deprecation of image stream {application_stream_name} already approached one month ago should be scheduled: enddate is {enddate}"
self.already_eol_images[self.os_name][
self.container_to_analyze
] = container_struct
self.already_eol_images[self.os_name][self.container_to_analyze] = container_struct
if is_eol != 0:
logger.info(eol_msg)

Expand Down Expand Up @@ -144,16 +140,9 @@ def _get_jira_msg(self, report_type: str, enddate: str) -> str:
if self.jira_fetcher.jira is None
else "Jira ticket is not filled. Use Jira issue template:"
)
return (
self.bold_line
+ f"{report_type} in {enddate}"
+ self.bold_line_end
+ f". {jira_msg}"
)
return self.bold_line + f"{report_type} in {enddate}" + self.bold_line_end + f". {jira_msg}"

def summary_for_images(
self, images: dict, os_name: str, eol_type: bool = True
) -> str:
def summary_for_images(self, images: dict, os_name: str, eol_type: bool = True) -> str:
"""
Generate a summary report for the images.
Args:
Expand All @@ -168,54 +157,33 @@ def summary_for_images(
report_type = "reached EOL" if eol_type else "approaching EOL"
report = "\n"
report += (
self.bold_line
+ f"Summary report for {os_name}:"
+ self.bold_line_end
+ self.end_line
self.bold_line + f"Summary report for {os_name}:" + self.bold_line_end + self.end_line
)
report += self.end_line + "\n"
logger.debug("EOL images: '%s'", images)
for container_name, values in images[os_name].items():
logger.info(
"Processing container: '%s' with values: '%s'", container_name, values
)
logger.info("Processing container: '%s' with values: '%s'", container_name, values)
stream_name = values["name"]
if self.send_email:
for mail in self.eol_sme_mails[container_name]:
if mail and mail not in self.default_mails:
self.default_mails.append(mail)
if self.jira_fetcher.jira is None:
logger.error("Connection to Jira failed")
jira_msg = self._get_jira_msg(
report_type=report_type, enddate=values["enddate"]
)
jira_msg = self._get_jira_msg(report_type=report_type, enddate=values["enddate"])
jira_id = self.jira_fetcher.jira_deprecation_ticket
jira_url = get_jira_ticket_url(jira_issue_id=jira_id)
url = (
f"<a href='{jira_url}'>{jira_url}</a>"
if self.send_email
else jira_url
)
url = f"<a href='{jira_url}'>{jira_url}</a>" if self.send_email else jira_url
report += f"{stream_name} for {os_name} {jira_msg} {url}{self.end_line}"
continue
jira_msg = self._get_jira_msg(
report_type=report_type, enddate=values["enddate"]
)
jira_msg = self._get_jira_msg(report_type=report_type, enddate=values["enddate"])
jira_msg += "Jira ticket is already filed:"
jira_id = self.jira_fetcher.is_jira_filled_for_container(
stream_name=stream_name
)
jira_id = self.jira_fetcher.is_jira_filled_for_container(stream_name=stream_name)
if jira_id == "":
jira_msg = self._get_jira_msg(
report_type=report_type, enddate=values["enddate"]
)
jira_msg = self._get_jira_msg(report_type=report_type, enddate=values["enddate"])
jira_id = self.jira_fetcher.jira_deprecation_ticket
jira_url = get_jira_ticket_url(jira_issue_id=jira_id)
url = (
f"<a href='{jira_url}'>{jira_url}</a>"
if self.send_email
else jira_url
)
url = f"<a href='{jira_url}'>{jira_url}</a>" if self.send_email else jira_url
report += f"{stream_name} for {os_name} {jira_msg} {url}{self.end_line}"
report += "\n"

Expand All @@ -230,13 +198,9 @@ def summary_report(self) -> str:
report = "\n"
for os_name in OS_NAMES:
if len(self.already_eol_images[os_name]) != 0:
report += self.summary_for_images(
images=self.already_eol_images, os_name=os_name
)
report += self.summary_for_images(images=self.already_eol_images, os_name=os_name)
if len(self.eol_images[os_name]) != 0:
report += self.summary_for_images(
images=self.eol_images, os_name=os_name
)
report += self.summary_for_images(images=self.eol_images, os_name=os_name)
if len(self.approaching_eol_images[os_name]) != 0:
report += self.summary_for_images(
images=self.approaching_eol_images, os_name=os_name, eol_type=False
Expand Down Expand Up @@ -266,9 +230,7 @@ def analyze_containers(self):
continue
self.lifecycle_data = YamlLoader.download_yaml(yaml_url)
if self.lifecycle_data is None:
logger.error(
"Failed to download lifecycle YAML file from '%s'", yaml_url
)
logger.error("Failed to download lifecycle YAML file from '%s'", yaml_url)
continue
self.analyze_lifecycle_yaml(self.lifecycle_data)
logger.info("Analyzing OS %s completed", self.os_name)
Expand Down
32 changes: 19 additions & 13 deletions eol-checker/eol_checker/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,17 +91,23 @@ def load_mails_from_environment():
Load email addresses from environment variables.
"""
sclorg_mails = {}
sclorg_mails["mariadb"] = get_env_variable("DB_SME").split(",")
sclorg_mails["mysql"] = get_env_variable("DB_SME").split(",")
sclorg_mails["postgresql"] = get_env_variable("DB_SME").split(",")
sclorg_mails["ruby"] = get_env_variable("RUBY_SME").split(",")
sclorg_mails["python"] = get_env_variable("PYTHON_SME").split(",")
sclorg_mails["nodejs"] = get_env_variable("NODEJS_SME").split(",")
sclorg_mails["perl"] = get_env_variable("PERL_SME").split(",")
sclorg_mails["php"] = get_env_variable("PHP_SME").split(",")
sclorg_mails["redis"] = get_env_variable("REDIS_SME").split(",")
sclorg_mails["varnish"] = get_env_variable("VARNISH_SME").split(",")
sclorg_mails["valkey"] = get_env_variable("VALKEY_SME").split(",")
sclorg_mails["httpd"] = get_env_variable("HTTPD_SME").split(",")
sclorg_mails["nginx"] = get_env_variable("NGINX_SME").split(",")
sclorg_mails["mariadb"] = get_env_variable("DB_MAILS").split(",")
sclorg_mails["mysql"] = get_env_variable("DB_MAILS").split(",")
sclorg_mails["postgresql"] = get_env_variable("DB_MAILS").split(",")
sclorg_mails["ruby"] = get_env_variable("RUBY_MAILS").split(",")
python_mails = get_env_variable("PYTHON_MAILS").split(",")
sclorg_mails["python"] = python_mails
sclorg_mails["python36"] = python_mails
sclorg_mails["python38"] = python_mails
sclorg_mails["python39"] = python_mails
sclorg_mails["python311"] = python_mails
sclorg_mails["python312"] = python_mails
sclorg_mails["nodejs"] = get_env_variable("NODEJS_MAILS").split(",")
sclorg_mails["perl"] = get_env_variable("PERL_MAILS").split(",")
sclorg_mails["php"] = get_env_variable("PHP_MAILS").split(",")
sclorg_mails["redis"] = get_env_variable("REDIS_MAILS").split(",")
sclorg_mails["varnish"] = get_env_variable("VARNISH_MAILS").split(",")
sclorg_mails["valkey"] = get_env_variable("VALKEY_MAILS").split(",")
sclorg_mails["httpd"] = get_env_variable("HTTPD_MAILS").split(",")
sclorg_mails["nginx"] = get_env_variable("NGINX_MAILS").split(",")
return sclorg_mails
40 changes: 13 additions & 27 deletions eol-checker/tests/test_checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,9 @@ def test_summary_for_images_when_jira_unavailable(checker):
def test_summary_for_images_without_jira_ticket(checker):
checker.eol_images["RHEL9"] = {"nodejs": _container_struct("nodejs-18", "20250501")}
flexmock(checker.jira_fetcher).should_receive("jira").and_return(flexmock())
flexmock(checker.jira_fetcher).should_receive(
"is_jira_filled_for_container"
).with_args(stream_name="nodejs-18").and_return("")
flexmock(checker.jira_fetcher).should_receive("is_jira_filled_for_container").with_args(
stream_name="nodejs-18"
).and_return("")

report = checker.summary_for_images(checker.eol_images, "RHEL9")

Expand Down Expand Up @@ -199,13 +199,9 @@ def test_summary_report_includes_all_eol_categories(checker):
checker.eol_images[os_name] = {}
checker.approaching_eol_images[os_name] = {}
checker.already_eol_images[os_name] = {}
checker.already_eol_images["RHEL8"] = {
"nodejs": _container_struct("nodejs-16", "20250401")
}
checker.already_eol_images["RHEL8"] = {"nodejs": _container_struct("nodejs-16", "20250401")}
checker.eol_images["RHEL9"] = {"nodejs": _container_struct("nodejs-18", "20250501")}
checker.approaching_eol_images["RHEL10"] = {
"httpd": _container_struct("httpd-26", "20250601")
}
checker.approaching_eol_images["RHEL10"] = {"httpd": _container_struct("httpd-26", "20250601")}
flexmock(checker.jira_fetcher).should_receive("jira").and_return(None)

report = checker.summary_report()
Expand Down Expand Up @@ -257,9 +253,7 @@ def test_analyze_containers_analyzes_downloaded_yaml(checker):
flexmock(checker_module.YamlLoader).should_receive("get_yaml_url").and_return(
"http://test/yaml"
)
flexmock(checker_module.YamlLoader).should_receive("download_yaml").and_return(
lifecycle_data
)
flexmock(checker_module.YamlLoader).should_receive("download_yaml").and_return(lifecycle_data)
flexmock(checker).should_receive("analyze_lifecycle_yaml").with_args(
lifecycle_data
).at_least().once()
Expand All @@ -274,16 +268,12 @@ def test_analyze_containers_populates_eol_from_yaml(checker):
flexmock(checker_module.YamlLoader).should_receive("get_yaml_url").and_return(
"http://test/yaml"
)
flexmock(checker_module.YamlLoader).should_receive("download_yaml").and_return(
lifecycle_data
)
flexmock(checker_module.YamlLoader).should_receive("download_yaml").and_return(lifecycle_data)

checker.analyze_containers()

for os_name in OS_NAMES:
assert checker.eol_images[os_name]["nodejs"] == _container_struct(
"nodejs-18", "20250501"
)
assert checker.eol_images[os_name]["nodejs"] == _container_struct("nodejs-18", "20250501")


def _mock_send_email_env():
Expand All @@ -307,9 +297,9 @@ def test_send_emails_sends_html_message(checker):
mock_smtp.should_receive("sendmail").once()
mock_smtp.should_receive("close").once()
_mock_send_email_env()
flexmock(checker_module).should_receive("SMTP").with_args(
"smtp.test", 2525
).and_return(mock_smtp)
flexmock(checker_module).should_receive("SMTP").with_args("smtp.test", 2525).and_return(
mock_smtp
)

checker.send_emails()

Expand All @@ -325,9 +315,7 @@ def test_send_emails_logs_smtp_exception(checker, caplog):
checker.body = "report"
mock_smtp = flexmock()
mock_smtp.should_receive("set_debuglevel").and_return(None)
mock_smtp.should_receive("sendmail").and_raise(
smtplib.SMTPException("smtp failure")
)
mock_smtp.should_receive("sendmail").and_raise(smtplib.SMTPException("smtp failure"))
mock_smtp.should_receive("close").once()
_mock_send_email_env()
flexmock(checker_module).should_receive("SMTP").and_return(mock_smtp)
Expand All @@ -340,9 +328,7 @@ def test_send_emails_logs_smtp_exception(checker, caplog):

def test_run_skips_jira_when_connection_unavailable(checker):
flexmock(checker.jira_fetcher).should_receive("jira").and_return(None)
flexmock(checker.jira_fetcher).should_receive(
"get_jira_deprecation_details"
).never()
flexmock(checker.jira_fetcher).should_receive("get_jira_deprecation_details").never()
flexmock(checker).should_receive("analyze_containers").once()
flexmock(checker).should_receive("summary_report").and_return("\nreport\n")
flexmock(checker).should_receive("send_emails").never()
Expand Down
5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[tool.black]
line-length = 100

[tool.ruff]
line-length = 100
2 changes: 2 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
black>=24.0.0
ruff>=0.8.0
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@ urllib3
GitPython
slack_sdk
xmltodict
colorama
atlassian-python-api
Loading