Skip to content

Cap the update level for the whole scan with a command line flag #146

Description

@fniessink

What

Add a --max-update-level {major,minor,patch} option (default major, meaning no restriction) that holds back updates above the given level for every dependency in the scan. --max-update-level minor is equivalent to marking every reference with # update-time: allow[minor-update], the same flag-to-marker duality as --allow-image-digest-drift. Builds on the level-based directives: issue-level-update-bounds.md.

Why

The level-based markers express per-reference policy, but a repository-wide policy shouldn't require sprinkling the same comment over every file. A global cap also unlocks a workflow the markers can't express: run update-time --max-update-level minor on a schedule for routine low-risk updates, and run it bare, on demand, when ready to take the majors — separating major updates from minor and patch updates, without editing any file.

Proposed behaviour

  • Option: --max-update-level {major,minor,patch}, default major. minor keeps minor and patch updates and holds back major ones; patch keeps only patch updates. Levels are positional, exactly as defined in Hold back major or minor updates with level-based directives #145, including the caveat that "stay on the CPython 3.12 line" needs patch, not minor.
  • Per-reference markers win: a reference's own bound — literal or level-based — replaces the global level rather than intersecting with it (an intersection would contradict the single-bound-per-reference rule), and an ignore or ignore[update] marker holds the reference back entirely, as always. In particular, # update-time: allow[major-update] opts a single reference back out of the global cap.
  • The redundancy warning becomes flag-aware: allow[major-update], redundant without the flag, is meaningful under --max-update-level minor and must not be warned about then. Redundancy is judged against the effective global level, not in isolation.
  • Scope: the cap applies to every reference whose new version Update-time selects itself — Docker images, GitHub Actions, requirements.txt dependencies, and jsDelivr npm URLs (plus .python-version files and pre-commit hooks once those land). For jsDelivr URLs, which the markers cannot reach, the flag is the first way to bound updates at all. Updates delegated to npm, pnpm, and uv are unaffected: those already stay within the ranges declared in package.json and pyproject.toml, which is the same control expressed in the ecosystem's own syntax, and the help text says so.
  • Everything else is unchanged: the cooldown applies to whichever version the cap selects, the digest or commit SHA is still pinned for it, and the staleness check is never affected by the cap — a dependency whose major update is held back is still reported when its newest release goes stale.

Considered alternative

Boolean flags mirroring the marker names (--ignore-major-updates, --ignore-minor-updates): self-documenting individually, but they allow the nonsensical combination of both at once and need prose to explain that ignoring minor updates implies ignoring major ones. The single value-taking option encodes that monotone closure in its own semantics.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions