0077 — Automated Dependabot upgrades: comprehensive gate, then auto-merge on green
- Status: Superseded by 0079 (2026-07-06)
- Date: 2026-07-03
- Deciders: Fede
Superseded. The auto-merge-everything-on-green bet failed in production: a 41-package prod batch auto-merged into an incident (#2975) and routine bumps piled into a 28-PR red wall. Dependabot is now security-only with auto-merge disarmed — see ADR-0079. The comprehensive CI gate this ADR introduced is retained.
Context
Dependabot opens a large weekly batch of dependency PRs (20+ open at the time of writing) across six lanes: the root npm app, four nested npm manifests (agents/clara, testing-harness, mock-pms-service, tools/graphify), Python/uv (tools/agent-smith), and GitHub Actions. Every one required a human to merge — there was no Dependabot auto-merge — so they piled up.
The goal: no manual review of dependency PRs, no wall of noisy open PRs, and no regressions — all three at once. Those only co-exist if the CI gate itself becomes the reviewer, so a human doesn't have to be.
Two findings (verified) made a naive "just turn on auto-merge" unsafe:
- Green CI was a false signal for nested-package bumps. Root
ci.ymlrunsnpm ci/tsc/vitestagainst the root lockfile only. A PR bumping a nested manifest was never installed/built/tested against the bumped version — root CI went green without exercising it. Onlytools/agent-smith(viaci-smith.yml) had real scoped CI. - PR test selection was vacuous for a lockfile diff. The PR
testjob isvitest --changed <base> --passWithNoTests; a lockfile-only diff imports into no test file, so it selects ~0 tests. The realnext buildis deferred on PRs, and the full sharded suite runs only nightly/merge_group. So a bad root bump could merge on a green-but-meaningless signal.
Decision
Make the gate comprehensive first, then auto-merge everything that passes it.
- Scoped nested CI (
ci-nested.yml). Validate each nested manifest against its own deps, scoped to what's meaningful in isolation (verified on PR #2961):mock-pms-service→ install + typecheck +next build;tools/graphify→ install + import-smoke + a graphology/vendored-bundle version guard (its build needs a gitignored input);agents/clara→ install + esbuild bundle build (its typecheck needs root@/…context, already covered by root Type Check);testing-harness→ install-only resolution check (tsconfig spans rootsrc, no build/test). Triggers on every PR with internaldorny/paths-filtergating, and a single always-runNested Gateaggregator that fails closed if the detector or any lane fails — so a skipped required check can never silently open the gate. - Real gate on Dependabot PRs (
ci.yml). Run the full sharded suite + realnext buildwhen the PR author isdependabot[bot], reusing the existing requiredUnit Tests/Buildcheck names. Auth env vars get a non-empty CI placeholder fallback so Dependabot-triggered runs (which read the Dependabot secret store, not Actions secrets) stay deterministic without mirroring secrets. - Auto-merge on green (
dependabot-auto-merge.yml). Arm GitHub-native squash auto-merge on every Dependabot PR except a short blocklist (graphology). Armed, not forced — the now-comprehensive required checks must be green for it to fire, so a breaking bump never merges. Security bumps auto-merge on green too: speed-to-patch is the point and the gate protects against regression. This supersedes the earlier "human is the merge gate" stance (Smith/axios PR #1728) for dependency PRs specifically, justified by the gate now being real. - Risk-matched grouping (
dependabot.yml). Per-directory, dev/prod-split groups so batches are homogeneous and independently mergeable (replaces the 50-update cross-directory mega-PR).graphologyisignored — it's exact-pinned and coupled to a hand-vendored viewer bundle. - Janitor (separate agent-smith track). A weekly Smith activity keeps the PR list empty: rebase stale PRs, auto-defer (close) bumps stuck red past a window, and roll them into a Slack/Trello digest. Smith already has an authed
ghCLI, Temporal crons, and Slack/Trello surfaces; the janitor needs only write-scope (list/comment/close), nevergh pr merge, so it stays inside Smith's existing "stop at mergeable" policy.
Consequences
- Activation step (manual, outside the code): add the
Nested Gatecheck tomain's required status checks so nested-package bumps actually gate auto-merge. Until then, auto-merge is gated only by the existing required checks (which now do real work on Dependabot PRs for root +agents/clara). - The full suite + real build now run on every Dependabot PR, including nested-only bumps where root deps didn't change (a mild over-run vs. the 2026-06-20 cost cut). Bounded by weekly volume; scoping it to root-manifest changes is a possible follow-up.
- A breaking major (e.g. TypeScript 6 across manifests) simply fails CI and never merges; the agent-smith janitor defers it, optionally handed to Smith's existing fix-PR sweep. No human review queue.