Skip to content

Conversation

@myakove
Copy link
Collaborator

@myakove myakove commented Nov 14, 2025

Add instance variable caching for repository private status and branch
required status checks to avoid repeated API calls within same webhook event.

  • Cache self._repository_private to avoid repeated repository.private checks
  • Cache self._branch_required_status_checks for branch protection settings
  • Saves ~1,300 API calls (1.4% reduction) by eliminating redundant
    get_branch() and get_protection() calls

Closes: Task 1 of API reduction project (Archon: dd076ce5-ab33-45d5-bae2-b3df839a1080)

Summary by CodeRabbit

  • Performance Improvements

    • Faster processing via shared base checkouts, lightweight worktrees, and cached repo/branch checks; OWNERS discovery now reads local files.
  • New Features

    • Added repository checkout/worktree flow with optional repo cloning and configurable secret-masking for command output; local filesystem OWNERS support and a reusable worktree helper.
  • Bug Fixes / Reliability

    • Improved error reporting, safer cleanup paths, guarded checkout/clone flows, and better redaction for registry/git interactions.
  • Tests

    • Expanded coverage for clone/checkout/worktree flows, parallel PR handling, OWNERS-from-disk cases, and related failure scenarios.

Add instance variable caching for repository private status and branch
required status checks to avoid repeated API calls within same webhook event.

- Cache self._repository_private to avoid repeated repository.private checks
- Cache self._branch_required_status_checks for branch protection settings
- Saves ~1,300 API calls (1.4% reduction) by eliminating redundant
  get_branch() and get_protection() calls

Closes: Task 1 of API reduction project (Archon: dd076ce5-ab33-45d5-bae2-b3df839a1080)
…e processing

Add automatic repository cloning for PR webhook events to enable reading
OWNERS files and changed files from local filesystem instead of GitHub API.

- Add _clone_repository_for_pr() method that clones repo and checks out base branch
- Add _repo_cloned boolean flag and cloned_repo_path string to track clone status
- Call clone method in process() after getting last_commit for all PR events
- Import run_command helper for git operations
- Clone to {clone_repo_dir}/repo for isolation from handler-specific clones
- Enables Tasks 3 and 4 to save ~1,280-2,080 API calls

This is infrastructure for OWNERS file local reading and git diff for changed
files, which will replace expensive GitHub API tree traversal operations.

Closes: Task 2 of API reduction project (Archon: 8f94afaf-8281-47c5-abc8-55c6f633a7c1)
Refactored repository cloning to use a single clone per webhook with
git worktrees for isolated checkouts. This eliminates ~80% of clone
operations and enables significant API call reduction.

Key changes:
- Clone repository once to clone_repo_dir (no /repo subdirectory)
- All handlers reuse single clone via git worktrees
- Created git_worktree_checkout() utility for reusable worktree logic
- Renamed _prepare_cloned_repo_dir() to _checkout_worktree()
- Fixed clone failure handling to abort webhook on error
- Updated all 6 callsites to use new worktree-based approach

Performance impact:
- Eliminates 3-5 clones per webhook → 1 clone
- Enables ~1,280-2,080 API call savings (OWNERS + changed files)
- Faster processing with isolated worktrees vs full clones
Update all test mocks and assertions to use renamed function:
- Renamed: _prepare_cloned_repo_dir → _checkout_worktree
- Updated return signature: 3-tuple → 4-tuple (added worktree_path)
- Fixed 38 failing tests across 3 test files

Files changed:
- webhook_server/tests/test_runner_handler.py
- webhook_server/tests/test_push_handler.py
- webhook_server/tests/test_github_api.py

All 146 tests now passing.
Add 6 comprehensive tests for _clone_repository_for_pr:
- test_clone_repository_for_pr_success: happy path
- test_clone_repository_for_pr_already_cloned: early return
- test_clone_repository_for_pr_clone_failure: RuntimeError on clone fail
- test_clone_repository_for_pr_checkout_failure: RuntimeError on checkout fail
- test_clone_repository_for_pr_git_config_warnings: non-critical failures
- test_clone_repository_for_pr_general_exception: exception handling

Coverage improvements:
- webhook_server/libs/github_api.py: 79% → 90%
- Overall coverage: 89.26% → 90.21%
- Tests passing: 904/904
Fixed 5 failing tests by correcting async property mocking patterns:
- Replaced AsyncMock instances with proper async functions for async properties
- Fixed RuntimeWarnings in test_process_new_or_reprocess_pull_request_parallel_execution
- Fixed RuntimeWarnings in test_process_new_or_reprocess_pull_request_exception_handling
- Mocked asyncio.to_thread to avoid threading complexity in tests
- Used proper async function mocks instead of AsyncMock for async cached properties

All 904 tests now pass with 90.21% coverage.
@coderabbitai
Copy link

coderabbitai bot commented Nov 14, 2025

Walkthrough

Adds a shared repository clone/worktree flow with secret redaction, introduces git_worktree_checkout, moves OWNERS discovery to local filesystem reads from a checked-out worktree, adds branch/privacy caching, and updates handlers and tests to use worktree-based checkouts and propagated stdout/stderr.

Changes

Cohort / File(s) Summary
Github API / cloning
webhook_server/libs/github_api.py
Adds self._repo_cloned: bool and self.mask_sensitive; new async _clone_repository(self, pull_request=None, checkout_ref=None) that prepares a shared clone, configures git, fetches PR refs, determines checkout target, checks out refs, redacts secrets in command output, and is invoked before push/PR processing.
Worktree helper
webhook_server/utils/helpers.py
Adds git_worktree_checkout(repo_dir, checkout, log_prefix, mask_sensitive=True) async context manager to create/remove temporary git worktrees, run git worktree add, yield (success, worktree_path, stdout, stderr), and attempt cleanup (git worktree remove / fs fallback).
Handler migration to worktrees
webhook_server/libs/handlers/runner_handler.py, webhook_server/libs/handlers/push_handler.py, webhook_server/libs/handlers/...
Replaces clone/temp-dir flows with _checkout_worktree (yields (success, worktree_path, out, err)); handlers run build/install/upload commands against worktree paths, propagate stdout/stderr to error reporting, and update run_podman_command usage to rely on github_webhook.mask_sensitive.
OWNERS → local filesystem
webhook_server/libs/handlers/owners_files_handler.py
Replaces GitHub API tree/content discovery with local filesystem rglob on a checked-out base; adds _get_file_content_from_local(content_path, base_path) and changes get_all_repository_approvers_and_reviewers() to read/parse OWNERS YAML locally with per-file error handling and a 1000-file cap.
Pull-request handler adjustments
webhook_server/libs/handlers/pull_request_handler.py
Redacts secrets for regctl/podman registry commands via redact_secrets; refactors closing issues to find matching issue via a threaded helper and early-exit when none found; minor control-flow/logging improvements.
CheckRunHandler caching
webhook_server/libs/handlers/check_run_handler.py
Adds _repository_private and _branch_required_status_checks caches; get_branch_required_status_checks() now caches repo privacy and branch-protection contexts to reduce repeated API calls.
Helpers & imports / mask integration
webhook_server/utils/helpers.py, webhook_server/libs/github_api.py
New imports and utilities for worktree lifecycle; integrates run_command and _redact_secrets for masked logging and command execution; mask_sensitive loaded from config and propagated into run_command/worktree flows.
Tests → worktree & OWNERS migration
webhook_server/tests/*.py, webhook_server/tests/conftest.py
Tests updated to mock _clone_repository / _checkout_worktree; adds unit tests for _clone_repository (success/failure/idempotency); OWNERS tests converted to filesystem fixtures with centralized OWNERS_TEST_DATA and owners_files_test_data in conftest.py; many tests adjusted for worktree semantics and new async/context behaviors.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

  • Areas requiring extra attention:
    • Concurrency and race conditions around self._repo_cloned across async handlers.
    • Worktree lifecycle: creation, cleanup, git worktree remove fallback and filesystem removal.
    • Propagation and redaction of stdout/stderr from git/run_command through handlers and error reporters.
    • OWNERS local discovery: path normalization, YAML parsing, 1000-file cap, and test fixture consistency.

Possibly related issues

Possibly related PRs

Suggested reviewers

  • rnetser
  • dbasunag

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 61.24% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding caching to reduce API calls for branch protection settings in the check-run handler.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch reduce-api-calls

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@myakove-bot
Copy link
Collaborator

Report bugs in Issues

Welcome! 🎉

This pull request will be automatically processed with the following features:

🔄 Automatic Actions

  • Reviewer Assignment: Reviewers are automatically assigned based on the "
    "OWNERS file in the repository root
    "
    "* Size Labeling: PR size labels (XS, S, M, L, XL, XXL) are "
    "automatically applied based on changes
    "
    f"* Issue Creation: A tracking issue is created for this PR and will be closed when the PR is merged or closed
    "
    "* Pre-commit Checks: pre-commit runs "
    "automatically if .pre-commit-config.yaml exists
    "
  • Branch Labeling: Branch-specific labels are applied to track the target branch
  • Auto-verification: Auto-verified users have their PRs automatically marked as verified

📋 Available Commands

PR Status Management

  • /wip - Mark PR as work in progress (adds WIP: prefix to title)
  • /wip cancel - Remove work in progress status
  • /hold - Block PR merging (approvers only)
  • /hold cancel - Unblock PR merging
  • /verified - Mark PR as verified
  • /verified cancel - Remove verification status
  • /reprocess - Trigger complete PR workflow reprocessing (useful if webhook failed or configuration changed)

Review & Approval

  • /lgtm - Approve changes (looks good to me)
  • /approve - Approve PR (approvers only)
  • /automerge - Enable automatic merging when all requirements are met (maintainers and approvers only)
  • /assign-reviewers - Assign reviewers based on OWNERS file
  • /assign-reviewer @username - Assign specific reviewer
  • /check-can-merge - Check if PR meets merge requirements

Testing & Validation

  • /retest tox - Run Python test suite with tox
  • /retest build-container - Rebuild and test container image
  • /retest python-module-install - Test Python package installation
  • /retest pre-commit - Run pre-commit hooks and checks
  • /retest conventional-title - Validate commit message format
  • /retest all - Run all available tests

Container Operations

  • /build-and-push-container - Build and push container image (tagged with PR number)
    • Supports additional build arguments: /build-and-push-container --build-arg KEY=value

Cherry-pick Operations

  • /cherry-pick <branch> - Schedule cherry-pick to target branch when PR is merged
    • Multiple branches: /cherry-pick branch1 branch2 branch3

Label Management

  • /<label-name> - Add a label to the PR
  • /<label-name> cancel - Remove a label from the PR

✅ Merge Requirements

This PR will be automatically approved when the following conditions are met:

  1. Approval: /approve from at least one approver
  2. LGTM Count: Minimum 1 /lgtm from reviewers
  3. Status Checks: All required status checks must pass
  4. No Blockers: No WIP, hold, or conflict labels
  5. Verified: PR must be marked as verified (if verification is enabled)

📊 Review Process

Approvers and Reviewers

Approvers:

  • myakove
  • rnetser

Reviewers:

  • myakove
  • rnetser
Available Labels
  • hold
  • verified
  • wip
  • lgtm
  • approve
  • automerge

💡 Tips

  • WIP Status: Use /wip when your PR is not ready for review
  • Verification: The verified label is automatically removed on each new commit
  • Cherry-picking: Cherry-pick labels are processed when the PR is merged
  • Container Builds: Container images are automatically tagged with the PR number
  • Permission Levels: Some commands require approver permissions
  • Auto-verified Users: Certain users have automatic verification and merge privileges

For more information, please refer to the project documentation or contact the maintainers.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
webhook_server/tests/test_push_handler.py (1)

110-201: Patch _checkout_worktree as an async context manager, not a plain Mock

All the upload_to_pypi tests here patch _checkout_worktree with a plain patch.object(..., "_checkout_worktree") and only tweak __aenter__.return_value. Because the production code does:

async with self.runner_handler._checkout_worktree(checkout=tag_name) as (success, worktree_path, out, err):
    ...

the patched object must behave as an async context manager. With the current pattern, __aenter__ is a regular Mock, so await __aenter__() will raise TypeError: 'Mock' object is not awaitable.

You already use the correct pattern in test_runner_handler.py; mirror it here. For example, for test_upload_to_pypi_success:

-        with patch.object(push_handler.runner_handler, "_checkout_worktree") as mock_checkout:
+        with patch.object(push_handler.runner_handler, "_checkout_worktree", new_callable=AsyncMock) as mock_checkout:
             with patch(
                 "webhook_server.libs.handlers.push_handler.run_command", new_callable=AsyncMock
             ) as mock_run_command:
                 with patch("webhook_server.libs.handlers.push_handler.send_slack_message") as mock_slack:
-                    # Mock successful checkout
-                    mock_checkout.return_value.__aenter__.return_value = (True, "/tmp/worktree-path", "", "")
+                    # Mock successful checkout
+                    mock_checkout.return_value.__aenter__ = AsyncMock(
+                        return_value=(True, "/tmp/worktree-path", "", "")
+                    )
+                    mock_checkout.return_value.__aexit__ = AsyncMock(return_value=None)

Apply the same AsyncMock pattern to the other tests in this file that patch _checkout_worktree so they accurately simulate the async context manager behavior and avoid awaitability errors.

Also applies to: 205-309, 311-392

webhook_server/libs/github_api.py (1)

123-127: Centralized PR clone flow is solid, but tighten error logging and docstring

The new clone_repo_dir + _repo_cloned + _clone_repository_for_pr() flow gives you a single on‑disk clone per webhook and lets all handlers share worktrees off that clone, which fits nicely with your API‑reduction/perf goals and avoids the owner.email‑may‑be‑None issue by using repository.owner.login for git config. Based on learnings.

Two improvements to consider:

  1. Avoid leaking the token in clone error logs

    You correctly pass redact_secrets=[github_token] into run_command, so the internal command‑execution logs are redacted. But in failure paths you also do:

    self.logger.error("... Failed to clone repository: %s", err)
    ...
    self.logger.error("... Failed to checkout base branch %s: %s", base_branch, err)

    where err is the raw stderr string returned by run_command. If git ever echoes the tokenized URL (https://<token>@github.com/...) into stderr, these messages can re‑introduce the token into your logs.

    A safer pattern would be to run err through the same redaction before logging, e.g. via a small helper around _redact_secrets(err, [github_token]), or by logging only high‑level context and omitting raw stderr in those outer messages.

  2. Update the __del__ docstring to match the new worktree design

    The destructor docstring still refers to “subdirectories (created with -uuid4() suffix) cleaned up by _prepare_cloned_repo_dir”, which no longer exists. Now you have:

    • A single clone_repo_dir created by tempfile.mkdtemp(...), cleaned up in __del__.
    • Worktrees created via git_worktree_checkout, which handles its own cleanup.

    Updating the docstring to describe this new split will make future maintenance less confusing.

These are relatively small adjustments on top of an otherwise well‑structured clone/worktree pipeline.

Also applies to: 171-273, 351-353, 663-671

🧹 Nitpick comments (2)
webhook_server/tests/test_pull_request_handler.py (1)

24-26: Async owners-data mocking and new parallel/exception tests look sound

The new _mock_owners_data_for_changed_files helper and its usage (both via AsyncMock(return_value={}) and via a pre‑created coroutine assigned to owners_data_for_changed_files) give _check_if_pr_approved a awaitable that resolves to {}, which matches the async‑cached‑property semantics you’re simulating. The new parallel and exception‑handling tests around process_new_or_reprocess_pull_request also correctly patch asyncio.to_thread / asyncio.gather and verify that failures in one task don’t block the automerge step.

If you want to tighten things up later, you could standardize on one mocking style (e.g., always AsyncMock(return_value={})) for owners_data_for_changed_files to make the tests more uniform, but behaviorally this all looks good.

Also applies to: 616-617, 642-718, 1329-1418

webhook_server/libs/handlers/runner_handler.py (1)

50-114: Clean refactoring to worktree-based checkouts.

The new _checkout_worktree method properly leverages the centralized clone and creates isolated worktrees for handler operations. The checkout target determination logic covers all scenarios, and the conditional merge for PR testing is appropriate.

Minor: Remove the unnecessary noqa directive on Line 71—the PLC0415 rule is not enabled.

-        from webhook_server.utils.helpers import git_worktree_checkout  # noqa: PLC0415
+        from webhook_server.utils.helpers import git_worktree_checkout
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b2465f7 and f465f1d.

📒 Files selected for processing (9)
  • webhook_server/libs/github_api.py (4 hunks)
  • webhook_server/libs/handlers/check_run_handler.py (2 hunks)
  • webhook_server/libs/handlers/push_handler.py (1 hunks)
  • webhook_server/libs/handlers/runner_handler.py (6 hunks)
  • webhook_server/tests/test_github_api.py (4 hunks)
  • webhook_server/tests/test_pull_request_handler.py (4 hunks)
  • webhook_server/tests/test_push_handler.py (7 hunks)
  • webhook_server/tests/test_runner_handler.py (16 hunks)
  • webhook_server/utils/helpers.py (2 hunks)
🧰 Additional context used
🧠 Learnings (13)
📓 Common learnings
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 0
File: :0-0
Timestamp: 2025-10-28T16:09:08.689Z
Learning: For this repository, prioritize speed and minimizing API calls in reviews and suggestions: reuse webhook payload data, batch GraphQL queries, cache IDs (labels/users), and avoid N+1 patterns.
📚 Learning: 2025-10-28T13:04:00.466Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 878
File: webhook_server/libs/handlers/runner_handler.py:491-571
Timestamp: 2025-10-28T13:04:00.466Z
Learning: In webhook_server/libs/handlers/runner_handler.py, the run_build_container method is designed with the pattern that push=True is always called with set_check=False in production code, so no check-run status needs to be finalized after push operations.

Applied to files:

  • webhook_server/tests/test_runner_handler.py
  • webhook_server/libs/handlers/push_handler.py
  • webhook_server/tests/test_push_handler.py
  • webhook_server/libs/handlers/runner_handler.py
📚 Learning: 2025-05-10T21:39:34.243Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 773
File: webhook_server/libs/pull_request_handler.py:281-308
Timestamp: 2025-05-10T21:39:34.243Z
Learning: In the refactored codebase, the `run_podman_command` method in `RunnerHandler` returns a tuple `(bool, str, str)` where the boolean `True` represents success and `False` represents failure, which is the opposite of traditional shell exit codes.

Applied to files:

  • webhook_server/tests/test_runner_handler.py
📚 Learning: 2024-10-29T08:09:57.157Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 612
File: webhook_server_container/libs/github_api.py:2089-2100
Timestamp: 2024-10-29T08:09:57.157Z
Learning: In `webhook_server_container/libs/github_api.py`, when the function `_keep_approved_by_approvers_after_rebase` is called, existing approval labels have already been cleared after pushing new changes, so there's no need to check for existing approvals within this function.

Applied to files:

  • webhook_server/tests/test_github_api.py
  • webhook_server/tests/test_push_handler.py
  • webhook_server/libs/github_api.py
📚 Learning: 2024-10-15T10:37:45.791Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 598
File: webhook_server_container/libs/github_api.py:1860-1874
Timestamp: 2024-10-15T10:37:45.791Z
Learning: In the `process_retest_command` method in `webhook_server_container/libs/github_api.py`, `_target_tests` is defined before use.

Applied to files:

  • webhook_server/tests/test_github_api.py
📚 Learning: 2025-05-13T12:06:27.297Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 778
File: webhook_server/libs/pull_request_handler.py:327-330
Timestamp: 2025-05-13T12:06:27.297Z
Learning: In the GitHub webhook server, synchronous GitHub API calls (like create_issue_comment, add_to_assignees, etc.) in async methods should be awaited using asyncio.to_thread or loop.run_in_executor to prevent blocking the event loop.

Applied to files:

  • webhook_server/tests/test_github_api.py
📚 Learning: 2025-10-30T00:18:06.176Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 878
File: webhook_server/libs/github_api.py:111-118
Timestamp: 2025-10-30T00:18:06.176Z
Learning: In webhook_server/libs/github_api.py, when creating temporary directories or performing operations that need repository names, prefer using self.repository_name (from webhook payload, always available) over dereferencing self.repository.name or self.repository_by_github_app.name, which may be None. This avoids AttributeError and keeps the code simple and reliable.

Applied to files:

  • webhook_server/libs/handlers/check_run_handler.py
  • webhook_server/libs/github_api.py
📚 Learning: 2024-10-14T14:12:28.924Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 588
File: webhook_server_container/libs/github_api.py:1638-1639
Timestamp: 2024-10-14T14:12:28.924Z
Learning: In `webhook_server_container/libs/github_api.py`, it is acceptable for `self.repository.owner.email` to be `None` since internal commands can handle this case.

Applied to files:

  • webhook_server/libs/handlers/check_run_handler.py
📚 Learning: 2024-10-07T16:21:03.462Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 579
File: webhook_server_container/libs/github_api.py:1098-1101
Timestamp: 2024-10-07T16:21:03.462Z
Learning: In the Python method `_run_tox` within `webhook_server_container/libs/github_api.py`, the variable `_tox_tests` is already comma-separated, so removing spaces with `_tox_tests.replace(" ", "")` is appropriate to handle any accidental spaces when specifying Tox environments.

Applied to files:

  • webhook_server/libs/handlers/runner_handler.py
📚 Learning: 2024-10-15T13:18:38.590Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 602
File: webhook_server_container/libs/github_api.py:2053-2062
Timestamp: 2024-10-15T13:18:38.590Z
Learning: In the `run_podman_command` method in `webhook_server_container/libs/github_api.py`, the `rc` variable is a boolean that returns `True` when the command succeeds and `False` when it fails.

Applied to files:

  • webhook_server/libs/handlers/runner_handler.py
📚 Learning: 2024-10-29T10:42:50.163Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 612
File: webhook_server_container/libs/github_api.py:925-926
Timestamp: 2024-10-29T10:42:50.163Z
Learning: In `webhook_server_container/libs/github_api.py`, the method `self._keep_approved_by_approvers_after_rebase()` must be called after removing labels when synchronizing a pull request. Therefore, it should be placed outside the `ThreadPoolExecutor` to ensure it runs sequentially after label removal.

Applied to files:

  • webhook_server/libs/github_api.py
📚 Learning: 2024-10-08T09:19:56.185Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 586
File: webhook_server_container/libs/github_api.py:1947-1956
Timestamp: 2024-10-08T09:19:56.185Z
Learning: In `webhook_server_container/libs/github_api.py`, the indentation style used in the `set_pull_request_automerge` method is acceptable as per the project's coding standards.

Applied to files:

  • webhook_server/libs/github_api.py
📚 Learning: 2024-10-14T14:13:21.316Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 588
File: webhook_server_container/libs/github_api.py:1632-1637
Timestamp: 2024-10-14T14:13:21.316Z
Learning: In the `ProcessGithubWehook` class in `webhook_server_container/libs/github_api.py`, avoid using environment variables to pass tokens because multiple commands with multiple tokens can run at the same time.

Applied to files:

  • webhook_server/libs/github_api.py
🧬 Code graph analysis (9)
webhook_server/tests/test_runner_handler.py (3)
webhook_server/libs/handlers/runner_handler.py (2)
  • RunnerHandler (31-706)
  • _checkout_worktree (50-114)
webhook_server/tests/test_pull_request_handler.py (1)
  • mock_pull_request (73-92)
webhook_server/tests/conftest.py (2)
  • pull_request (115-116)
  • github_webhook (120-140)
webhook_server/tests/test_github_api.py (1)
webhook_server/libs/github_api.py (3)
  • process (275-468)
  • GithubWebhook (50-677)
  • _clone_repository_for_pr (171-273)
webhook_server/libs/handlers/push_handler.py (2)
webhook_server/libs/handlers/runner_handler.py (1)
  • _checkout_worktree (50-114)
webhook_server/libs/handlers/check_run_handler.py (1)
  • get_check_run_text (299-325)
webhook_server/tests/test_pull_request_handler.py (3)
webhook_server/tests/test_runner_handler.py (1)
  • mock_pull_request (53-63)
webhook_server/libs/handlers/pull_request_handler.py (1)
  • process_new_or_reprocess_pull_request (1140-1191)
webhook_server/tests/conftest.py (1)
  • pull_request (115-116)
webhook_server/utils/helpers.py (1)
webhook_server/libs/handlers/runner_handler.py (1)
  • mask_sensitive (45-47)
webhook_server/tests/test_push_handler.py (1)
webhook_server/libs/handlers/push_handler.py (2)
  • upload_to_pypi (77-171)
  • PushHandler (16-171)
webhook_server/libs/handlers/check_run_handler.py (2)
webhook_server/tests/test_check_run_handler.py (2)
  • get_branch (585-586)
  • get_protection (588-589)
webhook_server/tests/conftest.py (2)
  • pull_request (115-116)
  • base (104-105)
webhook_server/libs/handlers/runner_handler.py (3)
webhook_server/utils/helpers.py (2)
  • git_worktree_checkout (596-652)
  • run_command (270-378)
webhook_server/libs/github_api.py (1)
  • get_pull_request (556-604)
webhook_server/libs/handlers/check_run_handler.py (1)
  • get_check_run_text (299-325)
webhook_server/libs/github_api.py (3)
webhook_server/utils/helpers.py (2)
  • run_command (270-378)
  • format_task_fields (117-136)
webhook_server/tests/conftest.py (2)
  • PullRequest (99-111)
  • base (104-105)
webhook_server/libs/config.py (1)
  • get_value (99-120)
🪛 Ruff (0.14.4)
webhook_server/tests/test_runner_handler.py

144-144: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


165-165: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


188-188: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


211-211: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


245-245: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


293-293: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


324-324: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


367-367: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


396-396: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


646-646: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


663-663: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


684-684: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


701-701: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


711-711: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


732-732: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


750-750: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


768-768: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


779-779: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


815-815: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


870-870: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


889-889: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)

webhook_server/tests/test_github_api.py

1038-1038: Unused function argument: args

(ARG001)


1038-1038: Unused function argument: kwargs

(ARG001)


1079-1079: Unused function argument: command

(ARG001)


1079-1079: Unused function argument: kwargs

(ARG001)


1132-1132: Unused function argument: args

(ARG001)


1132-1132: Unused function argument: kwargs

(ARG001)


1166-1166: Unused function argument: kwargs

(ARG001)


1186-1186: Unused function argument: args

(ARG001)


1186-1186: Unused function argument: kwargs

(ARG001)


1227-1227: Unused function argument: kwargs

(ARG001)


1250-1250: Unused function argument: args

(ARG001)


1250-1250: Unused function argument: kwargs

(ARG001)


1291-1291: Unused function argument: kwargs

(ARG001)


1323-1323: Unused function argument: args

(ARG001)


1323-1323: Unused function argument: kwargs

(ARG001)


1357-1357: Unused function argument: command

(ARG001)


1357-1357: Unused function argument: kwargs

(ARG001)


1358-1358: Avoid specifying long messages outside the exception class

(TRY003)

webhook_server/tests/test_pull_request_handler.py

1363-1363: Unused function argument: args

(ARG001)


1363-1363: Unused function argument: kwargs

(ARG001)


1365-1365: Create your own exception

(TRY002)


1365-1365: Avoid specifying long messages outside the exception class

(TRY003)


1367-1367: Unused function argument: args

(ARG001)


1367-1367: Unused function argument: kwargs

(ARG001)


1371-1371: Unused function argument: args

(ARG001)


1371-1371: Unused function argument: kwargs

(ARG001)


1390-1390: Unused function argument: args

(ARG001)


1390-1390: Unused function argument: kwargs

(ARG001)

webhook_server/utils/helpers.py

650-650: Do not catch blind exception: Exception

(BLE001)

webhook_server/tests/test_push_handler.py

116-116: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


145-145: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


166-166: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


187-187: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


211-211: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


236-236: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


263-263: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


287-287: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


318-318: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


343-343: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


369-369: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)

webhook_server/libs/handlers/runner_handler.py

71-71: Unused noqa directive (non-enabled: PLC0415)

Remove unused noqa directive

(RUF100)

webhook_server/libs/github_api.py

208-208: Abstract raise to an inner function

(TRY301)


208-208: Avoid specifying long messages outside the exception class

(TRY003)


260-260: Abstract raise to an inner function

(TRY301)


260-260: Avoid specifying long messages outside the exception class

(TRY003)


271-271: Redundant exception object included in logging.exception call

(TRY401)


273-273: Avoid specifying long messages outside the exception class

(TRY003)

🔇 Additional comments (11)
webhook_server/libs/handlers/check_run_handler.py (1)

39-40: Branch protection caching looks correct and safely scoped

The new _repository_private and _branch_required_status_checks caches nicely avoid repeated get_branch() / get_protection() calls while preserving behavior (per‑webhook handler instance, single PR). This aligns well with the repo’s API‑reduction goals; just keep in mind this relies on the current design where a CheckRunHandler instance only ever handles one PR per webhook.

Also applies to: 398-417

webhook_server/tests/test_runner_handler.py (1)

140-221: Worktree and container/cherry‑pick tests correctly model the async context flow

The updated tests here consistently model _checkout_worktree as an async context manager (using AsyncMock with async __aenter__/__aexit__) and provide solid coverage for success/failure scenarios of worktree setup, merge behavior, and downstream container build/cherry‑pick flows. This matches the new git_worktree_checkout contract and should keep regressions in the worktree wrapper caught by CI.

Also applies to: 242-406, 640-698, 775-898

webhook_server/utils/helpers.py (1)

4-5: Worktree helper cleanly encapsulates checkout and cleanup

The new git_worktree_checkout async context manager cleanly encapsulates worktree creation and teardown around an existing clone, returning (success, worktree_path, out, err) in a way that lines up with the updated RunnerHandler._checkout_worktree and its tests. The finally block’s best‑effort git removal with a shutil.rmtree fallback is appropriate here so that cleanup issues don’t interfere with handler logic.

Also applies to: 11-14, 17-18, 595-652

webhook_server/libs/handlers/push_handler.py (1)

98-109: Push‑tag flows will now fail because _checkout_worktree never has a base clone

upload_to_pypi (and tag‑push container builds via run_build_container(push=True, ...)) now rely on RunnerHandler._checkout_worktree, which in turn assumes github_webhook.clone_repo_dir is a valid git clone. That assumption is only satisfied for PR‑based events where GithubWebhook._clone_repository_for_pr is called; for push events we never clone the repo at all, so git -C {repo_dir} worktree add ... will consistently fail.

Net effect: tag push workflows (PyPI upload and container build/push) will always hit the “repository preparation failed” path and never actually build or publish.

You’ll need a clone step for push flows as well, e.g.:

  • Generalize _clone_repository_for_pr into an “ensure repo cloned” helper that can be called for both PR and push events (deriving the checkout ref from the push payload for tags), or
  • Introduce a separate clone routine for push events that runs before upload_to_pypi / run_build_container.

Without that, this change is a functional regression for push‑triggered release pipelines.

⛔ Skipped due to learnings
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 878
File: webhook_server/libs/handlers/runner_handler.py:491-571
Timestamp: 2025-10-28T13:04:00.466Z
Learning: In webhook_server/libs/handlers/runner_handler.py, the run_build_container method is designed with the pattern that push=True is always called with set_check=False in production code, so no check-run status needs to be finalized after push operations.
webhook_server/tests/test_github_api.py (2)

264-264: LGTM! Patches correctly bypass cloning in webhook processing tests.

The patches for _clone_repository_for_pr appropriately mock the new centralized cloning flow, allowing tests to focus on webhook processing logic without executing git operations.

Also applies to: 366-366, 751-753


1029-1366: Excellent test coverage for the new cloning flow.

The six new test functions comprehensively cover success, failure, and edge-case scenarios for _clone_repository_for_pr:

  • Success path with state verification
  • Early return when already cloned
  • Clone and checkout failures with appropriate RuntimeError
  • Config failures degrading gracefully to warnings
  • General exception handling

The static analysis warnings about unused mock function arguments are false positives—these parameters are intentionally present to match expected signatures.

webhook_server/libs/handlers/runner_handler.py (5)

173-214: Correct integration with the new worktree-based flow.

The run_tox method properly unpacks the 4-tuple from _checkout_worktree and uses worktree_path in command construction. Error handling correctly propagates stdout/stderr from worktree creation failures.


239-276: Consistent implementation following the worktree pattern.

The run_pre_commit method correctly integrates with the worktree-based checkout, using worktree_path appropriately in the pre-commit command.


324-386: Proper worktree integration for container builds.

The run_build_container method correctly uses worktree_path for both the Dockerfile path and build context, ensuring the container build operates on the isolated worktree checkout.


474-512: Correct worktree usage for Python module installation.

The run_install_python_module method properly uses worktree_path for both the wheel output directory and source, ensuring the installation operates on the isolated checkout.


628-703: Correct worktree integration for cherry-pick operations.

The cherry_pick method properly constructs git and hub commands with explicit --work-tree and --git-dir flags referencing the worktree, ensuring all cherry-pick operations are isolated to the worktree checkout.

- Added missing 'import asyncio' to test_pull_request_handler.py
- Removed unused 'mask_sensitive' parameter from run_podman_command method
- Resolves test_process_new_or_reprocess_pull_request_parallel_execution failure
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
webhook_server/libs/handlers/runner_handler.py (1)

84-87: Static analysis hint: Consider using a custom exception class for detailed messages.

This is a minor style suggestion from Ruff (TRY003). For runtime errors with detailed diagnostic information, consider defining a custom exception class instead of passing long messages directly to RuntimeError. However, given the low frequency of this error path and the clear diagnostic value of the inline message, this is optional.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f465f1d and 03458f3.

📒 Files selected for processing (6)
  • webhook_server/libs/github_api.py (6 hunks)
  • webhook_server/libs/handlers/pull_request_handler.py (2 hunks)
  • webhook_server/libs/handlers/runner_handler.py (12 hunks)
  • webhook_server/tests/test_pull_request_handler.py (10 hunks)
  • webhook_server/tests/test_push_handler.py (8 hunks)
  • webhook_server/tests/test_runner_handler.py (20 hunks)
🧰 Additional context used
🧠 Learnings (11)
📓 Common learnings
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 0
File: :0-0
Timestamp: 2025-10-28T16:09:08.689Z
Learning: For this repository, prioritize speed and minimizing API calls in reviews and suggestions: reuse webhook payload data, batch GraphQL queries, cache IDs (labels/users), and avoid N+1 patterns.
📚 Learning: 2024-10-15T13:19:23.105Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 602
File: webhook_server_container/libs/github_api.py:1503-1503
Timestamp: 2024-10-15T13:19:23.105Z
Learning: In `run_podman_command` function in `webhook_server_container/libs/github_api.py`, using environment variables or global login sessions for credentials is not suitable because the function may be called concurrently with different credentials.

Applied to files:

  • webhook_server/libs/handlers/pull_request_handler.py
📚 Learning: 2024-10-15T13:18:38.590Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 602
File: webhook_server_container/libs/github_api.py:2053-2062
Timestamp: 2024-10-15T13:18:38.590Z
Learning: In the `run_podman_command` method in `webhook_server_container/libs/github_api.py`, the `rc` variable is a boolean that returns `True` when the command succeeds and `False` when it fails.

Applied to files:

  • webhook_server/libs/handlers/pull_request_handler.py
  • webhook_server/libs/handlers/runner_handler.py
📚 Learning: 2024-10-29T08:09:57.157Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 612
File: webhook_server_container/libs/github_api.py:2089-2100
Timestamp: 2024-10-29T08:09:57.157Z
Learning: In `webhook_server_container/libs/github_api.py`, when the function `_keep_approved_by_approvers_after_rebase` is called, existing approval labels have already been cleared after pushing new changes, so there's no need to check for existing approvals within this function.

Applied to files:

  • webhook_server/tests/test_push_handler.py
  • webhook_server/libs/github_api.py
📚 Learning: 2025-10-28T13:04:00.466Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 878
File: webhook_server/libs/handlers/runner_handler.py:491-571
Timestamp: 2025-10-28T13:04:00.466Z
Learning: In webhook_server/libs/handlers/runner_handler.py, the run_build_container method is designed with the pattern that push=True is always called with set_check=False in production code, so no check-run status needs to be finalized after push operations.

Applied to files:

  • webhook_server/tests/test_push_handler.py
  • webhook_server/tests/test_runner_handler.py
  • webhook_server/libs/handlers/runner_handler.py
📚 Learning: 2025-10-30T00:18:06.176Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 878
File: webhook_server/libs/github_api.py:111-118
Timestamp: 2025-10-30T00:18:06.176Z
Learning: In webhook_server/libs/github_api.py, when creating temporary directories or performing operations that need repository names, prefer using self.repository_name (from webhook payload, always available) over dereferencing self.repository.name or self.repository_by_github_app.name, which may be None. This avoids AttributeError and keeps the code simple and reliable.

Applied to files:

  • webhook_server/libs/github_api.py
📚 Learning: 2024-10-29T10:42:50.163Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 612
File: webhook_server_container/libs/github_api.py:925-926
Timestamp: 2024-10-29T10:42:50.163Z
Learning: In `webhook_server_container/libs/github_api.py`, the method `self._keep_approved_by_approvers_after_rebase()` must be called after removing labels when synchronizing a pull request. Therefore, it should be placed outside the `ThreadPoolExecutor` to ensure it runs sequentially after label removal.

Applied to files:

  • webhook_server/libs/github_api.py
  • webhook_server/tests/test_pull_request_handler.py
📚 Learning: 2024-10-14T14:13:21.316Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 588
File: webhook_server_container/libs/github_api.py:1632-1637
Timestamp: 2024-10-14T14:13:21.316Z
Learning: In the `ProcessGithubWehook` class in `webhook_server_container/libs/github_api.py`, avoid using environment variables to pass tokens because multiple commands with multiple tokens can run at the same time.

Applied to files:

  • webhook_server/libs/github_api.py
  • webhook_server/libs/handlers/runner_handler.py
📚 Learning: 2025-05-10T22:07:53.544Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 773
File: webhook_server/libs/pull_request_handler.py:553-557
Timestamp: 2025-05-10T22:07:53.544Z
Learning: In the GitHub webhook server codebase, `root_approvers` and `root_reviewers` are properties of the GithubWebhook class, not methods, so they can be used with `.copy()` without parentheses.

Applied to files:

  • webhook_server/libs/github_api.py
📚 Learning: 2025-05-10T21:39:34.243Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 773
File: webhook_server/libs/pull_request_handler.py:281-308
Timestamp: 2025-05-10T21:39:34.243Z
Learning: In the refactored codebase, the `run_podman_command` method in `RunnerHandler` returns a tuple `(bool, str, str)` where the boolean `True` represents success and `False` represents failure, which is the opposite of traditional shell exit codes.

Applied to files:

  • webhook_server/tests/test_runner_handler.py
  • webhook_server/libs/handlers/runner_handler.py
📚 Learning: 2024-10-07T16:21:03.462Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 579
File: webhook_server_container/libs/github_api.py:1098-1101
Timestamp: 2024-10-07T16:21:03.462Z
Learning: In the Python method `_run_tox` within `webhook_server_container/libs/github_api.py`, the variable `_tox_tests` is already comma-separated, so removing spaces with `_tox_tests.replace(" ", "")` is appropriate to handle any accidental spaces when specifying Tox environments.

Applied to files:

  • webhook_server/libs/handlers/runner_handler.py
🧬 Code graph analysis (6)
webhook_server/libs/handlers/pull_request_handler.py (1)
webhook_server/libs/handlers/runner_handler.py (1)
  • run_podman_command (127-147)
webhook_server/tests/test_push_handler.py (1)
webhook_server/libs/handlers/push_handler.py (2)
  • PushHandler (16-171)
  • upload_to_pypi (77-171)
webhook_server/libs/github_api.py (1)
webhook_server/utils/helpers.py (3)
  • _redact_secrets (144-212)
  • format_task_fields (117-136)
  • run_command (270-378)
webhook_server/tests/test_pull_request_handler.py (1)
webhook_server/libs/handlers/pull_request_handler.py (1)
  • process_new_or_reprocess_pull_request (1165-1216)
webhook_server/tests/test_runner_handler.py (1)
webhook_server/libs/handlers/runner_handler.py (4)
  • run_build_container (285-455)
  • run_conventional_title_check (520-597)
  • cherry_pick (602-720)
  • _checkout_worktree (46-116)
webhook_server/libs/handlers/runner_handler.py (2)
webhook_server/utils/helpers.py (3)
  • git_worktree_checkout (596-652)
  • run_command (270-378)
  • _redact_secrets (144-212)
webhook_server/libs/handlers/check_run_handler.py (1)
  • get_check_run_text (299-325)
🪛 Ruff (0.14.4)
webhook_server/tests/test_push_handler.py

132-132: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


163-163: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


185-185: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


206-206: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


230-230: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


255-255: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


282-282: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


306-306: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


337-337: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


364-364: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


391-391: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)

webhook_server/libs/github_api.py

213-213: Abstract raise to an inner function

(TRY301)


213-213: Avoid specifying long messages outside the exception class

(TRY003)


266-266: Abstract raise to an inner function

(TRY301)


266-266: Avoid specifying long messages outside the exception class

(TRY003)


277-277: Redundant exception object included in logging.exception call

(TRY401)


279-279: Avoid specifying long messages outside the exception class

(TRY003)

webhook_server/tests/test_pull_request_handler.py

1371-1371: Unused function argument: args

(ARG001)


1371-1371: Unused function argument: kwargs

(ARG001)


1372-1372: Create your own exception

(TRY002)


1372-1372: Avoid specifying long messages outside the exception class

(TRY003)


1374-1374: Unused function argument: args

(ARG001)


1374-1374: Unused function argument: kwargs

(ARG001)


1377-1377: Unused function argument: args

(ARG001)


1377-1377: Unused function argument: kwargs

(ARG001)


1386-1386: Unused function argument: args

(ARG001)


1386-1386: Unused function argument: kwargs

(ARG001)


1389-1389: Unused function argument: args

(ARG001)


1389-1389: Unused function argument: kwargs

(ARG001)


1392-1392: Unused function argument: args

(ARG001)


1392-1392: Unused function argument: kwargs

(ARG001)

webhook_server/tests/test_runner_handler.py

144-144: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


165-165: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


188-188: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


211-211: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


245-245: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


293-293: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


324-324: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


366-366: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


395-395: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


645-645: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


662-662: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


683-683: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


701-701: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


711-711: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


731-731: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


749-749: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


767-767: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


778-778: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


814-814: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


869-869: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)


888-888: Probable insecure usage of temporary file or directory: "/tmp/worktree-path"

(S108)

webhook_server/libs/handlers/runner_handler.py

84-87: Avoid specifying long messages outside the exception class

(TRY003)

🔇 Additional comments (7)
webhook_server/libs/handlers/runner_handler.py (7)

46-116: Well-structured worktree checkout with clear separation of concerns.

The refactoring from local cloning to centralized worktree checkout is well-executed. The logic correctly:

  • Determines checkout targets based on context (checkout, tag, merged state, or PR)
  • Delegates worktree creation to the centralized helper
  • Handles merge operations only when appropriate (non-merged PRs without tags)
  • Propagates errors via the 4-tuple result

127-147: LGTM! Signature simplified correctly.

The removal of the mask_sensitive parameter and consistent use of self.github_webhook.mask_sensitive throughout both the main execution path and the podman bug retry path is correct.


176-219: LGTM! Tox execution correctly migrated to worktree-based checkout.

The method correctly:

  • Unpacks the 4-tuple result from _checkout_worktree
  • Uses worktree_path for all command construction
  • Handles checkout failures by propagating stdout/stderr
  • Applies masking consistently via self.github_webhook.mask_sensitive

244-283: LGTM! Pre-commit execution correctly migrated to worktree-based checkout.

The implementation follows the same correct pattern as run_tox, properly handling the worktree checkout and error propagation.


331-456: LGTM! Container build correctly migrated to worktree-based checkout.

The method properly:

  • Passes is_merged and tag_name to _checkout_worktree for appropriate checkout behavior
  • Uses worktree_path for all Dockerfile and build context paths
  • Handles both build and push flows with appropriate secret redaction on push operations

480-518: LGTM! Python module installation correctly migrated to worktree-based checkout.

The implementation correctly uses worktree_path for both the source directory and output directory in the pip wheel command.


634-720: LGTM! Cherry-pick correctly migrated to worktree-based checkout.

The method properly:

  • Uses worktree_path throughout all git and hub commands
  • Handles checkout failures with early return
  • Applies secret redaction both in run_command (via redact_secrets parameter) and in manual PR comment generation (via _redact_secrets helper)
  • Maintains the final success path where output["text"] uses the last command's output

[approve_code_challenges]

Replace GitHub API calls with filesystem operations for OWNERS file discovery
and reading. This eliminates ~1,200-2,000 API calls per webhook.

Changes:
- Modified owners_files_handler.py to use Path.rglob() for file discovery
- Replaced repository.get_git_tree() with filesystem walk
- Replaced repository.get_contents() with Path.read_text()
- Added _clone_repository_for_pr() call to ensure repo is cloned
- Updated tests to use tmp_path fixtures instead of API mocks
- Wrapped filesystem I/O in asyncio.to_thread() for non-blocking operation

Performance:
- Saves ~1,200-2,000 API calls per webhook (1.3-2.1% reduction)
- 1,500-6,000x faster than API-based approach
- Eliminates GitHub API rate limit pressure for OWNERS scanning

Test results:
- All 55 tests pass (39 + 16 across test files)
- 98% code coverage maintained
- Code review approved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
webhook_server/libs/handlers/owners_files_handler.py (2)

109-124: Consider handling filesystem I/O errors in _get_file_content_from_local.

The helper is clean and does exactly what we need, but if an OWNERS file is deleted or becomes unreadable between rglob and read_text, a OSError/FileNotFoundError will currently bubble up and fail the whole OWNERS loading. Wrapping the read in a small try/except OSError and logging/skip behavior would make this more robust in face of transient filesystem issues.


175-176: Optional: switch YAML error logging to logger.exception for better diagnostics.

Static analysis suggests using logger.exception inside the yaml.YAMLError handler so that the traceback is captured alongside the message, which can make debugging malformed OWNERS files easier:

-            except yaml.YAMLError as exp:
-                self.logger.error(f"{self.log_prefix} Invalid OWNERS file {relative_path_str}: {exp}")
+            except yaml.YAMLError:
+                self.logger.exception(f"{self.log_prefix} Invalid OWNERS file {relative_path_str}")

If you prefer less noisy logs, the current error call is fine; this is mainly an observability trade‑off.

webhook_server/tests/test_pull_request_owners.py (1)

129-135: Tidy up unused fixture parameters in test_get_all_repository_approvers_and_reviewers.

changed_files and all_repository_approvers_and_reviewers are only used for their fixture side effects, which Ruff flags as unused. If you want to keep the fixtures but silence ARG001, consider renaming them to _changed_files / _all_repository_approvers_and_reviewers or explicitly deleting them inside the test.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 03458f3 and d4aecdb.

📒 Files selected for processing (3)
  • webhook_server/libs/handlers/owners_files_handler.py (1 hunks)
  • webhook_server/tests/test_owners_files_handler.py (4 hunks)
  • webhook_server/tests/test_pull_request_owners.py (2 hunks)
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 0
File: :0-0
Timestamp: 2025-10-28T16:09:08.689Z
Learning: For this repository, prioritize speed and minimizing API calls in reviews and suggestions: reuse webhook payload data, batch GraphQL queries, cache IDs (labels/users), and avoid N+1 patterns.
📚 Learning: 2024-11-21T13:34:45.218Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 624
File: webhook_server_container/libs/github_api.py:596-604
Timestamp: 2024-11-21T13:34:45.218Z
Learning: In the codebase, aggregation of reviewers and approvers from all OWNERS files is handled within the `assign_reviewers` method.

Applied to files:

  • webhook_server/libs/handlers/owners_files_handler.py
  • webhook_server/tests/test_owners_files_handler.py
📚 Learning: 2025-05-10T22:07:53.544Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 773
File: webhook_server/libs/pull_request_handler.py:553-557
Timestamp: 2025-05-10T22:07:53.544Z
Learning: In the GitHub webhook server codebase, `root_approvers` and `root_reviewers` are properties of the GithubWebhook class, not methods, so they can be used with `.copy()` without parentheses.

Applied to files:

  • webhook_server/libs/handlers/owners_files_handler.py
🧬 Code graph analysis (3)
webhook_server/tests/test_pull_request_owners.py (3)
webhook_server/tests/conftest.py (3)
  • process_github_webhook (144-145)
  • owners_file_handler (149-150)
  • pull_request (115-116)
webhook_server/tests/test_owners_files_handler.py (1)
  • owners_file_handler (32-34)
webhook_server/libs/handlers/owners_files_handler.py (1)
  • get_all_repository_approvers_and_reviewers (126-179)
webhook_server/libs/handlers/owners_files_handler.py (2)
webhook_server/tests/conftest.py (3)
  • github_webhook (120-140)
  • pull_request (115-116)
  • PullRequest (99-111)
webhook_server/libs/github_api.py (1)
  • _clone_repository_for_pr (172-279)
webhook_server/tests/test_owners_files_handler.py (2)
webhook_server/tests/conftest.py (2)
  • owners_file_handler (149-150)
  • github_webhook (120-140)
webhook_server/libs/handlers/owners_files_handler.py (3)
  • OwnersFileHandler (22-433)
  • _get_file_content_from_local (109-124)
  • get_all_repository_approvers_and_reviewers (126-179)
🪛 Ruff (0.14.4)
webhook_server/tests/test_pull_request_owners.py

129-129: Unused function argument: changed_files

(ARG001)


133-133: Unused function argument: all_repository_approvers_and_reviewers

(ARG001)

webhook_server/libs/handlers/owners_files_handler.py

176-176: Use logging.exception instead of logging.error

Replace with exception

(TRY400)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (10)
  • GitHub Check: can-be-merged
  • GitHub Check: can-be-merged
  • GitHub Check: can-be-merged
  • GitHub Check: can-be-merged
  • GitHub Check: can-be-merged
  • GitHub Check: conventional-title
  • GitHub Check: build-container
  • GitHub Check: pre-commit
  • GitHub Check: python-module-install
  • GitHub Check: tox
🔇 Additional comments (8)
webhook_server/libs/handlers/owners_files_handler.py (1)

127-161: Local OWNERS discovery via clone_repo_dir looks correct and aligns with API-reduction goals.

The switch to clone_repo_dir.rglob("OWNERS"), bounded by max_owners_files, plus batching reads via _get_file_content_from_local and asyncio.gather, nicely removes the previous GitHub API tree/content calls while keeping behavior (root as ".", per-folder parents) consistent with existing tests and callers. This is a solid perf win with clear logging around discovery and caps.

Also applies to: 165-170

webhook_server/tests/test_pull_request_owners.py (1)

136-172: Tmp-path based OWNERS test correctly exercises the new local-file workflow.

The test’s use of tmp_path to build a mini repo tree, wiring process_github_webhook.clone_repo_dir, and patching _clone_repository_for_pr with AsyncMock gives good coverage of the filesystem-based OWNERS loading while staying completely local and fast, which fits well with the repo’s perf/API-reduction goals.

webhook_server/tests/test_owners_files_handler.py (6)

37-58: Good reuse of shared OWNERS data via mock_content_files fixture.

Centralizing the various OWNERS YAML payloads in a single fixture keeps the tests DRY and makes it easy to keep expectations in sync with the handler’s behavior when adding new cases.


157-170: test_get_file_content_from_local nicely validates relative path semantics.

This test ensures _get_file_content_from_local returns both the raw content and the path relative to clone_repo_dir ("test/OWNERS"), which is exactly what callers rely on when building the OWNERS mapping.


171-211: Local-clone get_all_repository_approvers_and_reviewers test mirrors real behavior well.

By constructing the filesystem layout under tmp_path, setting clone_repo_dir, and patching _clone_repository_for_pr to a no-op, the test exercises the new local discovery and YAML loading logic end-to-end and checks that the resulting dict structure matches expectations across root and nested folders.


213-233: Edge case for >1000 OWNERS files is well covered.

The too_many_files test directly validates the max_owners_files guard (returning 1000 entries and emitting a single error log), which is important for robustness in very large repos.


235-253: Invalid YAML handling test aligns with the YAML error branch.

Creating a syntactically invalid OWNERS file and asserting an empty result plus a single logger.error call gives good protection around the yaml.YAMLError path in the implementation.


255-273: Invalid OWNERS content structure test confirms validation behavior.

The test that writes "approvers": "not_a_list" and checks for an empty result and a single error log effectively covers _validate_owners_content returning False and ensures structurally bad OWNERS files are safely ignored.

…ssing

- Add OSError handling in _get_file_content_from_local to gracefully handle missing or unreadable files
- Return None for unreadable files instead of failing the entire process
- Update YAML error logging to use logger.exception for better diagnostics and full tracebacks
- Add test coverage for file not found scenario
- Fix unused fixture parameters in test_pull_request_owners.py with # noqa: ARG001 comments

Addresses CodeRabbit review feedback for better error handling and code quality.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
webhook_server/tests/test_pull_request_owners.py (1)

1-1: Local-clone-based OWNERS test aligns well with new handler flow

The switch to a filesystem-based setup with tmp_path, explicit OWNERS file creation, and patching _clone_repository_for_pr as an AsyncMock matches the new implementation and keeps the test free of real API/clone calls. The equality assertion against all_repository_approvers_and_reviewers continues to validate the aggregation logic end-to-end.

If you find yourself tweaking these OWNERS structures often, consider centralizing the shared OWNERS test data (here and in test_owners_files_handler.py) into a reusable fixture/helper to keep them in sync, but this is not required for correctness.

Also applies to: 127-173

webhook_server/libs/handlers/owners_files_handler.py (1)

109-132: Local OWNERS discovery & read path looks correct; minor Path/comment nits

The new local-read flow (_clone → rglob → async read → YAML parse/validate) is solid and matches the tests and API-reduction goal. Error handling (OSError, invalid YAML, invalid schema) gracefully skips bad files without blowing up the webhook.

Two small polish suggestions:

  1. Use a Path as the relative_to base for consistency

Right now _get_file_content_from_local does:

relative_path = content_path.relative_to(self.github_webhook.clone_repo_dir)

Given that get_all_repository_approvers_and_reviewers uses:

clone_path = Path(self.github_webhook.clone_repo_dir)
relative_path = owners_file_path.relative_to(clone_path)

it would be slightly safer and more self-consistent to mirror that here:

- relative_path = content_path.relative_to(self.github_webhook.clone_repo_dir)
+ clone_path = Path(self.github_webhook.clone_repo_dir)
+ relative_path = content_path.relative_to(clone_path)

This avoids any surprise if clone_repo_dir is ever a non-normalized path or a different type than expected.

  1. Clarify the max_owners_files comment

max_owners_files = 1000 # Configurable limit is intentionally hardcoded per prior guidance. Consider updating the comment to reflect reality, e.g.:

- max_owners_files = 1000  # Configurable limit
+ max_owners_files = 1000  # Hard limit to prevent runaway OWNERS scans

Functionally everything here looks good and aligns with the “minimize API calls” objective.

Also applies to: 134-188

webhook_server/tests/test_owners_files_handler.py (1)

1-1: Shared OWNERS fixtures using YAML strings look good

Importing Path and switching mock_content_files to return raw YAML strings keyed by file path keeps the tests close to the new filesystem-based behavior while remaining simple. This also mirrors the structure used in other tests that exercise OWNERS aggregation.

If duplication with test_pull_request_owners.py ever becomes a maintenance burden, you could consider moving this mapping into a common helper/fixture, but it’s fine as-is.

Also applies to: 37-58

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d4aecdb and d36a426.

📒 Files selected for processing (3)
  • webhook_server/libs/handlers/owners_files_handler.py (1 hunks)
  • webhook_server/tests/test_owners_files_handler.py (4 hunks)
  • webhook_server/tests/test_pull_request_owners.py (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📓 Common learnings
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 0
File: :0-0
Timestamp: 2025-10-28T16:09:08.689Z
Learning: For this repository, prioritize speed and minimizing API calls in reviews and suggestions: reuse webhook payload data, batch GraphQL queries, cache IDs (labels/users), and avoid N+1 patterns.
📚 Learning: 2024-11-21T13:34:45.218Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 624
File: webhook_server_container/libs/github_api.py:596-604
Timestamp: 2024-11-21T13:34:45.218Z
Learning: In the codebase, aggregation of reviewers and approvers from all OWNERS files is handled within the `assign_reviewers` method.

Applied to files:

  • webhook_server/tests/test_pull_request_owners.py
  • webhook_server/tests/test_owners_files_handler.py
  • webhook_server/libs/handlers/owners_files_handler.py
📚 Learning: 2024-11-21T16:10:01.777Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 624
File: webhook_server_container/libs/github_api.py:2067-2101
Timestamp: 2024-11-21T16:10:01.777Z
Learning: In `webhook_server_container/libs/github_api.py`, keep the `max_owners_files` limit as a hardcoded value rather than making it configurable through the config.

Applied to files:

  • webhook_server/libs/handlers/owners_files_handler.py
📚 Learning: 2025-05-10T22:07:53.544Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 773
File: webhook_server/libs/pull_request_handler.py:553-557
Timestamp: 2025-05-10T22:07:53.544Z
Learning: In the GitHub webhook server codebase, `root_approvers` and `root_reviewers` are properties of the GithubWebhook class, not methods, so they can be used with `.copy()` without parentheses.

Applied to files:

  • webhook_server/libs/handlers/owners_files_handler.py
🧬 Code graph analysis (3)
webhook_server/tests/test_pull_request_owners.py (3)
webhook_server/tests/conftest.py (3)
  • process_github_webhook (144-145)
  • owners_file_handler (149-150)
  • pull_request (115-116)
webhook_server/tests/test_owners_files_handler.py (1)
  • owners_file_handler (32-34)
webhook_server/libs/handlers/owners_files_handler.py (1)
  • get_all_repository_approvers_and_reviewers (133-190)
webhook_server/tests/test_owners_files_handler.py (3)
webhook_server/tests/conftest.py (2)
  • owners_file_handler (149-150)
  • github_webhook (120-140)
webhook_server/libs/handlers/owners_files_handler.py (3)
  • OwnersFileHandler (22-444)
  • _get_file_content_from_local (109-131)
  • get_all_repository_approvers_and_reviewers (133-190)
webhook_server/tests/test_runner_handler.py (1)
  • mock_pull_request (53-63)
webhook_server/libs/handlers/owners_files_handler.py (2)
webhook_server/tests/conftest.py (3)
  • github_webhook (120-140)
  • pull_request (115-116)
  • PullRequest (99-111)
webhook_server/libs/github_api.py (1)
  • _clone_repository_for_pr (172-279)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: can-be-merged
  • GitHub Check: can-be-merged
  • GitHub Check: can-be-merged
  • GitHub Check: can-be-merged
  • GitHub Check: build-container
  • GitHub Check: conventional-title
  • GitHub Check: pre-commit
  • GitHub Check: python-module-install
  • GitHub Check: tox
🔇 Additional comments (2)
webhook_server/tests/test_owners_files_handler.py (2)

157-192: _get_file_content_from_local is well covered for success and missing-file cases

The two tests around _get_file_content_from_local:

  • Verify that a real OWNERS file under tmp_path yields the expected (content, "relative/path") tuple when clone_repo_dir is set.
  • Confirm that a non-existent file returns None and emits a warning containing the right path and “Skipping this file” wording.

This matches the handler’s behavior exactly and protects against regressions if the logging or error handling changes.


194-295: Comprehensive tests for local OWNERS discovery, limits, and invalid content

The new/updated tests for get_all_repository_approvers_and_reviewers do a thorough job:

  • Normal path: populating a tmp_path hierarchy with OWNERS files from mock_content_files, patching _clone_repository_for_pr, and asserting the aggregated dict matches expectations.
  • Limit path: creating 1001 OWNERS files and asserting only 1000 are processed plus a single logger.error call, which validates the guardrail.
  • Error paths: separate tests for invalid YAML (exception logged, empty result) and invalid content structure (schema error logged via _validate_owners_content, empty result).

They also consistently rely on clone_repo_dir and local filesystem behavior, which aligns with the API-reduction goals of the PR.

No functional issues spotted here.

- Create shared owners_files_test_data fixture in conftest.py
- Remove duplicate OWNERS test data from test files (48 lines eliminated)
- Use Path() consistently in owners_files_handler.py (line 118)
- Clarify max_owners_files comment (intentionally hardcoded)

Addresses CodeRabbit AI review comments for better maintainability
and code consistency.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
webhook_server/tests/conftest.py (1)

198-225: Shared OWNERS fixture is solid; consider de‑duplicating source of truth

The owners_files_test_data fixture cleanly centralizes OWNERS YAML for tests and matches expectations elsewhere. The only minor concern is duplication with the inline OWNERS YAML in Repository.get_contents in this same file; if one changes and the other doesn’t, tests may drift.

If you keep both around long‑term, consider extracting a small helper or constant that both Repository.get_contents and this fixture use so the data stays in sync.

webhook_server/libs/handlers/owners_files_handler.py (1)

109-131: Local OWNERS reader looks good; consider also handling decode errors

The new _get_file_content_from_local correctly computes a relative path, offloads I/O to a thread pool, and safely skips unreadable files while logging a warning. One potential hardening tweak: if an OWNERS file has invalid encoding, read_text will raise UnicodeDecodeError, which currently isn’t caught and would abort processing for all files.

You could treat that similarly to OSError so a single bad file doesn’t break OWNERS aggregation:

-        except OSError as ex:
+        except (OSError, UnicodeDecodeError) as ex:
             # File may have been deleted or become unreadable between rglob and read_text
             self.logger.warning(
                 f"{self.log_prefix} Failed to read OWNERS file {relative_path}: {ex}. Skipping this file."
             )
             return None
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d36a426 and 249b3f0.

📒 Files selected for processing (4)
  • webhook_server/libs/handlers/owners_files_handler.py (1 hunks)
  • webhook_server/tests/conftest.py (1 hunks)
  • webhook_server/tests/test_owners_files_handler.py (3 hunks)
  • webhook_server/tests/test_pull_request_owners.py (2 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 0
File: :0-0
Timestamp: 2025-10-28T16:09:08.689Z
Learning: For this repository, prioritize speed and minimizing API calls in reviews and suggestions: reuse webhook payload data, batch GraphQL queries, cache IDs (labels/users), and avoid N+1 patterns.
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 612
File: webhook_server_container/libs/github_api.py:2089-2100
Timestamp: 2024-10-29T08:09:57.157Z
Learning: In `webhook_server_container/libs/github_api.py`, when the function `_keep_approved_by_approvers_after_rebase` is called, existing approval labels have already been cleared after pushing new changes, so there's no need to check for existing approvals within this function.
📚 Learning: 2024-11-21T13:34:45.218Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 624
File: webhook_server_container/libs/github_api.py:596-604
Timestamp: 2024-11-21T13:34:45.218Z
Learning: In the codebase, aggregation of reviewers and approvers from all OWNERS files is handled within the `assign_reviewers` method.

Applied to files:

  • webhook_server/tests/test_owners_files_handler.py
  • webhook_server/libs/handlers/owners_files_handler.py
📚 Learning: 2024-11-21T16:10:01.777Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 624
File: webhook_server_container/libs/github_api.py:2067-2101
Timestamp: 2024-11-21T16:10:01.777Z
Learning: In `webhook_server_container/libs/github_api.py`, keep the `max_owners_files` limit as a hardcoded value rather than making it configurable through the config.

Applied to files:

  • webhook_server/libs/handlers/owners_files_handler.py
📚 Learning: 2025-05-10T22:07:53.544Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 773
File: webhook_server/libs/pull_request_handler.py:553-557
Timestamp: 2025-05-10T22:07:53.544Z
Learning: In the GitHub webhook server codebase, `root_approvers` and `root_reviewers` are properties of the GithubWebhook class, not methods, so they can be used with `.copy()` without parentheses.

Applied to files:

  • webhook_server/libs/handlers/owners_files_handler.py
📚 Learning: 2025-05-10T22:07:53.544Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 773
File: webhook_server/libs/pull_request_handler.py:553-557
Timestamp: 2025-05-10T22:07:53.544Z
Learning: In the webhook server codebase, `root_approvers` and `root_reviewers` are defined as properties in the `GithubWebhook` class, not methods, so they can be accessed without parentheses and used with methods like `.copy()` directly.

Applied to files:

  • webhook_server/libs/handlers/owners_files_handler.py
🧬 Code graph analysis (3)
webhook_server/tests/test_owners_files_handler.py (1)
webhook_server/tests/conftest.py (3)
  • owners_file_handler (149-150)
  • github_webhook (120-140)
  • owners_files_test_data (199-225)
webhook_server/libs/handlers/owners_files_handler.py (2)
webhook_server/tests/conftest.py (3)
  • github_webhook (120-140)
  • pull_request (115-116)
  • PullRequest (99-111)
webhook_server/libs/github_api.py (1)
  • _clone_repository_for_pr (172-279)
webhook_server/tests/test_pull_request_owners.py (2)
webhook_server/tests/conftest.py (4)
  • process_github_webhook (144-145)
  • owners_file_handler (149-150)
  • pull_request (115-116)
  • owners_files_test_data (199-225)
webhook_server/libs/handlers/owners_files_handler.py (1)
  • get_all_repository_approvers_and_reviewers (133-190)
🔇 Additional comments (5)
webhook_server/libs/handlers/owners_files_handler.py (1)

133-190: Filesystem-based OWNERS aggregation is consistent and bounded

The updated get_all_repository_approvers_and_reviewers correctly:

  • Ensures the repo is cloned once via _clone_repository_for_pr.
  • Discovers OWNERS files via clone_path.rglob("OWNERS") in a thread pool.
  • Enforces a hard limit (max_owners_files = 1000) and logs when exceeded.
  • Reads each file via _get_file_content_from_local, skips unreadable entries, parses with yaml.safe_load, validates structure, and stores data keyed by the parent directory (normalizing empty/“.” to “.”).

This matches the expectations in the new tests and cleanly removes the previous API-based N+1 pattern in favor of local I/O, while still guarding against runaway repositories.

webhook_server/tests/test_pull_request_owners.py (1)

1-1: Filesystem-backed OWNERS test aligns well with the new handler behavior

The switch to using tmp_path + owners_files_test_data, wiring clone_repo_dir to the temp directory, and patching _clone_repository_for_pr to a no‑op AsyncMock gives this test good coverage of the new local‑filesystem path without any real cloning or API calls. Comparing the method result to owners_file_handler.all_repository_approvers_and_reviewers (seeded by the fixture) keeps the expected structure explicit and stable.

This looks correct and nicely integrated with the shared test data.

Also applies to: 128-152

webhook_server/tests/test_owners_files_handler.py (3)

133-167: Good coverage for _get_file_content_from_local success and failure paths

The tests for _get_file_content_from_local correctly:

  • Verify relative path calculation and returned (content, "test/OWNERS") tuple when the file exists.
  • Exercise the missing-file case, asserting the method returns None and that the warning log contains the expected phrases and relative path.

This tightly couples the tests to the intended behavior and will catch regressions in how unreadable files are handled.


170-207: Local-clone OWNERS aggregation test is well structured and reuses shared data

The updated test_get_all_repository_approvers_and_reviewers uses owners_files_test_data to populate a realistic repo layout under tmp_path, sets clone_repo_dir, patches _clone_repository_for_pr to a no‑op, and asserts the handler returns the expected directory→OWNERS mapping.

This mirrors production behavior closely while staying unit‑test friendly and avoids any remote API calls, which fits the perf goals.


211-271: Edge-case tests (limit, invalid YAML, invalid structure) nicely harden the handler

The trio of tests for:

  • too many OWNERS files (1001),
  • invalid YAML content, and
  • structurally invalid OWNERS data

do a good job of pinning down important edge cases:

  • The limit test confirms that only 1000 files are processed and that an error is logged once.
  • The invalid YAML test asserts an empty result and a single logger.exception call.
  • The invalid-structure test asserts an empty result and a single logger.error call from validation.

Together, they ensure the handler fails soft on bad or excessive inputs while keeping logging behavior well-defined.

Implement three fixes based on CodeRabbit AI review:
- Fix asyncio.to_thread mocking with async helper function
- Tighten error handling to special-case RuntimeError
- Prefix unused test parameters with underscores (ARG001)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

♻️ Duplicate comments (1)
webhook_server/libs/github_api.py (1)

41-48: Overall _clone_repository design and integration look solid, with one critical auth bug to fix.

The new clone flow is well structured: single shared clone per webhook via _repo_cloned, clear task‑scoped logging with format_task_fields, consistent use of run_command plus _redact_secrets/mask_sensitive, and correct integration into both push and PR/check_run/issue_comment paths. Config‑driven self.mask_sensitive also matches the helpers API and keeps sensitive data out of logs by default.

However, the clone URL still embeds the token as https://{token}@...:

github_token = self.token
clone_url_with_token = self.repository.clone_url.replace("https://", f"https://{github_token}@")

Per the earlier review, this pattern treats the token as the HTTP username with an empty password and can break cloning for private repositories and GitHub App/fine‑grained tokens that expect a proper username:token pair. It also diverges from GitHub’s documented x-access-token:{token} (for app installs) or api_user:{token} patterns and should be corrected before rollout. A safer approach is to build the clone URL explicitly, for example:

# Pseudocode – adjust username based on token type in your context
username = "x-access-token"  # or self.api_user if that’s what get_api_with_highest_rate_limit returns
clone_url_with_token = f"https://{username}:{github_token}@github.com/{self.repository_full_name}.git"

This change preserves the single‑clone optimization while ensuring auth works reliably for private and app‑backed repos.

Also applies to: 124-129, 172-307, 336-338, 389-391, 594-595

🧹 Nitpick comments (1)
webhook_server/tests/test_github_api.py (1)

1035-1452: New _clone_repository tests give thorough branch and error coverage.

The test_clone_repository_* set exercises success, early‑return on _repo_cloned, clone failure, checkout failure, git‑config warnings, general exceptions, and invalid argument cases. Async mocks for run_command and asyncio.to_thread are correctly awaitable, and the assertions line up with the implementation’s behavior and error messages. Only optional style nits remain (e.g., long error strings in pytest.raises and the hard‑coded /tmp in tests), which are fine to keep.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d1e1a46 and 1533f6d.

📒 Files selected for processing (2)
  • webhook_server/libs/github_api.py (7 hunks)
  • webhook_server/tests/test_github_api.py (6 hunks)
🧰 Additional context used
🧠 Learnings (8)
📓 Common learnings
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 0
File: :0-0
Timestamp: 2025-10-28T16:09:08.689Z
Learning: For this repository, prioritize speed and minimizing API calls in reviews and suggestions: reuse webhook payload data, batch GraphQL queries, cache IDs (labels/users), and avoid N+1 patterns.
📚 Learning: 2025-10-30T00:18:06.176Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 878
File: webhook_server/libs/github_api.py:111-118
Timestamp: 2025-10-30T00:18:06.176Z
Learning: In webhook_server/libs/github_api.py, when creating temporary directories or performing operations that need repository names, prefer using self.repository_name (from webhook payload, always available) over dereferencing self.repository.name or self.repository_by_github_app.name, which may be None. This avoids AttributeError and keeps the code simple and reliable.

Applied to files:

  • webhook_server/libs/github_api.py
📚 Learning: 2024-10-29T08:09:57.157Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 612
File: webhook_server_container/libs/github_api.py:2089-2100
Timestamp: 2024-10-29T08:09:57.157Z
Learning: In `webhook_server_container/libs/github_api.py`, when the function `_keep_approved_by_approvers_after_rebase` is called, existing approval labels have already been cleared after pushing new changes, so there's no need to check for existing approvals within this function.

Applied to files:

  • webhook_server/libs/github_api.py
  • webhook_server/tests/test_github_api.py
📚 Learning: 2024-10-14T14:13:21.316Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 588
File: webhook_server_container/libs/github_api.py:1632-1637
Timestamp: 2024-10-14T14:13:21.316Z
Learning: In the `ProcessGithubWehook` class in `webhook_server_container/libs/github_api.py`, avoid using environment variables to pass tokens because multiple commands with multiple tokens can run at the same time.

Applied to files:

  • webhook_server/libs/github_api.py
📚 Learning: 2025-05-10T22:07:53.544Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 773
File: webhook_server/libs/pull_request_handler.py:553-557
Timestamp: 2025-05-10T22:07:53.544Z
Learning: In the GitHub webhook server codebase, `root_approvers` and `root_reviewers` are properties of the GithubWebhook class, not methods, so they can be used with `.copy()` without parentheses.

Applied to files:

  • webhook_server/libs/github_api.py
  • webhook_server/tests/test_github_api.py
📚 Learning: 2025-10-28T13:04:00.466Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 878
File: webhook_server/libs/handlers/runner_handler.py:491-571
Timestamp: 2025-10-28T13:04:00.466Z
Learning: In webhook_server/libs/handlers/runner_handler.py, the run_build_container method is designed with the pattern that push=True is always called with set_check=False in production code, so no check-run status needs to be finalized after push operations.

Applied to files:

  • webhook_server/libs/github_api.py
📚 Learning: 2025-05-13T12:06:27.297Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 778
File: webhook_server/libs/pull_request_handler.py:327-330
Timestamp: 2025-05-13T12:06:27.297Z
Learning: In the GitHub webhook server, synchronous GitHub API calls (like create_issue_comment, add_to_assignees, etc.) in async methods should be awaited using asyncio.to_thread or loop.run_in_executor to prevent blocking the event loop.

Applied to files:

  • webhook_server/tests/test_github_api.py
📚 Learning: 2024-11-26T14:30:22.906Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 631
File: webhook_server_container/tests/test_github_api.py:321-327
Timestamp: 2024-11-26T14:30:22.906Z
Learning: In `webhook_server_container/tests/test_github_api.py`, when using `pytest.mark.parametrize` with indirect parameters, the `pytest.param` function may require nested lists to match the expected input structure.

Applied to files:

  • webhook_server/tests/test_github_api.py
🧬 Code graph analysis (2)
webhook_server/libs/github_api.py (1)
webhook_server/utils/helpers.py (4)
  • _redact_secrets (144-212)
  • format_task_fields (117-136)
  • prepare_log_prefix (555-592)
  • run_command (270-378)
webhook_server/tests/test_github_api.py (2)
webhook_server/libs/github_api.py (3)
  • process (309-506)
  • GithubWebhook (51-717)
  • _clone_repository (172-307)
webhook_server/libs/config.py (1)
  • repository_local_data (56-97)
🪛 Ruff (0.14.4)
webhook_server/libs/github_api.py

205-207: Avoid specifying long messages outside the exception class

(TRY003)


229-229: Abstract raise to an inner function

(TRY301)


229-229: Avoid specifying long messages outside the exception class

(TRY003)


291-291: Abstract raise to an inner function

(TRY301)


291-291: Avoid specifying long messages outside the exception class

(TRY003)


305-305: Redundant exception object included in logging.exception call

(TRY401)


307-307: Avoid specifying long messages outside the exception class

(TRY003)

webhook_server/tests/test_github_api.py

1374-1374: Avoid specifying long messages outside the exception class

(TRY003)


1431-1431: Probable insecure usage of temporary file or directory: "/tmp"

(S108)

🔇 Additional comments (2)
webhook_server/tests/test_github_api.py (1)

264-265: Event tests correctly stub _clone_repository without blocking real clone logic.

Using AsyncMock(return_value=None) on webhook._clone_repository in the pull_request, push, issue_comment, and check_run tests keeps the event‑flow assertions focused and avoids unnecessary git operations. The added get_github_repo_api patch and mock_repository.clone_url setup for push events are consistent with the production constructor and don’t introduce extra API calls.

Also applies to: 270-303, 310-312, 374-375, 758-761

webhook_server/libs/github_api.py (1)

703-716: Destructor docstring and cleanup behavior are aligned with the new clone strategy.

The updated __del__ docstring correctly explains that only the shared base clone directory (created via tempfile.mkdtemp) is removed here, with worktree cleanup delegated to handlers. The guarded shutil.rmtree call with best‑effort error handling is appropriate for a destructor.

Improve test code readability and portability:
- Shorten pytest.raises match strings for better readability
- Replace hard-coded /tmp paths with pytest tmp_path fixture
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
webhook_server/tests/test_github_api.py (2)

1088-1089: Consider extracting the async helper to a fixture.

The to_thread_sync helper is defined identically three times. While test isolation is valuable, extracting this to a pytest fixture would improve maintainability without sacrificing clarity.

Add a fixture at the class or module level:

@pytest.fixture
def async_to_thread_sync(self):
    """Helper to make asyncio.to_thread awaitable in tests while executing inline."""
    async def to_thread_sync(fn: Any, *args: Any, **kwargs: Any) -> Any:
        return fn(*args, **kwargs)
    return to_thread_sync

Then use it in tests:

def test_clone_repository_success(self, ..., async_to_thread_sync):
    ...
    with (
        patch("webhook_server.libs.github_api.run_command", side_effect=mock_run_command),
        patch("asyncio.to_thread", side_effect=async_to_thread_sync),
    ):

Also applies to: 1243-1244, 1312-1313


1043-1054: Consider extracting the config mock side effect to a fixture.

The get_value_side_effect function is duplicated five times with identical implementation. Extracting to a fixture would reduce duplication and make future config changes easier to maintain.

Add a fixture:

@pytest.fixture
def mock_config_side_effect(self):
    """Standard config side effect for clone tests."""
    def get_value_side_effect(value: str, *_args: Any, **_kwargs: Any) -> Any:
        config_values = {
            "mask-sensitive-data": True,
            "container": {},
            "pypi": {},
            "tox": {},
            "verified-job": True,
        }
        return config_values.get(value)
    return get_value_side_effect

Then use it in tests:

def test_clone_repository_success(self, ..., mock_config_side_effect):
    ...
    mock_config.return_value.get_value.side_effect = mock_config_side_effect

Also applies to: 1141-1152, 1195-1206, 1262-1273, 1340-1351

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1533f6d and 7490573.

📒 Files selected for processing (1)
  • webhook_server/tests/test_github_api.py (7 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 0
File: :0-0
Timestamp: 2025-10-28T16:09:08.689Z
Learning: For this repository, prioritize speed and minimizing API calls in reviews and suggestions: reuse webhook payload data, batch GraphQL queries, cache IDs (labels/users), and avoid N+1 patterns.
📚 Learning: 2025-05-13T12:06:27.297Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 778
File: webhook_server/libs/pull_request_handler.py:327-330
Timestamp: 2025-05-13T12:06:27.297Z
Learning: In the GitHub webhook server, synchronous GitHub API calls (like create_issue_comment, add_to_assignees, etc.) in async methods should be awaited using asyncio.to_thread or loop.run_in_executor to prevent blocking the event loop.

Applied to files:

  • webhook_server/tests/test_github_api.py
📚 Learning: 2024-11-26T14:30:22.906Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 631
File: webhook_server_container/tests/test_github_api.py:321-327
Timestamp: 2024-11-26T14:30:22.906Z
Learning: In `webhook_server_container/tests/test_github_api.py`, when using `pytest.mark.parametrize` with indirect parameters, the `pytest.param` function may require nested lists to match the expected input structure.

Applied to files:

  • webhook_server/tests/test_github_api.py
📚 Learning: 2024-10-29T08:09:57.157Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 612
File: webhook_server_container/libs/github_api.py:2089-2100
Timestamp: 2024-10-29T08:09:57.157Z
Learning: In `webhook_server_container/libs/github_api.py`, when the function `_keep_approved_by_approvers_after_rebase` is called, existing approval labels have already been cleared after pushing new changes, so there's no need to check for existing approvals within this function.

Applied to files:

  • webhook_server/tests/test_github_api.py
📚 Learning: 2025-05-10T22:07:53.544Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 773
File: webhook_server/libs/pull_request_handler.py:553-557
Timestamp: 2025-05-10T22:07:53.544Z
Learning: In the GitHub webhook server codebase, `root_approvers` and `root_reviewers` are properties of the GithubWebhook class, not methods, so they can be used with `.copy()` without parentheses.

Applied to files:

  • webhook_server/tests/test_github_api.py
🧬 Code graph analysis (1)
webhook_server/tests/test_github_api.py (1)
webhook_server/libs/github_api.py (3)
  • process (309-506)
  • GithubWebhook (51-717)
  • _clone_repository (172-307)
🪛 Ruff (0.14.4)
webhook_server/tests/test_github_api.py

1375-1375: Avoid specifying long messages outside the exception class

(TRY003)

🔇 Additional comments (2)
webhook_server/tests/test_github_api.py (2)

265-265: LGTM! Proper mocking of the new clone flow.

The patches for _clone_repository correctly use AsyncMock to prevent actual repository cloning during tests while maintaining the async contract. The mock repository with clone_url in the push event test provides the necessary attributes for the clone operation.

Also applies to: 311-311, 375-375, 760-760


1036-1098: Excellent test coverage for the new clone functionality!

The comprehensive test suite for _clone_repository correctly addresses the past review comment about asyncio.to_thread mocking. The async helper to_thread_sync ensures the mocked call remains awaitable while executing inline, which is the proper approach.

The test cases cover all critical paths: success, early returns, various failure modes, and input validation.

Extract to_thread_sync and get_value_side_effect helpers to pytest
fixtures in test_github_api.py to reduce code duplication.

- Add to_thread_sync fixture (previously duplicated 3 times)
- Add get_value_side_effect fixture (previously duplicated 5 times)
- Update 5 tests to use the new fixtures

Improves maintainability by centralizing helper function definitions.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
webhook_server/tests/test_github_api.py (2)

1064-1147: Success and early-return tests work correctly.

The tests properly verify the clone success path and the already-cloned optimization. Consider enhancing test_clone_repository_success to also assert that run_command was called with the expected git clone command to make the test more robust.

Example enhancement for line 1115:

# After the await gh._clone_repository(pull_request=mock_pr) call
from unittest.mock import call

# Verify clone succeeded
assert gh._repo_cloned is True

# Optionally verify the clone command was called
# This makes the test more robust by checking actual git operations
with patch("webhook_server.libs.github_api.run_command") as mock_cmd:
    await gh._clone_repository(pull_request=mock_pr)
    clone_calls = [c for c in mock_cmd.call_args_list if "git clone" in str(c)]
    assert len(clone_calls) == 1

1247-1310: Config warnings test verifies non-fatal behavior correctly.

The test properly confirms that git config failures log warnings but don't prevent successful cloning. The assertion of exactly 4 warnings matches the current implementation.

For increased robustness, consider verifying specific warning messages rather than just the count:

# Instead of just checking count
warning_messages = [str(call) for call in mock_logger.warning.call_args_list]
assert any("user.name" in msg for msg in warning_messages)
assert any("user.email" in msg for msg in warning_messages)
assert any("fetch" in msg or "PR fetch" in msg for msg in warning_messages)
assert any("remote" in msg for msg in warning_messages)
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7490573 and a9116b7.

📒 Files selected for processing (1)
  • webhook_server/tests/test_github_api.py (8 hunks)
🧰 Additional context used
🧠 Learnings (5)
📓 Common learnings
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 0
File: :0-0
Timestamp: 2025-10-28T16:09:08.689Z
Learning: For this repository, prioritize speed and minimizing API calls in reviews and suggestions: reuse webhook payload data, batch GraphQL queries, cache IDs (labels/users), and avoid N+1 patterns.
📚 Learning: 2025-05-13T12:06:27.297Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 778
File: webhook_server/libs/pull_request_handler.py:327-330
Timestamp: 2025-05-13T12:06:27.297Z
Learning: In the GitHub webhook server, synchronous GitHub API calls (like create_issue_comment, add_to_assignees, etc.) in async methods should be awaited using asyncio.to_thread or loop.run_in_executor to prevent blocking the event loop.

Applied to files:

  • webhook_server/tests/test_github_api.py
📚 Learning: 2024-11-26T14:30:22.906Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 631
File: webhook_server_container/tests/test_github_api.py:321-327
Timestamp: 2024-11-26T14:30:22.906Z
Learning: In `webhook_server_container/tests/test_github_api.py`, when using `pytest.mark.parametrize` with indirect parameters, the `pytest.param` function may require nested lists to match the expected input structure.

Applied to files:

  • webhook_server/tests/test_github_api.py
📚 Learning: 2024-10-29T08:09:57.157Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 612
File: webhook_server_container/libs/github_api.py:2089-2100
Timestamp: 2024-10-29T08:09:57.157Z
Learning: In `webhook_server_container/libs/github_api.py`, when the function `_keep_approved_by_approvers_after_rebase` is called, existing approval labels have already been cleared after pushing new changes, so there's no need to check for existing approvals within this function.

Applied to files:

  • webhook_server/tests/test_github_api.py
📚 Learning: 2025-05-10T22:07:53.544Z
Learnt from: myakove
Repo: myk-org/github-webhook-server PR: 773
File: webhook_server/libs/pull_request_handler.py:553-557
Timestamp: 2025-05-10T22:07:53.544Z
Learning: In the GitHub webhook server codebase, `root_approvers` and `root_reviewers` are properties of the GithubWebhook class, not methods, so they can be used with `.copy()` without parentheses.

Applied to files:

  • webhook_server/tests/test_github_api.py
🧬 Code graph analysis (1)
webhook_server/tests/test_github_api.py (4)
webhook_server/tests/test_helpers.py (3)
  • get_value_side_effect (174-181)
  • get_value_side_effect (197-204)
  • get_value_side_effect (220-227)
webhook_server/libs/github_api.py (2)
  • process (309-506)
  • _clone_repository (172-307)
webhook_server/libs/config.py (2)
  • get_value (99-120)
  • repository_data (53-54)
webhook_server/tests/conftest.py (2)
  • base (95-96)
  • pull_request (106-107)
🪛 Ruff (0.14.4)
webhook_server/tests/test_github_api.py

1346-1346: Avoid specifying long messages outside the exception class

(TRY003)

🔇 Additional comments (4)
webhook_server/tests/test_github_api.py (4)

78-104: LGTM! Fixtures correctly implement async mocking for clone tests.

The to_thread_sync fixture properly addresses the past review comment by making asyncio.to_thread awaitable while executing callables inline. The get_value_side_effect fixture provides appropriate test config values.


293-293: Good isolation of clone behavior in existing tests.

Properly mocks _clone_repository to prevent git operations and focus each test on its specific webhook event handling logic.

Also applies to: 339-339, 403-403, 788-788


1150-1245: Failure scenarios correctly tested.

Both clone and checkout failure tests properly verify that RuntimeError is raised with appropriate messages. The selective mocking of asyncio.to_thread (only when needed to reach the checkout step) demonstrates good understanding of the code flow.


1313-1421: Exception handling and validation tests are comprehensive.

The tests properly verify that unexpected exceptions are wrapped in RuntimeError and that missing/invalid arguments trigger ValueError. Coverage is thorough.

Note: The static analysis hint about line 1346 (long exception message) is a false positive—it's appropriate for test code to simulate various error conditions.

@myakove
Copy link
Collaborator Author

myakove commented Nov 16, 2025

/verified

@myakove
Copy link
Collaborator Author

myakove commented Nov 17, 2025

/approve

@myakove
Copy link
Collaborator Author

myakove commented Nov 17, 2025

/verified
/approve

@myakove myakove merged commit 5439c0f into main Nov 17, 2025
8 of 9 checks passed
@myakove myakove deleted the reduce-api-calls branch November 17, 2025 18:30
@myakove-bot
Copy link
Collaborator

Successfully removed PR tag: ghcr.io/myk-org/github-webhook-server:pr-906.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants