Skip to content

ci: merge Dependabot patch bumps natively instead of via the Claude caller - #344

Merged
docdyhr merged 1 commit into
mainfrom
ci/native-patch-auto-merge
Oct 21, 2026
Merged

docdyhr merged 1 commit into
mainfrom
ci/native-patch-auto-merge

Conversation

@docdyhr

@docdyhr docdyhr commented Oct 21, 2026 •

Copy link
Copy Markdown
Owner

Summary

dependabot-auto-merge.yml was a dispatch-only caller of the Claude merger in docdyhr/.github. The org is retiring those callers together with their templates. This PR replaces it with the native patch auto-merge that httpcheck and malwarespotter use, so a Dependabot patch bump merges on its own once the required checks pass. Until now it needed someone to dispatch the Claude merger with merge_mode=live.

Changes

  • .github/workflows/dependabot-auto-merge.yml is now the native workflow. On pull_request_target, when the actor is Dependabot, it reads dependabot/fetch-metadata and approves a semver-patch PR and runs gh pr merge --auto --squash on it. It never checks out PR code, and PR values reach the shell only through env:.
  • One addition over httpcheck's copy: a PR whose dependency names contain ruff is skipped. CLAUDE.md requires a ruff check --statistics comparison against main before a ruff bump merges, and ruff sits in the dev-tools group, which takes patch updates. Without the exclusion, a patch-only dev-tools PR would merge without that check.
  • CLAUDE.md: patch bumps now merge natively, except anything touching ruff. Everything else stays user-run.
  • CHANGELOG.md: an Unreleased "Changed" entry.

Verification

  • actionlint: clean. The YAML parses.
  • The main ruleset requires status checks, so --auto waits for them. "Allow auto-merge" is on for the repo.
  • pytest --maxfail=1000: 2841 passed, 16 skipped.
  • ANTHROPIC_API_KEY has no other user in this repo, so the secret can be deleted after merge.
  • Not testable before merge: pull_request_target runs the base branch's copy, so the first Dependabot patch PR after merge is the first real run.

🤖 Generated with Claude Code

Summary by Sourcery

Enable native automatic merging for eligible Dependabot patch updates while retaining manual review for ruff, minor, and major updates.

New Features:

  • Automatically approve and enable squash auto-merge for Dependabot semver-patch updates once required checks pass.

Enhancements:

  • Exclude updates touching ruff from automatic merging so the required lint-statistics comparison can be performed first.
  • Retire the dispatch-only Claude-based Dependabot merge workflow in favor of native repository automation.

Documentation:

  • Document the new native patch-bump merge behavior and ruff exception in project guidance and the changelog.

…aller

dependabot-auto-merge.yml was a dispatch-only caller of the Claude merger
in docdyhr/.github, which the org retires together with its template. It
is now the native workflow httpcheck and malwarespotter use: a Dependabot
patch bump is approved and set to auto-merge once the required checks
pass.

One addition: any PR whose dependency names contain "ruff" is skipped,
because CLAUDE.md requires a ruff check --statistics comparison against
main before a ruff bump merges, and ruff sits in the dev-tools group that
takes patch updates. CLAUDE.md and CHANGELOG.md describe the new policy.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@sourcery-ai

sourcery-ai Bot commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Sorry @docdyhr, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 2 days and 15 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Oct 21, 2026

Copy link
Copy Markdown
Contributor

Reviewer's Guide

The PR retires the organization-level Claude Dependabot merger integration and implements a native, event-driven workflow that approves and enables squash auto-merge for Dependabot semver-patch updates after required checks pass, while excluding ruff-related PRs and leaving minor, major, and other merges for manual review.

Sequence diagram for native Dependabot patch auto-merge

sequenceDiagram
    participant Dependabot
    participant GitHub
    participant Workflow
    participant Metadata as DependabotMetadata
    participant Checks as RequiredChecks

    Dependabot->>GitHub: Open or update pull request
    GitHub->>Workflow: pull_request_target
    Workflow->>Metadata: fetch-metadata
    Metadata-->>Workflow: update-type and dependency-names
    alt semver-patch and does not contain ruff
        Workflow->>GitHub: gh pr review --approve
        Workflow->>GitHub: gh pr merge --auto --squash
        GitHub->>Checks: Wait for required checks
        Checks-->>GitHub: Checks pass
        GitHub-->>Dependabot: Squash merge pull request
    else ruff, minor, or major update
        Workflow-->>Dependabot: Report skipped PR
    end
Loading

File-Level Changes

Change Details Files
Replaced the dispatch-only Claude merger caller with a native Dependabot patch auto-merge workflow.
  • Trigger on Dependabot pull request events using pull_request_target.
  • Fetch Dependabot update metadata and act only on semver-patch updates.
  • Approve eligible patches and enable squash auto-merge so required checks gate merging.
  • Pass pull request data to shell commands through environment variables without checking out PR code.
  • Skip any patch PR whose dependency names contain ruff, while reporting skipped minor, major, and excluded updates.
.github/workflows/dependabot-auto-merge.yml
Updated repository guidance to reflect the new automated merge boundary.
  • Allow native automation for patch bumps while keeping other dependency merges user-run.
  • Retain the required manual ruff statistics comparison before ruff-related merges.
CLAUDE.md
Documented the Dependabot automation change and cleanup implication.
  • Added an Unreleased changelog entry describing patch auto-merge behavior, ruff exclusions, and the unused Anthropic secret.
CHANGELOG.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-21T10:40:24.099774Z f6f57a8 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

Copy link
Copy Markdown

🔒 Security Analysis Report

Security Analysis Report

Generated: Wed Oct 21 10:38:17 UTC 2026
Repository: docdyhr/versiontracker
Commit: 5a4e0da

Bandit Security Scan

�[?25l
�[2KWorking... �[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━�[0m �[35m  0%�[0m �[36m-:--:--�[0m
�[2KWorking... �[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━�[0m �[35m  0%�[0m �[36m-:--:--�[0m
�[2KWorking... �[91m━━━━━━━━━━━�[0m�[90m╺�[0m�[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━�[0m �[35m 28%�[0m �[36m0:00:01�[0m
�[2KWorking... �[91m━━━━━━━━━━━━━━━━�[0m�[90m╺�[0m�[90m━━━━━━━━━━━━━━━━━━━━━━━�[0m �[35m 41%�[0m �[36m0:00:01�[0m
�[2KWorking... �[91m━━━━━━━━━━━━━━━━━━━━━━�[0m�[91m╸�[0m�[90m━━━━━━━━━━━━━━━━━�[0m �[35m 56%�[0m �[36m0:00:01�[0m
�[2KWorking... �[91m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━�[0m�[90m╺�[0m�[90m━━━━━━━━━━�[0m �[35m 73%�[0m �[36m0:00:01�[0m
�[2KWorking... �[91m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━�[0m�[91m╸�[0m�[90m━━━━━━�[0m �[35m 84%�[0m �[36m0:00:01�[0m
�[2KWorking... �[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━�[0m �[35m100%�[0m �[33m0:00:00�[0m
�[2KWorking... �[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━�[0m �[35m100%�[0m �[33m0:00:00�[0m
�[?25hRun started:2026-10-21 10:38:17.967359+00:00

Test results:
>> Issue: [B608:hardcoded_sql_expressions] Possible SQL injection vector through string-based query construction.
   Severity: Medium   Confidence: Low
   CWE: CWE-89 (https://cwe.mitre.org/data/definitions/89.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b608_hardcoded_sql_expressions.html
   Location: versiontracker/advanced_cache.py:693:24
692	                # Use f-string for better readability
693	                msg = f"Failed to delete from cache {key}: {e}"
694	                raise CacheError(msg) from e

--------------------------------------------------
>> Issue: [B105:hardcoded_password_string] Possible hardcoded password: 'homebrew_token'
   Severity: Low   Confidence: Medium
   CWE: CWE-259 (https://cwe.mitre.org/data/definitions/259.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b105_hardcoded_password_string.html
   Location: versiontracker/audit/models.py:161:21
160	    BUNDLE_ID = "bundle_id"
161	    HOMEBREW_TOKEN = "homebrew_token"
162	    DISPLAY_NAME = "display_name"

--------------------------------------------------
>> Issue: [B404:blacklist] Consider possible security implications associated with the subprocess module.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_imports.html#b404-import-subprocess
   Location: versiontracker/config.py:174:16
173	                cmd = f"{path} --version"
174	                import subprocess
175	

--------------------------------------------------
>> Issue: [B603:subprocess_without_shell_equals_true] subprocess call - check for execution of untrusted input.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b603_subprocess_without_shell_equals_true.html
   Location: versiontracker/config.py:177:29
176	                try:
177	                    result = subprocess.run(cmd.split(), capture_output=True, timeout=2, check=False)
178	                    returncode = result.returncode

--------------------------------------------------
>> Issue: [B110:try_except_pass] Try, Except, Pass detected.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b110_try_except_pass.html
   Location: versiontracker/experimental/analytics.py:645:16
644	                    self.peak_cpu = max(self.peak_cpu, cpu_percent)
645	                except Exception:
646	                    pass
647	                time.sleep(0.05)

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: versiontracker/handlers/outdated_handlers.py:518:8
517	        # Type assertion: apps and brews cannot be None here due to exit_code checks above
518	        assert apps is not None
519	        assert brews is not None

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: versiontracker/handlers/outdated_handlers.py:519:8
518	        assert apps is not None
519	        assert brews is not None
520	        apps = _filter_applications(apps, brews, include_brews)

--------------------------------------------------
>> Issue: [B101:assert_used] Use of assert detected. The enclosed code will be removed when compiling to optimised byte code.
   Severity: Low   Confidence: High
   CWE: CWE-703 (https://cwe.mitre.org/data/definitions/703.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b101_assert_used.html
   Location: versiontracker/handlers/outdated_handlers.py:539:8
538	        # Type assertion: outdated_info cannot be None here due to exit_code check
539	        assert outdated_info is not None
540	        # Type cast: outdated_info cannot be None here due to exit_code check above

--------------------------------------------------
>> Issue: [B404:blacklist] Consider possible security implications associated with the subprocess module.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_imports.html#b404-import-subprocess
   Location: versiontracker/homebrew.py:12:0
11	import re
12	import subprocess
13	import time

--------------------------------------------------
>> Issue: [B404:blacklist] Consider possible security implications associated with the subprocess module.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_imports.html#b404-import-subprocess
   Location: versiontracker/macos_integration.py:12:0
11	import plistlib
12	import subprocess
13	from pathlib import Path

--------------------------------------------------
>> Issue: [B404:blacklist] Consider possible security implications associated with the subprocess module.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_imports.html#b404-import-subprocess
   Location: versiontracker/menubar_app.py:8:0
7	import logging
8	import subprocess
9	import sys

--------------------------------------------------
>> Issue: [B404:blacklist] Consider possible security implications associated with the subprocess module.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_imports.html#b404-import-subprocess
   Location: versiontracker/plugins/example_plugins.py:322:16
321	            try:
322	                import subprocess
323	

--------------------------------------------------
>> Issue: [B607:start_process_with_partial_path] Starting a process with a partial executable path
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b607_start_process_with_partial_path.html
   Location: versiontracker/plugins/example_plugins.py:324:25
323	
324	                result = subprocess.run(["brew", "--version"], capture_output=True, text=True, timeout=5)
325	                if result.returncode == 0:

--------------------------------------------------
>> Issue: [B603:subprocess_without_shell_equals_true] subprocess call - check for execution of untrusted input.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b603_subprocess_without_shell_equals_true.html
   Location: versiontracker/plugins/example_plugins.py:324:25
323	
324	                result = subprocess.run(["brew", "--version"], capture_output=True, text=True, timeout=5)
325	                if result.returncode == 0:

--------------------------------------------------
>> Issue: [B404:blacklist] Consider possible security implications associated with the subprocess module.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_imports.html#b404-import-subprocess
   Location: versiontracker/utils.py:16:0
15	import shutil
16	import subprocess
17	import sys

--------------------------------------------------
>> Issue: [B607:start_process_with_partial_path] Starting a process with a partial executable path
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b607_start_process_with_partial_path.html
   Location: versiontracker/utils.py:804:17
803	    try:
804	        result = subprocess.run(["which", "brew"], capture_output=True, text=True, timeout=5)
805	        return result.returncode == 0

--------------------------------------------------
>> Issue: [B603:subprocess_without_shell_equals_true] subprocess call - check for execution of untrusted input.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b603_subprocess_without_shell_equals_true.html
   Location: versiontracker/utils.py:804:17
803	    try:
804	        result = subprocess.run(["which", "brew"], capture_output=True, text=True, timeout=5)
805	        return result.returncode == 0

--------------------------------------------------
>> Issue: [B607:start_process_with_partial_path] Starting a process with a partial executable path
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b607_start_process_with_partial_path.html
   Location: versiontracker/utils.py:820:17
819	    try:
820	        result = subprocess.run(["brew", "--prefix"], capture_output=True, text=True, timeout=5)
821	        if result.returncode == 0:

--------------------------------------------------
>> Issue: [B603:subprocess_without_shell_equals_true] subprocess call - check for execution of untrusted input.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b603_subprocess_without_shell_equals_true.html
   Location: versiontracker/utils.py:820:17
819	    try:
820	        result = subprocess.run(["brew", "--prefix"], capture_output=True, text=True, timeout=5)
821	        if result.returncode == 0:

--------------------------------------------------
>> Issue: [B603:subprocess_without_shell_equals_true] subprocess call - check for execution of untrusted input.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/plugins/b603_subprocess_without_shell_equals_true.html
   Location: versiontracker/utils.py:853:15
852	    try:
853	        return subprocess.run(command, capture_output=True, text=True, timeout=timeout, check=check)
854	    except subprocess.TimeoutExpired as e:

--------------------------------------------------
>> Issue: [B404:blacklist] Consider possible security implications associated with the subprocess module.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_imports.html#b404-import-subprocess
   Location: versiontracker/version/batch.py:11:0
10	import logging
11	import subprocess
12	from concurrent.futures import ThreadPoolExecutor

--------------------------------------------------
>> Issue: [B404:blacklist] Consider possible security implications associated with the subprocess module.
   Severity: Low   Confidence: High
   CWE: CWE-78 (https://cwe.mitre.org/data/definitions/78.html)
   More Info: https://bandit.readthedocs.io/en/1.9.4/blacklists/blacklist_imports.html#b404-import-subprocess
   Location: versiontracker/version/homebrew.py:18:0
17	import logging
18	import subprocess
19	

--------------------------------------------------

Code scanned:
	Total lines of code: 17221
	Total lines skipped (#nosec): 0
	Total potential issues skipped due to specifically being disabled (e.g., #nosec BXXX): 30

Run metrics:
	Total issues (by severity):
		Undefined: 0
		Low: 21
		Medium: 1
		High: 0
	Total issues (by confidence):
		Undefined: 0
		Low: 1
		Medium: 1
		High: 20
Files skipped (0):

Pip-Audit Results

�[?25l�[32m-�[0m Collecting inputs
�[2K�[32m-�[0m Collecting inputs
�[2K�[32m-�[0m Collecting inputs
�[2K�[32m-�[0m Collecting inputs
�[2K�[32m\�[0m Collecting aiohappyeyeballs (2.7.1)
�[2K�[32m\�[0m Collecting aiohappyeyeballs (2.7.1)
�[2K�[32m\�[0m Auditing aiohappyeyeballs (2.7.1)
�[2K�[32m\�[0m Collecting aiohttp (3.14.5)
�[2K�[32m\�[0m Auditing aiohttp (3.14.5)
�[2K�[32m\�[0m Collecting aiosignal (1.4.0)
�[2K�[32m\�[0m Auditing aiosignal (1.4.0)
�[2K�[32m\�[0m Collecting ast_serialize (0.13.1)
�[2K�[32m\�[0m Auditing ast_serialize (0.13.1)
�[2K�[32m\�[0m Collecting attrs (26.1.0)
�[2K�[32m\�[0m Auditing attrs (26.1.0)
�[2K�[32m\�[0m Collecting bandit (1.9.4)
�[2K�[32m\�[0m Auditing bandit (1.9.4)
�[2K�[32m\�[0m Collecting boolean.py (5.0)
�[2K�[32m\�[0m Auditing boolean.py (5.0)
�[2K�[32m\�[0m Collecting build (1.6.1)
�[2K�[32m\�[0m Auditing build (1.6.1)
�[2K�[32m\�[0m Collecting CacheControl (0.14.4)
�[2K�[32m\�[0m Auditing CacheControl (0.14.4)
�[2K�[32m\�[0m Collecting certifi (2026.10.19)
�[2K�[32m\�[0m Auditing certifi (2026.10.19)
�[2K�[32m\�[0m Collecting cffi (2.1.1)
�[2K�[32m\�[0m Auditing cffi (2.1.1)
�[2K�[32m\�[0m Collecting charset-normalizer (3.5.2)
�[2K�[32m\�[0m Auditing charset-normalizer (3.5.2)
�[2K�[32m\�[0m Collecting coverage (7.16.2)
�[2K�[32m\�[0m Auditing coverage (7.16.2)
�[2K�[32m\�[0m Collecting cryptography (50.0.2)
�[2K�[32m\�[0m Auditing cryptography (50.0.2)
�[2K�[32m\�[0m Collecting cyclonedx-python-lib (11.12.0)
�[2K�[32m\�[0m Auditing cyclonedx-python-lib (11.12.0)
�[2K�[32m\�[0m Collecting defusedxml (0.7.1)
�[2K�[32m\�[0m Auditing defusedxml (0.7.1)
�[2K�[32m\�[0m Collecting docutils (0.23)
�[2K�[32m\�[0m Auditing docutils (0.23)
�[2K�[32m\�[0m Collecting filelock (4.2.4)
�[2K�[32m\�[0m Auditing filelock (4.2.4)
�[2K�[32m\�[0m Collecting frozenlist (1.8.0)
�[2K�[32m\�[0m Auditing frozenlist (1.8.0)
�[2K�[32m\�[0m Collecting id (1.6.1)
�[2K�[32m\�[0m Auditing id (1.6.1)
�[2K�[32m\�[0m Collecting idna (3.20)
�[2K�[32m\�[0m Auditing idna (3.20)
�[2K�[32m\�[0m Collecting iniconfig (2.3.1)
�[2K�[32m\�[0m Auditing iniconfig (2.3.1)
�[2K�[32m\�[0m Collecting jaraco.classes (3.4.0)
�[2K�[32m\�[0m Auditing jaraco.classes (3.4.0)
�[2K�[32m\�[0m Collecting jaraco.context (6.1.2)
�[2K�[32m\�[0m Auditing jaraco.context (6.1.2)
�[2K�[32m\�[0m Collecting jaraco.functools (4.6.0)
�[2K�[32m\�[0m Auditing jaraco.functools (4.6.0)
�[2K�[32m\�[0m Collecting jeepney (0.9.0)
�[2K�[32m\�[0m Auditing jeepney (0.9.0)
�[2K�[32m\�[0m Collecting keyring (25.7.0)
�[2K�[32m\�[0m Auditing keyring (25.7.0)
�[2K�[32m\�[0m Collecting librt (0.16.0)
�[2K�[32m\�[0m Auditing librt (0.16.0)
�[2K�[32m\�[0m Collecting license-expression (30.4.4)
�[2K�[32m\�[0m Auditing license-expression (30.4.4)
�[2K�[32m\�[0m Collecting macversiontracker (1.2.0)
�[2K�[32m\�[0m Auditing macversiontracker (1.2.0)
�[2K�[32m\�[0m Collecting markdown-it-py (4.2.0)
�[2K�[32m\�[0m Auditing markdown-it-py (4.2.0)
�[2K�[32m\�[0m Collecting mdurl (0.1.2)
�[2K�[32m\�[0m Auditing mdurl (0.1.2)
�[2K�[32m\�[0m Collecting more-itertools (11.2.1)
�[2K�[32m\�[0m Auditing more-itertools (11.2.1)
�[2K�[32m\�[0m Collecting msgpack (1.2.3)
�[2K�[32m\�[0m Auditing msgpack (1.2.3)
�[2K�[32m\�[0m Collecting multidict (7.1.0)
�[2K�[32m\�[0m Auditing multidict (7.1.0)
�[2K�[32m\�[0m Collecting mypy (2.4.0)
�[2K�[32m\�[0m Auditing mypy (2.4.0)
�[2K�[32m\�[0m Collecting mypy_extensions (1.1.0)
�[2K�[32m\�[0m Auditing mypy_extensions (1.1.0)
�[2K�[32m\�[0m Collecting nh3 (0.3.7)
�[2K�[32m\�[0m Auditing nh3 (0.3.7)
�[2K�[32m\�[0m Collecting packageurl-python (0.17.6)
�[2K�[32m\�[0m Auditing packageurl-python (0.17.6)
�[2K�[32m\�[0m Collecting packaging (26.3)
�[2K�[32m\�[0m Auditing packaging (26.3)
�[2K�[32m\�[0m Collecting pathspec (1.1.1)
�[2K�[32m\�[0m Collecting pathspec (1.1.1)
�[2K�[32m\�[0m Auditing pathspec (1.1.1)
�[2K�[32m\�[0m Collecting pip (26.2.2)
�[2K�[32m\�[0m Auditing pip (26.2.2)
�[2K�[32m\�[0m Collecting pip_api (0.0.35)
�[2K�[32m\�[0m Auditing pip_api (0.0.35)
�[2K�[32m\�[0m Collecting pip_audit (2.10.1)
�[2K�[32m\�[0m Auditing pip_audit (2.10.1)
�[2K�[32m\�[0m Collecting pip-requirements-parser (32.0.1)
�[2K�[32m\�[0m Auditing pip-requirements-parser (32.0.1)
�[2K�[32m\�[0m Collecting platformdirs (4.13.5)
�[2K�[32m\�[0m Auditing platformdirs (4.13.5)
�[2K�[32m\�[0m Collecting pluggy (1.7.0)
�[2K�[32m\�[0m Auditing pluggy (1.7.0)
�[2K�[32m\�[0m Collecting propcache (0.5.4)
�[2K�[32m\�[0m Auditing propcache (0.5.4)
�[2K�[32m\�[0m Collecting psutil (7.2.2)
�[2K�[32m\�[0m Auditing psutil (7.2.2)
�[2K�[32m\�[0m Collecting py-serializable (2.1.0)
�[2K�[32m\�[0m Auditing py-serializable (2.1.0)
�[2K�[32m\�[0m Collecting pycparser (3.11)
�[2K�[32m\�[0m Auditing pycparser (3.11)
�[2K�[32m\�[0m Collecting Pygments (2.21.0)
�[2K�[32m\�[0m Auditing Pygments (2.21.0)
�[2K�[32m\�[0m Collecting pyparsing (3.3.3)
�[2K�[32m\�[0m Auditing pyparsing (3.3.3)
�[2K�[32m\�[0m Collecting pyproject_hooks (1.3.3)
�[2K�[32m\�[0m Auditing pyproject_hooks (1.3.3)
�[2K�[32m\�[0m Collecting pytest (9.1.1)
�[2K�[32m\�[0m Auditing pytest (9.1.1)
�[2K�[32m\�[0m Collecting pytest-asyncio (1.4.0)
�[2K�[32m\�[0m Auditing pytest-asyncio (1.4.0)
�[2K�[32m\�[0m Collecting pytest-cov (7.1.0)
�[2K�[32m\�[0m Auditing pytest-cov (7.1.0)
�[2K�[32m\�[0m Collecting pytest-mock (3.17.0)
�[2K�[32m\�[0m Auditing pytest-mock (3.17.0)
�[2K�[32m\�[0m Collecting pytest-timeout (2.4.0)
�[2K�[32m\�[0m Auditing pytest-timeout (2.4.0)
�[2K�[32m\�[0m Collecting PyYAML (6.0.3)
�[2K�[32m\�[0m Auditing PyYAML (6.0.3)
�[2K�[32m\�[0m Collecting readme_renderer (46.0)
�[2K�[32m\�[0m Auditing readme_renderer (46.0)
�[2K�[32m\�[0m Collecting requests (2.34.2)
�[2K�[32m\�[0m Auditing requests (2.34.2)
�[2K�[32m\�[0m Collecting requests-toolbelt (1.0.0)
�[2K�[32m\�[0m Auditing requests-toolbelt (1.0.0)
�[2K�[32m\�[0m Collecting rfc3986 (2.0.0)
�[2K�[32m\�[0m Auditing rfc3986 (2.0.0)
�[2K�[32m\�[0m Collecting rich (15.0.0)
�[2K�[32m\�[0m Auditing rich (15.0.0)
�[2K�[32m\�[0m Collecting ruff (0.17.0)
�[2K�[32m\�[0m Auditing ruff (0.17.0)
�[2K�[32m\�[0m Collecting SecretStorage (3.5.0)
�[2K�[32m\�[0m Auditing SecretStorage (3.5.0)
�[2K�[32m\�[0m Collecting setuptools (84.2.1)
�[2K�[32m\�[0m Auditing setuptools (84.2.1)
�[2K�[32m\�[0m Collecting sortedcontainers (2.4.0)
�[2K�[32m\�[0m Auditing sortedcontainers (2.4.0)
�[2K�[32m\�[0m Collecting stevedore (5.9.1)
�[2K�[32m\�[0m Auditing stevedore (5.9.1)
�[2K�[32m\�[0m Collecting tabulate (0.10.0)
�[2K�[32m\�[0m Auditing tabulate (0.10.0)
�[2K�[32m\�[0m Collecting termcolor (3.3.0)
�[2K�[32m\�[0m Auditing termcolor (3.3.0)
�[2K�[32m\�[0m Collecting tomli (2.5.0)
�[2K�[32m\�[0m Auditing tomli (2.5.0)
�[2K�[32m\�[0m Collecting tomli_w (1.2.0)
�[2K�[32m\�[0m Auditing tomli_w (1.2.0)
�[2K�[32m\�[0m Collecting tqdm (4.70.1)
�[2K�[32m\�[0m Auditing tqdm (4.70.1)
�[2K�[32m\�[0m Collecting twine (7.0.0)
�[2K�[32m\�[0m Auditing twine (7.0.0)
�[2K�[32m\�[0m Collecting types-PyYAML (6.0.12.20260906)
�[2K�[32m\�[0m Auditing types-PyYAML (6.0.12.20260906)
�[2K�[32m\�[0m Collecting typing_extensions (4.16.0)
�[2K�[32m\�[0m Auditing typing_extensions (4.16.0)
�[2K�[32m\�[0m Collecting urllib3 (2.8.0)
�[2K�[32m\�[0m Auditing urllib3 (2.8.0)
�[2K�[32m\�[0m Collecting wheel (0.48.0)
�[2K�[32m\�[0m Auditing wheel (0.48.0)
�[2K�[32m\�[0m Collecting yarl (1.25.1)
�[2K�[32m\�[0m Auditing yarl (1.25.1)
�[2K�[32m\�[0m Auditing yarl (1.25.1)
�[?25h
�[1A�[2K```

@codecov

codecov Bot commented Oct 21, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@docdyhr
docdyhr merged commit e407f1c into main Oct 21, 2026
25 checks passed
@docdyhr
docdyhr deleted the ci/native-patch-auto-merge branch October 21, 2026 15:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant