Skip to content

Read npm min-release-age from .npmrc and apply as cooldown#15132

Open
yeikel wants to merge 1 commit into
dependabot:mainfrom
yeikel:npm-min-release-age
Open

Read npm min-release-age from .npmrc and apply as cooldown#15132
yeikel wants to merge 1 commit into
dependabot:mainfrom
yeikel:npm-min-release-age

Conversation

@yeikel
Copy link
Copy Markdown
Contributor

@yeikel yeikel commented May 25, 2026

Summary

min-release-age setting in .npmrc prevents installing any package version younger than N days. Dependabot was unaware of this setting, so it could try to open PRs for versions that would violate user's configuration

This pull request reads min-release-age from .npmrc and uses its value as a lower bound on every update_cooldown field. If no update_cooldown is configured in dependabot.yml, one is created from the npmrc value. If one is already configured, the npmrc value only raises individual fields that are below it

Fixes #14151

Merge semantics

Scenario Result
No update_cooldown in dependabot.yml default_days = .npmrc value
dependabot.yml default_days >= npmrc value all fields unchanged (debug log only)
dependabot.yml default_days < npmrc value default_days raised to npmrc floor; warn logged
semver_*_days field < npmrc value that field raised to npmrc floor; per-field warn logged
include/exclude patterns always dropped; npm applies min-release-age globally with no per-package filtering

The npmrc value acts as a floor: it can only raise cooldown values, never lower them.

Anything you want to highlight for special attention from reviewers?

.npmrc and dependabot.yml cooldown settings don't translate cleanly. This is, for the most part, because Dependabot support features that npm does not support yet

  • npm's min-release-age is a global, unconditional install-time constraint with no per-package filtering

  • dependabot.yml supports include/exclude patterns and per-semver thresholds that have no npm equivalent. When both are present, the choices are: honour dependabot.yml as-is and risk Dependabot proposing versions npm install immediately rejects; or use min-release-age as a floor and silently drop incompatible dependabot.yml features

This PR takes the second path on the grounds that a broken install is worse than a dropped preference, with a log warning to surface the trade-off. A third option such as failing the pipeline on conflict seems more damaging.

How will you know you've accomplished your goal?

  • Both existing an new tests pass
  • Tested via the Dependabot CLI

Reproducer: https://github.com/yeikel/dependabot-issue-14151

Without this change, dependabot happily suggests the latest version of my dependency at test(3.5.34) ignoring my min-release-age configuration :

image

However, after this change, it suggests the version the configuration expects(3.4.27):

https://github.com/yeikel/dependabot-issue-14151/blob/bfc9181bbe5b21e8c9f2a8b0853506164946cdab/.npmrc#L1

image

Checklist

  • I have run the complete test suite to ensure all tests and linters pass.
  • I have thoroughly tested my code changes to ensure they work as expected, including adding additional tests for new functionality.
  • I have written clear and descriptive commit messages.
  • I have provided a detailed description of the changes in the pull request, including the problem it addresses, how it fixes the problem, and any relevant details about the implementation.
  • I have ensured that the code is well-documented and easy to understand.

@yeikel yeikel force-pushed the npm-min-release-age branch 4 times, most recently from 3404fc2 to e5daee2 Compare May 25, 2026 20:15
- `default_days` now uses `[existing.default_days, npmrc_days].max` so
  the npmrc value never lowers a higher value set in dependabot.yml
- Conflict warning is conditional: only fires when at least one cooldown
  field is actually below the npmrc threshold; otherwise logs at debug
- Removed `default_days` from the per-field override-warning loop;
  the top-level conflict message covers it; per-field messages are for
  the three `semver_*_days` fields only
- `.npmrc` filename match tightened to `File.basename(f.name) == ".npmrc"`
  to avoid false matches like `foo.npmrc`
- Extracted `log_npmrc_cooldown_conflicts` and `merge_cooldown_with_npmrc_floor`
  helpers (satisfies Rubocop Metrics cops)
- TODO comment added for Yarn 4.10+ `npmMinimalAgeGate` follow-up

Spec changes:
- "when explicit update_cooldown already exceeds the npmrc floor": asserts
  default_days stays unchanged and no warning is logged
- "when dependabot.yml default_days is below the npmrc floor": expects
  conflict warning once and per-field warnings for semver fields only
- Replace `instance_variable_get(:@update_cooldown)` with `checker.update_cooldown`
@yeikel yeikel force-pushed the npm-min-release-age branch from e5daee2 to b07b1cf Compare May 25, 2026 20:24
@yeikel yeikel marked this pull request as ready for review May 25, 2026 20:41
@yeikel yeikel requested a review from a team as a code owner May 25, 2026 20:41
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.

Convert npm min-release-age to equivalent Cooldown options

1 participant