diff --git a/.github/workflows/build-and-push.yml b/.github/workflows/build-and-push.yml
index fb94e2d..8b4f249 100644
--- a/.github/workflows/build-and-push.yml
+++ b/.github/workflows/build-and-push.yml
@@ -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 }}
diff --git a/.gitignore b/.gitignore
index db18d27..26b0ca8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
.mypy_cache
.idea
+.venv
.vscode
__pycache__
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 93e89e3..7794a31 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -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:
diff --git a/Dockerfile.daily-tests b/Dockerfile.daily-tests
index 2a70a4e..2ca117c 100644
--- a/Dockerfile.daily-tests
+++ b/Dockerfile.daily-tests
@@ -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" \
diff --git a/Makefile b/Makefile
index c6674d0..fc23f06 100644
--- a/Makefile
+++ b/Makefile
@@ -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 .
diff --git a/eol-checker/eol_checker/checker.py b/eol-checker/eol_checker/checker.py
index 7d69a21..773e62a 100755
--- a/eol-checker/eol_checker/checker.py
+++ b/eol-checker/eol_checker/checker.py
@@ -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)
@@ -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:
@@ -168,17 +157,12 @@ 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]:
@@ -186,36 +170,20 @@ def summary_for_images(
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"{jira_url}"
- if self.send_email
- else jira_url
- )
+ url = f"{jira_url}" 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"{jira_url}"
- if self.send_email
- else jira_url
- )
+ url = f"{jira_url}" if self.send_email else jira_url
report += f"{stream_name} for {os_name} {jira_msg} {url}{self.end_line}"
report += "\n"
@@ -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
@@ -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)
diff --git a/eol-checker/eol_checker/utils.py b/eol-checker/eol_checker/utils.py
index 583cc56..aa590c5 100644
--- a/eol-checker/eol_checker/utils.py
+++ b/eol-checker/eol_checker/utils.py
@@ -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
diff --git a/eol-checker/tests/test_checker.py b/eol-checker/tests/test_checker.py
index c3c52df..e13f73b 100644
--- a/eol-checker/tests/test_checker.py
+++ b/eol-checker/tests/test_checker.py
@@ -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")
@@ -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()
@@ -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()
@@ -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():
@@ -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()
@@ -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)
@@ -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()
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..f933397
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,5 @@
+[tool.black]
+line-length = 100
+
+[tool.ruff]
+line-length = 100
diff --git a/requirements-dev.txt b/requirements-dev.txt
new file mode 100644
index 0000000..d121e11
--- /dev/null
+++ b/requirements-dev.txt
@@ -0,0 +1,2 @@
+black>=24.0.0
+ruff>=0.8.0
diff --git a/requirements.txt b/requirements.txt
index e66fbf4..c3b06df 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -4,3 +4,5 @@ urllib3
GitPython
slack_sdk
xmltodict
+colorama
+atlassian-python-api