Skip to content

chore(deps): dependabot catch-all groups let one breaking major block every other update in the ecosystem #871

Description

@isadeks

Component: tooling (.github/dependabot.yml)

Describe the bug

Every ecosystem in .github/dependabot.yml funnels all updates into a single catch-all group and allows only one open PR:

open-pull-requests-limit: 1
groups:
  all-npm:
    patterns: ["*"]

Because update-types is unset, the group takes majors, minors and patches together. So one breaking major poisons every other bump in that ecosystem, and open-pull-requests-limit: 1 means Dependabot cannot open a second PR for the safe remainder while the poisoned one is open. The ecosystem is then stuck until a human resolves the major.

That is not hypothetical — it is the current state of two ecosystems:

Adopting TypeScript 7, cdk-nag 3 and mcp 2 each needs its own migration — AGENTS.md still documents the stack as TypeScript 6.x — so these majors will sit for a while, and every minor and patch in those two ecosystems is blocked behind them for as long as they do.

Second defect: a documented cross-ecosystem lockstep has no guard

agent/pyproject.toml:19 records an invariant:

"claude-agent-sdk==0.2.110",  # ... (bundles claude CLI 2.1.191;
                              # kept in lockstep with the npm CLI
                              # pin in the Dockerfile, #215)

and agent/Dockerfile:90 is the other half:

npm install -g @anthropic-ai/claude-code@2.1.191

#859 bumps the SDK to 0.2.148 and touches only agent/pyproject.toml and agent/uv.lock. The Dockerfile pin stays at 2.1.191, so the bundled CLI and the installed CLI diverge, and the inline comment asserting 2.1.191 becomes false in the same commit. Dependabot cannot see this: the two halves live in different ecosystems (uv and docker/npm), and no CI check compares them.

The config already handles exactly this shape for the Cedar engines — reciprocal ignore entries for cedarpy and @cedar-policy/cedar-wasm at lines 48 and 71, each with a comment pointing at the decision. claude-agent-sdk ⊥ the Dockerfile CLI pin is the same class of coupling and is unprotected.

Third: runtime interpreter bumps arrive as digest refreshes

#827 is titled as a 3-update docker group. Two entries are a jdxcode/mise digest refresh and golang 1.26.41.27.1 in a build-only stage. The third moves the agent's runtime interpreter:

agent/Dockerfile:29  python:3.13-slim -> python:3.14-slim

build (agentcore) is green, so this builds — but three other places still say 3.13: agent/mise.toml:4 (python = "3.13", so local dev and the container would run different minors), agent/pyproject.toml:184 (python-version = "3.13", the ty/ruff target, so type-checking would stop describing the runtime), and the CVE-patching comment at agent/Dockerfile:44, which names the python:3.13-slim tag explicitly. A runtime minor bump for a C-extension-heavy dependency set deserves its own PR landing together with those pins.

Expected behavior

A breaking major in one dependency delays only that dependency. Minors and patches keep flowing on the weekly schedule. Dependencies with a documented cross-ecosystem lockstep are not bumped unilaterally.

Proposed solution

(Revised — the original wording here proposed a second <eco>-majors group per ecosystem. That raises the open-PR ceiling from 4 to 8, and there is a subtler problem with it: see below. #872 takes the approach in this revision.)

  1. Exclude majors from the grouped PRignore version-update:semver-major for * in each ecosystem, leaving the groups untouched. The steady state stays at one grouped PR per ecosystem, the same count as today, but nothing can wedge it.

    Note why the obvious alternative is wrong: restricting the group to update-types: ["minor", "patch"] leaves majors ungrouped, and an ungrouped update gets its own PR — so that would produce one PR per major dependency, strictly worse than today. The ignore is what holds the count down.

  2. Raise open-pull-requests-limit to 2 — one grouped PR plus a slot of headroom so a lone ungrouped or security PR cannot starve the group.

  3. Add an ignore for claude-agent-sdk mirroring the cedarpy treatment, with a comment naming the Dockerfile pin and feat: Bedrock cost attribution — session tags, request metadata, and operator FinOps guidance #215.

  4. Add an ignore for python major/minor on the docker ecosystem, referencing chore(agent): upgrade Python 3.13 → 3.14 #105, so the interpreter bump is always a deliberate change while digest and patch refreshes keep flowing.

Accepted trade-off: a major that fixes an advisory will not arrive as a PR. Detection is unaffected — //:security:deps fails the build on any advisory regardless of Dependabot — but the upgrade is driven by hand, and majors are tracked as issues instead. Today's config does not avoid that work; it hides it behind a PR that cannot merge while still costing a weekly rebase and a full CI run.

Once (1)–(2) land, closing #859 and #860 lets Dependabot regenerate one grouped PR per ecosystem carrying only routine updates, recovering the 45 npm and 6 python bumps currently blocked.

Other information

The cooldown: default-days: 7 and commit-message.prefix settings are working as intended and are unchanged by the above.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    v1Version 1

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions