deniz.in

Markets

Weather

Loading weather

· via dev.to (home feed)

A complete-looking Dependabot config watched only two of six updatable surfaces

A dev.to post shows a Dependabot config that looked done while ignoring npm subdirectories, Dockerfiles and a nested composite action, and explains why closed update PRs never come back.

A complete-looking Dependabot config watched only two of six updatable surfaces

A config that read as finished

The setup looked airtight: a dependabot.yml with two entries, pip and github-actions, both pointed at the repository root and both on a weekly schedule. According to a post on dev.to by Juan Auriti, that file served a Python project with CI, and by any casual read it seemed complete.

Then the author inventoried everything in the repository that a dependency bot could actually touch. The list ran to pyproject.toml, frontend/package., a second package. under integrations/astro-geoready/, two root Dockerfiles, a root action.yml, a composite action inside .github/actions/geo-audit/, and six workflow files. Six distinct update surfaces existed. The config watched two of them.

Why each gap was invisible

The npm gap was the most straightforward miss: Dependabot works per directory, and the config contained no npm entry anywhere, leaving an entire frontend of dependencies unwatched. The subtlety, the post notes, is that a single npm entry for /frontend still would not have covered the second package., because every directory with a manifest needs its own entry, and the nested integration package was forgotten while the config was written for the directory the author was thinking about.

The Dockerfiles were missed for a simpler reason: no docker ecosystem entry existed, so base image tags never got bumped. Both files live in the repository root, so one entry would have covered them — but zero entries covered either.

The most instructive gap was the composite action. As the post explains, a github-actions entry with directory set to / covers the workflow files under .github/workflows and a root action.yml, but it does not reach a composite action that lives in its own subdirectory. That nested file pins third-party actions exactly like any workflow, and its position inside .github/ is precisely why the author assumed it was already covered.

A two-command audit

The post prescribes a reconciliation exercise that works in any repository: one command lists every updatable manifest — package., requirements files, pyproject.toml, Gemfile, go.mod, Cargo.toml, Dockerfiles and action files — while pruning node_modules, .venv and dist so vendored manifests do not drown the output; a second command greps dependabot.yml for its package-ecosystem and directory lines. Comparing the two lists by eye exposes the difference.

The author also supplies the mapping needed to read one list against the other: pip watches the directory holding pyproject.toml or requirements files, npm and docker likewise work per directory, workflows are covered by a github-actions entry at the root, and — the case almost nobody writes down — a nested action.yml needs its own github-actions entry pointing at the action's own directory.

Closed pull requests never come back

While fixing the configuration, the author found stale pull requests from months earlier and closed several as superseded, including a patch bump already overtaken by a later minor. That triggered a second warning in the post: Dependabot does not reopen a pull request you closed, and it does not re-propose a version you rejected. Closing what looks like the old PR registers a decision about that update. If the superseding PR is not actually open, the dependency now sits at its current version indefinitely, with no open PR and no error.

The practical guidance is to close a superseded PR only after confirming the replacement exists and is open. And because dependabot.yml records nothing about closures, the only visible symptom is a dependency that stops producing PRs — which looks exactly like a dependency that is fully up to date.

Why it matters

The core problem, as the post frames it, is that dependabot.yml describes what you asked it to watch, while nothing anywhere describes what you should have asked for. GitHub raises no warning for an unwatched manifest, and adding an ecosystem is opt-in per directory, so the file reads as finished the moment it covers the ecosystems you had in mind when you wrote it.

The broader lesson generalises well beyond Dependabot: an allow-list has no error state. Reviewing it will always confirm it is correct, because it lists exactly what it lists. The only trustworthy audit comes from the outside — enumerating the full set of manifests the config is supposed to cover and checking the config against that. For teams treating automated dependency updates as a security control, a config that looks complete may quietly monitor a fraction of the dependency surface, and cleanup habits around stale PRs can freeze remaining updates without leaving a trace.

  • #dependabot
  • #github-actions
  • #dependency-management
  • #devops
  • #security

Related posts