Skip to content

New source config cooldown path has gaps compared to legacy resolve_package_cooldown() #1252

Description

@smoparth

CooldownMixin._cooldown in _resolver.py will replace resolve_package_cooldown() in resolver.py when the new source config is wired in. The new path has gaps compared to legacy path.

Bug 1: None vs 0 conflated

_cooldown uses if not self.min_release_age, which is True for both None and 0. Both return None to the provider.

None should mean "inherit global cooldown"
0 should mean "disable cooldown for this package"
Legacy path:

if per_package_days is None:
return global_cooldown # inherit
if per_package_days == 0:
return None # disable

Bug 2: Global cooldown not inherited

When min_release_age is None (not set in YAML), the legacy path returns ctx.cooldown (the global value from --min-release-age). The new _cooldown property returns None, ignoring the global entirely. A package with no per-package override will have no cooldown even when the global is set.

Bug 3: TOP_LEVEL equality pin bypass missing

Legacy path skips cooldown if the requirement is top-level with an exact == pin. The new path doesn't check this. _cooldown is a property on the Pydantic model with no access to req_type. The resolver_provider() method receives req_type but doesn't use it for cooldown.

Bug 4: bootstrap_time not shared

Legacy path reuses the global Cooldown.bootstrap_time when creating per-package overrides. This ensures all packages resolved in a single run use the same reference timestamp. The new _cooldown creates a fresh Cooldown with bootstrap_time=now() each time, so different packages get different cutoffs.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions