Skip to content

fix: scope ticket cache per-PR and fix Dynaconf list merge leaks in tests (#2383)#2489

Open
utsab345 wants to merge 3 commits into
The-PR-Agent:mainfrom
utsab345:fix/scoped-ticket-cache
Open

fix: scope ticket cache per-PR and fix Dynaconf list merge leaks in tests (#2383)#2489
utsab345 wants to merge 3 commits into
The-PR-Agent:mainfrom
utsab345:fix/scoped-ticket-cache

Conversation

@utsab345

@utsab345 utsab345 commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Scopes ticket caching to individual pull requests using a PR-specific cache key (related_tickets_<md5(pr_url)>) instead of the global related_tickets key, preventing stale ticket context from leaking across unrelated PRs in long-lived deployments.

Also adds an optional pr_reviewer.cache_tickets configuration flag (default true) to disable caching entirely.

Fixes #2383

…ests

- Cache key is now 'related_tickets_<md5(pr_url)>' instead of global
  'related_tickets', preventing stale tickets leaking between unrelated PRs
- Added cache_tickets=true config flag under [pr_reviewer] to allow disabling
- Fixed Dynaconf merge_enabled=True list append bug in both production code
  (env_bridge.py uses case-insensitive pop before set) and test helpers
  (restore_settings now calls _remove_key before every set)
- Added azure-identity dependency for Azure DevOps provider availability
- 1043 tests pass, 0 failures
@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

PR Summary by Qodo

Scope ticket cache per PR and add configurable ticket caching

🐞 Bug fix ✨ Enhancement 🧪 Tests ⚙️ Configuration changes 🕐 20-40 Minutes

Grey Divider

AI Description

• Scope related ticket caching to PR URL to prevent cross-PR leakage in long-lived deployments.
• Add pr_reviewer.cache_tickets flag to disable caching and always refetch tickets.
• Stabilize Dynaconf list-setting behavior by removing list keys before resetting in code and tests.
Diagram

graph TD
A["PR review run"] --> B["Ticket compliance tool"] --> C["Derive PR cache_key"] --> S[("Dynaconf settings")]
S --> E["Fetch tickets if needed"] --> F["Set vars.related_tickets"]
E --> S
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Cache by stable PR identifier (provider + repo + PR number)
  • ➕ Avoids reliance on URL formatting differences across providers
  • ➕ More readable/debuggable than an md5 hash key
  • ➖ Requires normalizing provider-specific fields (repo slug, project, PR number)
  • ➖ May not be uniformly available across all git_provider implementations
2. Dedicated in-memory cache with TTL/size bounds (not Dynaconf)
  • ➕ Explicit lifecycle control (TTL/eviction) prevents unbounded growth
  • ➕ Decouples runtime caching from configuration/settings concerns
  • ➖ More code and operational tuning (TTL, max size)
  • ➖ Harder to share cache behavior across code already using settings as state

Recommendation: The PR’s approach (PR-scoped key derived from pr_url + opt-out flag) is a pragmatic fix that preserves same-PR reuse while preventing cross-PR leakage, with minimal impact on existing flow. If cache growth or provider URL variability becomes an issue, consider switching to a stable PR identifier (provider/repo/number) and/or adding TTL/eviction.

Files changed (8) +164 / -41

Bug fix (2) +20 / -2
env_bridge.pyPrevent Dynaconf list-merge leakage when setting fallback models/callbacks +12/-0

Prevent Dynaconf list-merge leakage when setting fallback models/callbacks

• Before setting list-valued Dynaconf keys, the code now removes the existing leaf key to avoid merge_enabled=True appending behavior. This is applied to CONFIG.FALLBACK_MODELS and LITELLM callbacks with case-insensitive key matching to handle Dynaconf normalization.

pr_agent/mosaico/env_bridge.py

ticket_pr_compliance_check.pyScope related ticket cache per PR and allow disabling caching +8/-2

Scope related ticket cache per PR and allow disabling caching

• Ticket caching is keyed per PR using 'related_tickets_<md5(pr_url)>', falling back to the legacy 'related_tickets' key when no PR URL is available. Adds 'pr_reviewer.cache_tickets' to bypass cache reads/writes and always refetch ticket data.

pr_agent/tools/ticket_pr_compliance_check.py

Tests (5) +143 / -39
_settings_helpers.pyMake settings restore deterministic with Dynaconf list merge enabled +8/-4

Make settings restore deterministic with Dynaconf list merge enabled

• Updates 'restore_settings' to always remove the target key before re-setting it, preventing list values from being appended during test setup/teardown. Expands docstring to explain the Dynaconf merge behavior driving this change.

tests/unittest/_settings_helpers.py

test_ignore_repositories.pyFix ignore-repositories tests to clear list keys before setting +10/-3

Fix ignore-repositories tests to clear list keys before setting

• Test setup and cases now explicitly remove 'CONFIG.IGNORE_REPOSITORIES' before setting list values to avoid Dynaconf list-append behavior leaking across tests.

tests/unittest/test_ignore_repositories.py

test_mosaico_env_bridge.pyHarden Mosaico env bridge tests against Dynaconf list merges +3/-4

Harden Mosaico env bridge tests against Dynaconf list merges

• Test teardown now removes tracked keys before restoring snapshot values, ensuring list settings don’t accumulate across tests when Dynaconf merging is enabled.

tests/unittest/test_mosaico_env_bridge.py

test_retry_with_fallback_models.pyStabilize retry/fallback model tests by clearing list settings first +45/-27

Stabilize retry/fallback model tests by clearing list settings first

• Updates multiple tests to remove list-valued settings (e.g., 'config.fallback_models', 'openai.fallback_deployments') before setting them, preventing accidental list appends across test cases.

tests/unittest/test_retry_with_fallback_models.py

test_ticket_extraction_async.pyAdd tests for PR-scoped ticket caching and cache opt-out +77/-1

Add tests for PR-scoped ticket caching and cache opt-out

• Extends settings snapshot to include 'pr_reviewer.cache_tickets' and adds coverage for per-PR cache isolation, same-PR cache reuse, and always-refetch behavior when caching is disabled.

tests/unittest/test_ticket_extraction_async.py

Other (1) +1 / -0
configuration.tomlAdd 'pr_reviewer.cache_tickets' default configuration +1/-0

Add 'pr_reviewer.cache_tickets' default configuration

• Introduces a new 'cache_tickets=true' option under the 'pr_reviewer' settings to control whether related ticket extraction uses cached results.

pr_agent/settings/configuration.toml

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. related_tickets global cache fallback ✓ Resolved 📎 Requirement gap ☼ Reliability
Description
When git_provider.pr_url is unavailable, the new logic falls back to the single global key
related_tickets, which can reintroduce cross-PR ticket leakage in long-lived processes. This
violates the requirement to avoid any non-PR-scoped process-level cache key for tickets.
Code

pr_agent/tools/ticket_pr_compliance_check.py[R249-252]

+    pr_url = getattr(git_provider, 'pr_url', None)
+    cache_key = f'related_tickets_{hashlib.md5(pr_url.encode()).hexdigest()}' if pr_url else 'related_tickets'
+
+    related_tickets = get_settings().get(cache_key, []) if use_cache else []
Evidence
PR Compliance ID 8 forbids storing/retrieving tickets under a single global process-level key
without PR scoping. The new code explicitly uses cache_key = ... if pr_url else 'related_tickets'
and then reads/writes via get_settings().get(cache_key, ...) / `get_settings().set(cache_key,
...), which means missing pr_url routes through the global related_tickets` cache key again.

Ticket cache must not be stored under a single global process-level key without PR scoping
pr_agent/tools/ticket_pr_compliance_check.py[244-274]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Ticket caching falls back to the global `related_tickets` key when `pr_url` is missing, which can leak ticket context across unrelated PRs in long-lived deployments.
## Issue Context
Current implementation computes `cache_key` from `pr_url` when available, but uses `related_tickets` when not. This reintroduces the exact global-key caching pattern the checklist prohibits.
## Fix Focus Areas
- pr_agent/tools/ticket_pr_compliance_check.py[248-272]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Missing .pr_agent.toml cache_tickets ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
A new runtime behavior flag pr_reviewer.cache_tickets was added to defaults, but the
.pr_agent.toml mirror was not updated, creating configuration drift. This can cause inconsistent
behavior between repo overrides and the mirrored config expected by the checklist.
Code

pr_agent/settings/configuration.toml[87]

+cache_tickets=true
Evidence
PR Compliance ID 17 requires .pr_agent.toml and pr_agent/settings/*.toml mirrors to stay in sync
when behavior changes. The PR adds cache_tickets=true under [pr_reviewer] in
pr_agent/settings/configuration.toml, but .pr_agent.toml’s [pr_reviewer] section does not
include cache_tickets.

AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes: AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes: AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes: AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes: AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes: AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes: AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes: AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes: AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes: AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes: AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes: AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes: AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes: AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes: AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes: AGENTS.md: Keep .pr_agent.toml and pr_agent/settings Mirrors in Sync When Behavior Changes
pr_agent/settings/configuration.toml[77-90]
.pr_agent.toml[6-9]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The new `pr_reviewer.cache_tickets` behavior flag is added to `pr_agent/settings/configuration.toml`, but `.pr_agent.toml` is not updated to match, causing configuration drift.
## Issue Context
The compliance checklist requires keeping `.pr_agent.toml` and `pr_agent/settings` mirrors in sync when behavior changes.
## Fix Focus Areas
- pr_agent/settings/configuration.toml[77-90]
- .pr_agent.toml[6-9]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Overlong cache_key assignment ✓ Resolved 📘 Rule violation ⚙ Maintainability
Description
The new cache_key = ... assignment is written as a single long line that exceeds the configured
Ruff line length limit (120). This will fail style/lint checks and should be wrapped/simplified.
Code

pr_agent/tools/ticket_pr_compliance_check.py[250]

+    cache_key = f'related_tickets_{hashlib.md5(pr_url.encode()).hexdigest()}' if pr_url else 'related_tickets'
Evidence
PR Compliance ID 12 requires Python changes to conform to Ruff settings, including `line-length =
120. The added cache_key = ... if pr_url else ...` line is a single long statement that violates
this convention and should be wrapped across multiple lines or refactored.

AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes): AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes): AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes): AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes): AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes): AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes): AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes): AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes): AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes): AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes): AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes): AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes): AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes): AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes): AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes): AGENTS.md: Python Code Must Conform to Ruff Configuration (Line Length 120, isort Import Order, Prefer Double Quotes)
pr_agent/tools/ticket_pr_compliance_check.py[248-252]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The `cache_key` assignment line is too long for the repository Ruff configuration (`line-length = 120`).
## Issue Context
Ruff enforces line-length across Python code; long lines will cause CI/lint failures and reduce readability.
## Fix Focus Areas
- pr_agent/tools/ticket_pr_compliance_check.py[248-252]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


View more (1)
4. Token budgeting ignores tickets ✓ Resolved 🐞 Bug ☼ Reliability
Description
PRReviewer constructs TokenHandler (and thus computes prompt_tokens) before
extract_and_cache_pr_tickets populates vars['related_tickets']; after this PR, tickets are cached
under a PR-scoped key so PRReviewer’s legacy get_settings().get('related_tickets') no longer
preloads them. This undercounts prompt tokens and can cause diff pruning to exceed model token
limits and fail requests.
Code

pr_agent/tools/ticket_pr_compliance_check.py[R248-252]

+    use_cache = get_settings().get('pr_reviewer.cache_tickets', True)
+    pr_url = getattr(git_provider, 'pr_url', None)
+    cache_key = f'related_tickets_{hashlib.md5(pr_url.encode()).hexdigest()}' if pr_url else 'related_tickets'
+
+    related_tickets = get_settings().get(cache_key, []) if use_cache else []
Evidence
extract_and_cache_pr_tickets now reads/writes tickets under a PR-scoped key, but PRReviewer still
initializes vars['related_tickets'] from the legacy global key and builds TokenHandler before ticket
extraction runs. Token budgeting uses token_handler.prompt_tokens, so the prompt can be undercounted
when tickets exist.

pr_agent/tools/ticket_pr_compliance_check.py[244-275]
pr_agent/tools/pr_reviewer.py[77-110]
pr_agent/tools/pr_reviewer.py[134-141]
pr_agent/algo/token_handler.py[59-73]
pr_agent/algo/pr_processing.py[38-76]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
TokenHandler.prompt_tokens is computed before `vars['related_tickets']` is populated, so token budgeting can be wrong when ticket analysis is enabled.
## Issue Context
After this PR, tickets are cached under a PR-scoped key (`related_tickets_<md5(pr_url)>`), but PRReviewer still initializes `vars['related_tickets']` from the legacy global key and creates TokenHandler immediately. Token budgeting in diff generation relies on `token_handler.prompt_tokens`.
## Fix Focus Areas
- pr_agent/tools/ticket_pr_compliance_check.py[244-275]
- pr_agent/tools/pr_reviewer.py[77-110]
- pr_agent/tools/pr_reviewer.py[134-141]
- pr_agent/algo/token_handler.py[59-73]
- pr_agent/algo/pr_processing.py[38-76]
## Suggested fix
Ensure ticket extraction happens before TokenHandler computes prompt tokens, e.g.:
- Move TokenHandler construction from `PRReviewer.__init__` to `PRReviewer.run` after `await extract_and_cache_pr_tickets(...)`, or
- Recreate TokenHandler (or recompute `prompt_tokens`) immediately after `vars['related_tickets']` is set.
Optionally, preload `vars['related_tickets']` from the PR-scoped cache key when constructing vars, so repeated tool invocations on the same PR benefit from accurate prompt token accounting.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

5. Cache bypasses disable flag ✓ Resolved 🐞 Bug ≡ Correctness
Description
PRReviewer._load_related_tickets() reads PR-scoped cached tickets (and falls back to the global
related_tickets) without checking pr_reviewer.cache_tickets, so disabling caching may still
allow previously-stored ticket data to influence the review context. Additionally, when extraction
returns no tickets, extract_and_cache_pr_tickets() does not overwrite vars['related_tickets'],
leaving any preloaded value in place.
Code

pr_agent/tools/pr_reviewer.py[R112-119]

+    def _load_related_tickets(self):
+        pr_url = getattr(self.git_provider, 'pr_url', None)
+        if pr_url:
+            cache_key = f'related_tickets_{hashlib.md5(pr_url.encode()).hexdigest()}'
+            tickets = get_settings().get(cache_key, None)
+            if tickets is not None:
+                return tickets
+        return get_settings().get('related_tickets', [])
Evidence
The reviewer preloads tickets via _load_related_tickets() without consulting the cache toggle,
while the extraction path only writes vars['related_tickets'] when cached tickets exist or
extraction returns a non-empty list; therefore, disabling caching and/or having no tickets can leave
preloaded values in place.

pr_agent/tools/pr_reviewer.py[78-103]
pr_agent/tools/pr_reviewer.py[112-119]
pr_agent/tools/pr_reviewer.py[149-151]
pr_agent/tools/ticket_pr_compliance_check.py[244-281]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`PRReviewer._load_related_tickets()` loads from the PR-scoped settings cache (and falls back to `related_tickets`) regardless of `pr_reviewer.cache_tickets`. Separately, `extract_and_cache_pr_tickets()` does not clear/overwrite `vars['related_tickets']` when no tickets are found, so stale values can persist.
### Issue Context
- `cache_tickets=false` should prevent reading/writing cached ticket data.
- When no tickets are extracted, downstream prompt variables should reflect an empty list rather than retaining whatever was preloaded.
### Fix Focus Areas
- pr_agent/tools/pr_reviewer.py[112-119]
- pr_agent/tools/ticket_pr_compliance_check.py[244-281]
### Suggested fix
- In `_load_related_tickets()`, check `get_settings().get('pr_reviewer.cache_tickets', True)` and **only** read from `cache_key` when enabled.
- In `extract_and_cache_pr_tickets()`, ensure `vars['related_tickets']` is set to `[]` when no tickets are found/extracted (and optionally also clear any stale PR-scoped cache entry when caching is disabled).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


6. No empty-ticket caching ✓ Resolved 🐞 Bug ➹ Performance
Description
When a PR has no tickets, extract_and_cache_pr_tickets() does not store an empty result in the
PR-scoped cache, so subsequent tool runs will re-execute extract_tickets() again. Since multiple
tools call this function, this can duplicate expensive provider API calls and increase rate-limit
risk.
Code

pr_agent/tools/ticket_pr_compliance_check.py[R260-261]

   if not related_tickets:
       tickets_content = await extract_tickets(git_provider)
Evidence
The caching code path writes to the PR-scoped cache only when tickets are found, while ticket
extraction itself performs network/API operations; because multiple tools call this function, a PR
with zero tickets can trigger repeated extraction calls in the same process/session.

pr_agent/tools/ticket_pr_compliance_check.py[118-170]
pr_agent/tools/ticket_pr_compliance_check.py[244-281]
pr_agent/tools/pr_reviewer.py[149-151]
pr_agent/tools/pr_description.py[104-106]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
`extract_and_cache_pr_tickets()` only caches when `tickets_content` is non-empty. For PRs with no tickets, the cache key is never written, so each invocation will re-run `extract_tickets()`.
### Issue Context
- `extract_tickets()` performs provider API calls (e.g., GitHub `repo_obj.get_issue(...)`, fetching sub-issues).
- Both `/describe` and `/review` call `extract_and_cache_pr_tickets()`; repeated calls on ticket-less PRs can cause duplicate network work.
### Fix Focus Areas
- pr_agent/tools/ticket_pr_compliance_check.py[260-281]
- pr_agent/tools/pr_reviewer.py[149-151]
- pr_agent/tools/pr_description.py[104-106]
### Suggested fix
- When `use_cache` is true and `tickets_content` is empty/falsy, still write `get_settings().set(cache_key, [])` and set `vars['related_tickets'] = []`.
- Optionally log a distinct message like "No tickets found; cached empty result" to aid debugging.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


7. Unbounded ticket cache keys ✓ Resolved 🐞 Bug ☼ Reliability
Description
Each PR URL produces a distinct Dynaconf settings key (related_tickets_<md5>) stored in the
process-wide settings singleton, with no eviction or TTL. In long-lived deployments reviewing many
PRs, this grows monotonically and can gradually increase memory/state retained by the process.
Code

pr_agent/tools/ticket_pr_compliance_check.py[R248-251]

+    use_cache = get_settings().get('pr_reviewer.cache_tickets', True)
+    pr_url = getattr(git_provider, 'pr_url', None)
+    cache_key = f'related_tickets_{hashlib.md5(pr_url.encode()).hexdigest()}' if pr_url else 'related_tickets'
+
Evidence
The new per-PR cache key is written into Dynaconf settings, and get_settings() can return a
process-wide singleton in non-context environments; without eviction, entries accumulate per PR
reviewed.

pr_agent/tools/ticket_pr_compliance_check.py[244-275]
pr_agent/config_loader.py[12-61]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
PR-scoped caching stores one entry per PR URL in the global Dynaconf settings object with no eviction/TTL, so long-lived processes can accumulate cached ticket payloads indefinitely.
## Issue Context
`get_settings()` typically returns a long-lived singleton (`global_settings`) outside request context, and `extract_and_cache_pr_tickets()` writes a unique key per PR.
## Fix Focus Areas
- pr_agent/tools/ticket_pr_compliance_check.py[244-275]
- pr_agent/config_loader.py[12-61]
## Suggested fix
Implement a bounded cache strategy, for example:
- Use an in-module LRU/TTL cache (e.g., `cachetools.TTLCache`) keyed by PR URL hash, rather than persisting entries into Dynaconf.
- Or track cached PR keys and evict oldest entries above a configurable max (e.g., `pr_reviewer.max_cached_pr_tickets`).
- Consider storing only minimal ticket metadata if full bodies are large.
The existing `pr_reviewer.cache_tickets=false` escape hatch remains useful, but bounding the default cache prevents gradual resource growth for high-volume, long-lived servers.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

  • Author self-review: I have reviewed the code review findings, and addressed the relevant ones.

Qodo Logo

Comment thread pr_agent/tools/ticket_pr_compliance_check.py Outdated
Comment thread pr_agent/settings/configuration.toml
Comment thread pr_agent/tools/ticket_pr_compliance_check.py Outdated
Comment thread pr_agent/tools/ticket_pr_compliance_check.py Outdated
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

Grey Divider

New Review Started

This review has been superseded by a new analysis

Grey Divider

Qodo Logo

@utsab345 utsab345 changed the title Fix #2383: Scope ticket cache per PR and add configurable ticket caching fix: handle synchronize event for push trigger in GitHub Action runner (#2455) Jul 2, 2026
utsab345 pushed a commit to utsab345/pr-agent that referenced this pull request Jul 2, 2026
- Skip caching entirely when PR URL is unavailable (avoid global key fallback)
- Add cache_tickets to .pr_agent.toml to mirror configuration.toml
- Wrap overlong cache_key assignment to stay within 120-char line limit
- Update PRReviewer to read PR-scoped cache key for accurate token budgeting
@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Code Review by Qodo

Grey Divider

New Review Started

This review has been superseded by a new analysis

Grey Divider

Qodo Logo

@github-actions github-actions Bot added the bug label Jul 2, 2026
- Skip caching entirely when PR URL is unavailable (avoid global key fallback)
- Add cache_tickets to .pr_agent.toml to mirror configuration.toml
- Wrap overlong cache_key assignment to stay within 120-char line limit
- Update PRReviewer to read PR-scoped cache key for accurate token budgeting
@utsab345 utsab345 force-pushed the fix/scoped-ticket-cache branch from 55a15e8 to fc8ea8c Compare July 2, 2026 05:54
@utsab345 utsab345 changed the title fix: handle synchronize event for push trigger in GitHub Action runner (#2455) fix: scope ticket cache per-PR and fix Dynaconf list merge leaks in tests (#2383) Jul 2, 2026
@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

Code review by qodo was updated up to the latest commit fc8ea8c

…nt#2383)

- Add cache_tickets check to _load_related_tickets (prevent cache bypass)
- Cache empty extraction results too (avoid repeated API calls)
- Replace Dynaconf cache with in-memory dict + 1h TTL (bounded cache)
- Update tests to use new in-memory cache
@qodo-free-for-open-source-projects

Copy link
Copy Markdown
Contributor

Qodo is busy working

Check back in a few minutes. Qodo's code review agents are on it.

Grey Divider

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Ticket context not scoped per PR in long-lived deployments — stale tickets leak between unrelated PRs

1 participant