From 8215651903e73c0626f495dbb81845ba8d3aa634 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 8 Oct 2026 21:39:36 +0000 Subject: [PATCH 1/2] chore(deps): bump super-linter/super-linter from 8.7.0 to 9.0.0 Bumps [super-linter/super-linter](https://github.com/super-linter/super-linter) from 8.7.0 to 9.0.0. - [Release notes](https://github.com/super-linter/super-linter/releases) - [Changelog](https://github.com/super-linter/super-linter/blob/main/CHANGELOG.md) - [Commits](https://github.com/super-linter/super-linter/compare/4ce20838b8ab83717e78138c5b3a1407148e0918...2da136927bd4a73596db63044b504547c62cb854) --- updated-dependencies: - dependency-name: super-linter/super-linter dependency-version: 9.0.0 dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/super-linter.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/super-linter.yaml b/.github/workflows/super-linter.yaml index 97df767..a01db26 100644 --- a/.github/workflows/super-linter.yaml +++ b/.github/workflows/super-linter.yaml @@ -41,7 +41,7 @@ jobs: run: | uv sync --frozen - name: Lint Code Base - uses: super-linter/super-linter@4ce20838b8ab83717e78138c5b3a1407148e0918 # v8.7.0 + uses: super-linter/super-linter@2da136927bd4a73596db63044b504547c62cb854 # v9.0.0 env: DEFAULT_BRANCH: main GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} From 83887a88aafc19eb49286dbb066fe6c5b413171d Mon Sep 17 00:00:00 2001 From: jmeridth Date: Thu, 8 Oct 2026 21:35:28 -0500 Subject: [PATCH 2/2] fix(lint): satisfy hadolint 2.15 and ruff 0.16 from super-linter v9 ## What/Why super-linter v9 ships ruff 0.16.8 and hadolint 2.15.1, which flag 21 ruff and 1 hadolint violation. This fixes the rule hits and teaches isort our first-party modules so it agrees with ruff on import order. ## Proof it works ruff 0.16.8 (super-linter template config), hadolint 2.15.1, and make lint (flake8, isort, pylint 10.00, mypy, black) all pass locally. make test: 182 passed, 100% coverage. ## Risk Low. Import reordering, lint suppressions, and behavior-preserving rewrites. Date comparison now uses UTC-aware datetimes with identical wall-clock semantics. ## AI role Generated by Claude Opus 5.5 (ruff --fix plus manual fixes); human review pending. ## Review focus - TRY004 suppressed with noqa because callers catch ValueError only - known_first_party list in .isort.cfg must be kept in sync with new modules Signed-off-by: jmeridth --- .github/linters/.isort.cfg | 3 ++- Dockerfile | 2 +- auth.py | 3 ++- dependabot_file.py | 11 ++++++++--- env.py | 4 ++-- evergreen.py | 33 ++++++++++++++++++--------------- test_auth.py | 3 ++- test_cooldown.py | 3 ++- test_dependabot_file.py | 5 +++-- test_evergreen.py | 3 ++- test_exceptions.py | 9 +++++---- 11 files changed, 47 insertions(+), 32 deletions(-) diff --git a/.github/linters/.isort.cfg b/.github/linters/.isort.cfg index c76db01..81e7324 100644 --- a/.github/linters/.isort.cfg +++ b/.github/linters/.isort.cfg @@ -1,2 +1,3 @@ -[isort] +[settings] profile = black +known_first_party = auth,dependabot_file,env,evergreen,exceptions diff --git a/Dockerfile b/Dockerfile index 13def6c..255d6e7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,7 +16,7 @@ RUN uv sync --frozen --no-dev --no-editable \ # Add a simple healthcheck to satisfy container scanners HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \ - CMD python3 -c "import os,sys; sys.exit(0 if os.path.exists('/action/workspace/evergreen.py') else 1)" + CMD ["python3", "-c", "import os,sys; sys.exit(0 if os.path.exists('/action/workspace/evergreen.py') else 1)"] ENV PYTHONUNBUFFERED=1 ENV UV_LINK_MODE=copy diff --git a/auth.py b/auth.py index c3daf5d..6c5ba34 100644 --- a/auth.py +++ b/auth.py @@ -1,8 +1,9 @@ """This is the module that contains functions related to authenticating to GitHub with a personal access token.""" -import env from github import Auth, Github, GithubException, GithubIntegration +import env + def auth_to_github( token: str, diff --git a/dependabot_file.py b/dependabot_file.py index 8e8c814..5b16379 100644 --- a/dependabot_file.py +++ b/dependabot_file.py @@ -6,10 +6,11 @@ from collections.abc import Mapping import ruamel.yaml -from exceptions import OptionalFileNotFoundError, check_optional_file from github import UnknownObjectException from ruamel.yaml.scalarstring import SingleQuotedScalarString +from exceptions import OptionalFileNotFoundError, check_optional_file + # Define data structure for dependabot.yaml data = { "version": 2, @@ -67,7 +68,9 @@ def validate_cooldown_config(cooldown): ValueError: if the cooldown configuration is invalid """ if not isinstance(cooldown, Mapping): - raise ValueError("Cooldown configuration must be a mapping") + raise ValueError( # noqa: TRY004 - callers catch ValueError + "Cooldown configuration must be a mapping" + ) unknown_keys = set(cooldown.keys()) - VALID_COOLDOWN_KEYS if unknown_keys: @@ -109,7 +112,9 @@ def validate_cooldown_config(cooldown): ) for item in items: if not isinstance(item, str): - raise ValueError(f"Cooldown '{list_key}' items must be strings") + raise ValueError( # noqa: TRY004 - callers catch ValueError + f"Cooldown '{list_key}' items must be strings" + ) def make_dependabot_config( diff --git a/env.py b/env.py index 7d1a8ab..d71b45d 100644 --- a/env.py +++ b/env.py @@ -276,7 +276,7 @@ def get_env_vars( "Here's an example of the code:" ), } - body = body = default_bodies[follow_up_type] + body = default_bodies[follow_up_type] commit_message = os.getenv("COMMIT_MESSAGE") if commit_message: @@ -313,7 +313,7 @@ def get_env_vars( "FILTER_VISIBILITY environment variable not 'public', 'private', or 'internal'" ) filter_visibility_set.add(visibility.strip().lower()) - filter_visibility_list = sorted(list(filter_visibility_set)) + filter_visibility_list = sorted(filter_visibility_set) else: filter_visibility_list = sorted(["public", "private", "internal"]) # all diff --git a/evergreen.py b/evergreen.py index 200d374..64fd83d 100644 --- a/evergreen.py +++ b/evergreen.py @@ -3,15 +3,16 @@ import io import sys import uuid -from datetime import datetime +from datetime import datetime, timezone -import auth -import env import requests import ruamel.yaml +from github import UnknownObjectException + +import auth +import env from dependabot_file import build_dependabot_file, validate_cooldown_config from exceptions import OptionalFileNotFoundError, check_optional_file -from github import UnknownObjectException def main(): # pragma: no cover @@ -211,13 +212,15 @@ def main(): # pragma: no cover continue # Get dependabot security updates enabled if possible - if config.enable_security_updates: - if not is_dependabot_security_updates_enabled( + if ( + config.enable_security_updates + and not is_dependabot_security_updates_enabled( + config.ghe, config.ghe_api_url, repo.owner.login, repo.name, token + ) + ): + enable_dependabot_security_updates( config.ghe, config.ghe_api_url, repo.owner.login, repo.name, token - ): - enable_dependabot_security_updates( - config.ghe, config.ghe_api_url, repo.owner.login, repo.name, token - ) + ) if config.follow_up_type == "issue": skip = check_pending_issues_for_duplicates(config.title, repo) @@ -294,8 +297,8 @@ def main(): # pragma: no cover print("\tFailed to create pull request. Check write permissions.") continue - print(f"Done. {str(count_eligible)} repositories were eligible.") - print(f"{str(count_prs_created)} pull requests were created.") + print(f"Done. {count_eligible!s} repositories were eligible.") + print(f"{count_prs_created!s} pull requests were created.") # Append the summary content to the GitHub step summary file append_to_github_summary(summary_content) @@ -305,14 +308,14 @@ def is_repo_created_date_before( ): """Check if the repository was created before the created_after_date""" if isinstance(repo_created_at, datetime): - repo_created_at_date = repo_created_at.replace(tzinfo=None) + repo_created_at_date = repo_created_at.replace(tzinfo=timezone.utc) else: repo_created_at_date = datetime.fromisoformat(repo_created_at).replace( - tzinfo=None + tzinfo=timezone.utc ) return created_after_date and repo_created_at_date < datetime.strptime( created_after_date, "%Y-%m-%d" - ) + ).replace(tzinfo=timezone.utc) def is_dependabot_security_updates_enabled(ghe, ghe_api_url, owner, repo, access_token): diff --git a/test_auth.py b/test_auth.py index 4393bf4..b16a381 100644 --- a/test_auth.py +++ b/test_auth.py @@ -3,9 +3,10 @@ import unittest from unittest.mock import MagicMock, patch -import auth from github import GithubException +import auth + class TestAuth(unittest.TestCase): """ diff --git a/test_cooldown.py b/test_cooldown.py index 30b7a57..b560561 100644 --- a/test_cooldown.py +++ b/test_cooldown.py @@ -2,9 +2,10 @@ import unittest -from dependabot_file import validate_cooldown_config from ruamel.yaml import YAML +from dependabot_file import validate_cooldown_config + class TestValidateCooldownConfig(unittest.TestCase): """Test the validate_cooldown_config function.""" diff --git a/test_dependabot_file.py b/test_dependabot_file.py index f3f5285..b971ea5 100644 --- a/test_dependabot_file.py +++ b/test_dependabot_file.py @@ -7,9 +7,10 @@ from unittest.mock import MagicMock, patch import ruamel.yaml -from dependabot_file import add_existing_ecosystem_to_exempt_list, build_dependabot_file from github import UnknownObjectException +from dependabot_file import add_existing_ecosystem_to_exempt_list, build_dependabot_file + yaml = ruamel.yaml.YAML() @@ -492,7 +493,7 @@ def test_build_dependabot_file_with_terraform_without_files(self): repo = MagicMock() # Test absence of Terraform files - repo.get_contents.side_effect = lambda path: [] if path == "/" else [] + repo.get_contents.side_effect = lambda path: [] result = build_dependabot_file( repo, False, [], {}, None, "weekly", "", [], None ) diff --git a/test_evergreen.py b/test_evergreen.py index 93342ff..9781d40 100644 --- a/test_evergreen.py +++ b/test_evergreen.py @@ -7,6 +7,8 @@ from unittest.mock import MagicMock, patch import requests +from github import UnknownObjectException + from evergreen import ( append_to_github_summary, check_existing_config, @@ -22,7 +24,6 @@ is_repo_created_date_before, link_item_to_project, ) -from github import UnknownObjectException class TestDependabotSecurityUpdates(unittest.TestCase): diff --git a/test_exceptions.py b/test_exceptions.py index 709fd9d..7400fcb 100644 --- a/test_exceptions.py +++ b/test_exceptions.py @@ -3,9 +3,10 @@ import unittest from unittest.mock import Mock -from exceptions import OptionalFileNotFoundError, check_optional_file from github import UnknownObjectException +from exceptions import OptionalFileNotFoundError, check_optional_file + class TestOptionalFileNotFoundError(unittest.TestCase): """Test the OptionalFileNotFoundError exception.""" @@ -31,7 +32,7 @@ def test_can_catch_as_unknown_object_exception(self): raise OptionalFileNotFoundError(status=404, data="Not Found") except UnknownObjectException as e: self.assertIsInstance(e, OptionalFileNotFoundError) - except Exception: # pylint: disable=broad-exception-caught + except Exception: # noqa: BLE001 # pylint: disable=broad-exception-caught self.fail( "OptionalFileNotFoundError should be catchable as UnknownObjectException" ) @@ -42,7 +43,7 @@ def test_can_catch_specifically(self): raise OptionalFileNotFoundError(status=404, data="Not Found") except OptionalFileNotFoundError as e: self.assertIsInstance(e, OptionalFileNotFoundError) - except Exception: # pylint: disable=broad-exception-caught + except Exception: # noqa: BLE001 # pylint: disable=broad-exception-caught self.fail("OptionalFileNotFoundError should be catchable specifically") def test_optional_file_not_found_error_properties(self): @@ -106,7 +107,7 @@ def test_check_optional_file_can_catch_as_unknown_object_exception(self): check_optional_file(mock_repo, "missing.yml") except UnknownObjectException as e: self.assertIsInstance(e, OptionalFileNotFoundError) - except Exception: # pylint: disable=broad-exception-caught + except Exception: # noqa: BLE001 # pylint: disable=broad-exception-caught self.fail( "Should be able to catch OptionalFileNotFoundError as UnknownObjectException" )