agentsclimarketplace

Dependabot triage

Skill infohata/mind-vault/skills/dependabot-triage

Triage and batch-merge accumulated Dependabot PRs in multi-requirements-file Python repos (web + lsp + dev + per-workspace) — diff-based duplicate detection across the root vs per-workspace ecosystems, risk-tier batching for git-bisect cleanliness, worktree-isolated verification, live-staging smoke, post-merge forward-sync of remaining branches. TRIGGER when the user says "review dependabot PRs", "merge dependabot batch", "dependabot sweep", "what to do with these dep PRs", "clean up the dep updates", or asks for a roadmap merging multiple `chore(deps)` PRs. Includes the vendored-static variant — synthetic npm-ecosystem manifest tracking vendored browser assets + a re-vendor CI workflow (stuck "unstable" PRs, major-bump map src changes, re-vendor reproduction, consolidation-as-unblock).From its SKILL.md

Install
npx -y skills add infohata/mind-vault --skill dependabot-triage

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its file declares

Copied from the file, not written here

The file declares its own license as Apache-2.0. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

14.2 KB, as published. Nobody here has run it

dependabot-triage

A workflow for processing 5–20 accumulated Dependabot PRs as one coherent sweep instead of one-PR-at-a-time fatigue. The non-obvious pieces are (1) two PRs touching the same package are not necessarily duplicates when the repo has multiple requirements files served by separate dependabot ecosystems, and (2) risk-tier batching with one commit per dep preserves git bisect even when the PR ships a bundle.

Vendored-static variant. If the repo tracks vendored browser assets via a synthetic package.json (npm ecosystem) + a re-vendor CI workflow that commits refreshed static/ bytes onto the PR branch, the sweep has its own failure modes (PRs stuck unstable on stale map src paths; major bumps need a revendor-map src change, not a byte refresh; consolidation as the unblock when CI is wedged and the bot can't recreate). Read references/VENDORED_STATIC_REVENDOR.md alongside the steps below.

When to use

TRIGGER when:

  • A pile of Dependabot PRs has accumulated and the user asks for a roadmap to merge them.
  • Two PRs look like duplicates but the user is unsure whether to close one.
  • A version-scheme jump (e.g. pre-1.0 → post-1.0, or 0.0.x → 1.x.x) is mixed in with low-risk patch bumps and the user wants to know how to split them.
  • A dep PR floor-bumps a package that's actively used somewhere subtle (Vertex / OpenAI / Stripe / etc.) — needs targeted smoke beyond the test suite.

SKIP when:

  • Single Dependabot PR with no version-scheme jumps and no actively-used SDK — just merge it.
  • Repo has only one requirements file and one ecosystem — the multi-ecosystem nuance doesn't apply, simpler triage.
  • Security-only batch where every PR must merge same day — risk-tier batching is overkill, ship them as one or sequentially.

Pattern

1. Survey

gh pr list --author "app/dependabot" --state open --limit 100 \
  --json number,title,headRefName,mergeable,labels

For each PR, capture: number, title, branch path (dependabot/pip/<pkg>... vs dependabot/pip/<workspace>/<pkg>...), files touched, diff size. The branch path tells you which dependabot ecosystem opened it.

2. Detect duplicates by diff content, not titles

Multi-requirements-file repos typically configure two or more pip ecosystems in .github/dependabot.yml:

- package-ecosystem: "pip"
  directory: "/"                    # → root: requirements-web.txt, requirements-lsp.txt, …
- package-ecosystem: "pip"
  directory: "/<workspace>"         # → workspace: <workspace>/requirements-*.txt

When both ecosystems see the same package needing a bump, you get two PRs that look identical by title but are produced by independent ecosystems. Sometimes they're true duplicates (same diff, same file). Sometimes they're not (root PR bumps web + lsp + workspace; workspace-PR bumps only the workspace file).

The hard rule: never close a duplicate by title alone. Diff every candidate pair:

gh pr diff <PR_A> > /tmp/A.diff
gh pr diff <PR_B> > /tmp/B.diff
diff /tmp/A.diff /tmp/B.diff

Close only when one diff is byte-identical to the other, or a strict superset (the larger diff includes every line of the smaller diff and nothing the smaller PR uniquely contributes is omitted).

The closing comment should cite the canonical PR carrying the change forward: Closing as duplicate of #X — both update <pkg> to <ver> in <file> with identical diffs.

3. Conflict map (single-PR feasibility)

For each unique PR, record the files it touches. Build a per-file table:

FilePRs touching itLines collide?
requirements-web.txt#A, #B, #CNo (different deps)
<workspace>/requirements.txt#A, #D, #ENo

If no two PRs touch the same line of the same file, a bundled merge is conflict-free. Almost always the case for Dependabot — each PR floor-bumps one package on its own line.

4. Risk-tier classification

Slot each unique bump into one of four tiers:

TierWhatTreatment
🟢 Patch2.0.1 → 2.0.2, security-floor patchBundle freely.
🟢 Minor>=0.45 → >=0.46Bundle freely.
🟡 ModerateMany minor versions (e.g. >=0.100 → >=0.136), but pre-1.0 still pre-1.0Bundle if surface area is small; isolate if the package is load-bearing.
🔴 HighVersion-scheme jump (pre-1.0 → 1.x), API-breaking range, library actively used in subtle code paths (SDKs, parsers, embedders)Isolate into its own PR.

The dividing line for isolation is bisectability: if a regression appears post-merge, can git bisect point at the responsible commit (or PR) without ambiguity? If the high-risk bump is bundled with five low-risk ones in a single squash-merge, bisect resolves to the bundle and the operator has to manually un-bundle.

5. Bundle layout — one commit per dep

Even when bundling 5 deps into a single PR, use 5 separate commits (one per dep):

chore(deps): bump xlrd 2.0.1 → 2.0.2
chore(deps): bump uvicorn[standard] >=0.45.0 → >=0.46.0
chore(deps): bump requests >=2.32.5 → >=2.33.1
chore(deps): bump markdown >=3.7 → >=3.10.2
chore(deps): bump fastapi >=0.100 → >=0.136.1

Order low-to-high risk so the riskiest commit is on top — if a regression surfaces post-merge, git revert HEAD~N..HEAD peels off the riskier ones first. Every commit message mentions Closes #<original-PR> so the bundle PR auto-closes the dependabot PRs on merge.

The PR description lists every closed PR — gh pr merge honours Closes lines from any commit message in the PR.

Merge-strategy gotcha — non-negotiable. Per-dep commits only preserve git bisect resolution if the merge into main keeps them as separate commits. GitHub's default Squash and merge collapses every commit in the PR into a single squash-commit, defeating the entire bisect benefit. For a bundled dep PR specifically, the operator must:

  • Use Create a merge commit (branch's commits land on main verbatim, plus a merge commit), OR
  • Use Rebase and merge (branch's commits land on main linearly, no merge commit).

gh pr merge --merge (merge commit) or gh pr merge --rebase (rebase) — never gh pr merge --squash for dep-bundle PRs. If the repo is configured to allow only squash-merge, change the per-PR setting via the GitHub web UI dropdown before clicking merge, or escalate to a maintainer who can. The bisect benefit and the per-dep commit discipline are coupled; if the merge strategy can't be controlled, the per-dep commits are theatre — fall back to a single squashed commit and accept the loss of post-merge bisect.

6. Worktree-isolated verification (per RULE_parallel-worktree-docker)

Each PR (bundle and isolated-high-risk) gets its own worktree:

git worktree add ../<repo>-deps-<slug> -b chore/dependabot-<slug>-YYYY-MM origin/main

Per-worktree:

  • Sentinel .env (never copy real secrets except where targeted smoke needs them — for SDK floor bumps that exercise real APIs, copy the credentials file bytewise without reading: cp credentials.json <worktree>/path/credentials.json).
  • docker-compose.override.yml with port offset (+30000 / +50000 etc.) and non-overlapping subnet (172.30.0.0/16 etc.).
  • make build (cache-aware — pip layer is invalidated automatically because requirements file content hash changed; --no-cache only needed if a prior build with the same hash got a silent skip).
  • make migrate and make test.
  • Targeted smoke per the bumped SDK (e.g. real Vertex embedContent round-trip for google-genai; real PDF extraction for pymupdf4llm).

Resource ceiling: two parallel test stacks on a 16 GB box hits CPU contention with each running pytest -n 8. Sequential is faster end-to-end. Cooperative-pause technique: kill the lower-priority stack's pytest mid-flight (docker compose stop web celery on the worktree releases its CPU), let the higher-priority finish uncontended, then resume.

7. Live-staging smoke

After the bundle PR merges, switch staging to the next isolated-high-risk PR's branch:

make stop                                    # avoid migration drift on branch switch
git fetch origin <pr-branch>
git checkout <pr-branch>
make build                                   # pip layer rebuilds since deps changed
make start
make migrate                                 # idempotent

Hand back to the user for live verification. Per RULE_git-safety the human reviews + merges; the agent never does.

8. Post-merge forward-sync of remaining branches

When the first PR merges, the remaining isolated PRs are now behind. Forward-sync each:

git fetch origin main                        # critical — without this, origin/main is stale and the merge silently misses the just-landed merge commit (or rebased / squashed lineage, depending on which strategy the bundle PR used)
git checkout <next-pr-branch>
git merge --no-edit origin/main
git push origin <next-pr-branch>             # regular push, no force — additive merge commit

The git fetch origin main step is non-optional. The remote ref origin/main is local cache that only updates on fetch; web-UI merges on GitHub do not propagate to your local view automatically. Skip the fetch and the merge becomes a no-op (or worse: a partial sync against a stale snapshot that masks a real conflict you'll only discover at merge time).

Forward-sync is always allowed by RULE_git-safety (the feature branch's tip moves; main's doesn't). A regular git push keeps PR review threads intact; only --force-with-lease would invalidate them.

9. Documentation wrap

Open a small docs PR (or fold into the still-open dep PR) covering:

  • Devlog entry in the current month's docs/archive/YYYY-MM-DEVELOPMENT_LOG.md — what merged, what shipped isolated, operational lessons.
  • Live-doc references to bumped packages (setup guides, validation snippets, version pins) — refresh stale "ad-hoc install" notes that predate the package landing in requirements.
  • Skip historical references (archived IDEAs, past deployment-session files) — frozen by convention.

If only one isolated PR remains and its review window is short, fold the docs commit into that PR; otherwise a standalone chore/docs-dep-updates-YYYY-MM branch off main keeps it independently mergeable.

Anti-patterns

  • Title-based duplicate triage. "Same package, same version → duplicate" is wrong when ecosystems differ. Diff comparison is the only valid test.
  • Mass-bundle including version-scheme jumps. Bisect ambiguity wipes out the audit trail when the high-risk bump regresses.
  • Single-commit bundle PR. Per-dep commits preserve git bisect resolution post-merge — but only if the operator picks merge-commit or rebase-merge as the merge strategy. GitHub's default Squash and merge collapses per-dep commits into one squash-commit and silently negates the entire bisect benefit (see step 5's merge-strategy gotcha). The two pieces — per-dep commits and non-squash merge — are coupled; doing one without the other is theatre.
  • Real .env copy into a worktree. Worktree must use sentinels (per RULE_parallel-worktree-docker); only the credentials file backing a specific SDK smoke gets copied bytewise — and only into the worktree where that smoke runs.
  • Skipping live-staging for SDK bumps. Test suites typically mock SDK clients. Real-API smoke against the upgraded floor is the only signal that the new SDK shape works in production.
  • Force-pushing the dep PR mid-review. Forward-sync via git merge origin/main + regular push, not rebase + force-push. Review threads survive.
  • Driving @dependabot recreate/rebase from a bot/App actor. When a base-branch move invalidates the open dep PRs (a big merge rewrote the files they touch → conflicts that don't auto-resolve), the fix is @dependabot recreate on each — but dependabot rejects the command from a bot/App ("only users with push access can use that command"), even one with write access. A <your-app>[bot]-issued recreate is silently refused; a human push-access user must post it. Same human-only-actor class as the other App-driven-automation gaps — see ../review-loop/references/GITHUB_APP_DRIVEN_LOOP.md. (Recreate AFTER the conflicting base PRs have all merged, so the regenerated PR branches off a settled base.)

Composes with

Keep looking

Skills are one crate of 627,801. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.