Skip to content

fix(resolver): bypass cooldown for transitive deps when top-level pin exists#1154

Merged
mergify[bot] merged 1 commit into
python-wheel-build:mainfrom
LalatenduMohanty:cooldown_bug_ogx_api
May 14, 2026
Merged

fix(resolver): bypass cooldown for transitive deps when top-level pin exists#1154
mergify[bot] merged 1 commit into
python-wheel-build:mainfrom
LalatenduMohanty:cooldown_bug_ogx_api

Conversation

@LalatenduMohanty
Copy link
Copy Markdown
Member

@LalatenduMohanty LalatenduMohanty commented May 14, 2026

When a package is both a top-level exact-pinned requirement (e.g., foo==1.0) and a transitive dependency of another package (e.g., bar depends on foo>=0.9), the cooldown check was blocking the transitive resolution even though the user explicitly approved that version via the pin. This could cause version downgrades or resolution failures.

resolve_package_cooldown() now checks the dependency graph for an existing top-level exact pin before enforcing cooldown on transitive dependencies.

Closes: #1153

… exists

When a package is both a top-level exact-pinned requirement (e.g.,
`foo==1.0`) and a transitive dependency of another package (e.g.,
`bar` depends on `foo>=0.9`), the cooldown check was blocking the
transitive resolution even though the user explicitly approved that
version via the pin. This could cause version downgrades or resolution
failures.

`resolve_package_cooldown()` now checks the dependency graph for an
existing top-level exact pin before enforcing cooldown on transitive
dependencies.

Closes: python-wheel-build#1153
Co-Authored-By: Claude <claude@anthropic.com>
Signed-off-by: Lalatendu Mohanty <lmohanty@redhat.com>
@LalatenduMohanty LalatenduMohanty requested a review from a team as a code owner May 14, 2026 17:23
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 14, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR extends the cooldown bypass logic in resolve_package_cooldown() to handle transitive dependencies that match a top-level exact pin. When resolving a non-top-level requirement, the resolver now checks the dependency graph for root-level edges with RequirementType.TOP_LEVEL and an exact == pin for the same package; if found, it bypasses cooldown by returning None. The change includes two comprehensive test cases validating both the direct bypass logic and end-to-end resolution behavior when a transitive dependency matches an already-approved top-level pin.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: bypassing cooldown for transitive dependencies when a top-level pin exists, which is the core functionality added in this PR.
Linked Issues check ✅ Passed The PR implementation directly addresses all coding requirements from issue #1153: detecting top-level exact-pinned entries in the dependency graph and bypassing cooldown for transitive resolutions when such pins exist.
Out of Scope Changes check ✅ Passed All changes are scoped to the cooldown bypass logic for transitive dependencies with top-level pins, plus corresponding test coverage. No extraneous modifications detected.
Description check ✅ Passed The pull request description clearly explains the problem (cooldown blocking transitive dependencies despite top-level exact pins) and the solution (checking dependency graph for existing pins).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

@LalatenduMohanty LalatenduMohanty changed the title fix(resolver): bypass cooldown for transitive deps when top-level pin… fix(resolver): bypass cooldown for transitive deps when top-level pin exists May 14, 2026
@mergify mergify Bot added the ci label May 14, 2026
Copy link
Copy Markdown
Contributor

@rd4398 rd4398 left a comment

Choose a reason for hiding this comment

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

LGTM!

@mergify mergify Bot merged commit db8a160 into python-wheel-build:main May 14, 2026
39 checks passed
@ryanpetrello
Copy link
Copy Markdown
Contributor

ryanpetrello commented May 14, 2026

I'm late to party on review here, but just thinking out loud.

@LalatenduMohanty @rd4398

I think it makes sense to always do this, but I'm wondering about edge cases?

  - top-level: foo==1.5, transitive: foo — bypass lets 1.5 be a candidate. Resolver picks it. Correct.
  - top-level: foo==1.5, transitive: foo>=1.0 — same thing.
  - top-level: foo==1.5, transitive: foo>=1.5 — same thing.
  - top-level: foo==1.5, transitive: foo>=2.0 — dependency conflict, cooldown is irrelevant

Comment thread src/fromager/resolver.py
logger.info("cooldown bypassed as the top-level requirement uses == pin")
return None

if req_type != RequirementType.TOP_LEVEL:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: this graph lookup (get_root_node + get_outgoing_edges) runs for every non-top-level resolution even when ctx.cooldown is None. We could add an early if ctx.cooldown is None: return None guard at the top of the function to skip both this check and the existing top-level pin check when cooldown isn't active.

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.

Cooldown check blocks transitive dependency that matches top-level exact pin

4 participants