From cam-fleet-ops
Add Dependabot config to a fleet of repos, triage auto-PRs that fail CI, and manage the auto-PR lifecycle. Covers: auto-detecting lockfile ecosystem (npm/pnpm/yarn/bun/composer/pip), writing `.github/dependabot.yml` per-repo, understanding why Dependabot PRs often fail CI (peer-dep conflicts, major version bumps), and the "billing cap vs Dependabot PR" classification trick. From a real 35-repo Dependabot rollout.
How this skill is triggered — by the user, by Claude, or both
Slash command
/cam-fleet-ops:dependabot-opsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Dependabot is GitHub's auto-PR tool for dependency updates. Most fleets have it off by default; adding it to a fleet is a single-config-per-repo job, but the operations don't end there. Dependabot PRs often fail CI on auto-generated dependency bumps, creating noise in the fleet status that has to be triaged.
Dependabot is GitHub's auto-PR tool for dependency updates. Most fleets have it off by default; adding it to a fleet is a single-config-per-repo job, but the operations don't end there. Dependabot PRs often fail CI on auto-generated dependency bumps, creating noise in the fleet status that has to be triaged.
This skill covers the full lifecycle: add the config, understand the PR failures, triage them, and decide which to merge vs close.
.github/dependabot.yml)The config goes in .github/dependabot.yml at the repo root. The structure:
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
open-pull-requests-limit: 5
groups:
production-dependencies:
dependency-type: "production"
development-dependencies:
dependency-type: "development"
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-major"]
For PHP repos:
- package-ecosystem: "composer"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 3
For Python repos:
- package-ecosystem: "pip"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 3
Before writing the config, check which lockfiles exist:
ecosystems = set()
for path in ["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb"]:
if file_exists(repo, path):
ecosystems.add("npm") # all JS ecosystems use "npm" in dependabot
if file_exists(repo, "composer.json"):
ecosystems.add("composer")
for pip_file in ["requirements.txt", "pyproject.toml", "Pipfile"]:
if file_exists(repo, pip_file):
ecosystems.add("pip")
break
If no lockfiles are found (e.g., a repo with just static HTML files), skip Dependabot — it won't have anything to update.
Dependabot's automation creates a PR with the new version. It doesn't fix anything else. The PR's CI runs against:
The new version might:
prisma.config.ts)The auto-PR's CI failure is expected in many cases. The fix:
This is a fleet-audit pattern. When you see a red CI Build run, classify it:
Check the head branch:
dependabot/, the failure is on a Dependabot auto-PR. Not a real issue — main branch is unaffected.main or master, the failure is on the main branch. Real issue.Check the run conclusion:
cancelled → newer push superseded this run. Not an issue.failure with annotation spending limit needs to be increased → billing cap. Not a code issue, user must increase limit.failure with real error in the log → real code issue. Needs source fix.Combine for the final classification:
main branch + spending limit annotation = billing capmain branch + real error = real source issuedependabot/* branch + any failure = Dependabot PR noise, can ignore for nowWhen a Dependabot PR fails CI:
For 35+ repos in a fleet:
import json, base64, subprocess
def get_dependabot_config(repo):
"""Auto-detect which lockfiles exist and return the right config."""
ecosystems = set()
for path in ["package-lock.json", "pnpm-lock.yaml", "yarn.lock", "bun.lockb"]:
r = subprocess.run(["gh", "api", f"/repos/camster91/{repo}/contents/{path}"], ...)
if r.returncode == 0:
ecosystems.add("npm")
r = subprocess.run(["gh", "api", f"/repos/camster91/{repo}/contents/composer.json"], ...)
if r.returncode == 0:
ecosystems.add("composer")
for pip_file in ["requirements.txt", "pyproject.toml", "Pipfile"]:
r = subprocess.run(["gh", "api", f"/repos/camster91/{repo}/contents/{pip_file}"], ...)
if r.returncode == 0:
ecosystems.add("pip")
break
if not ecosystems:
return None
config = "version: 2\nupdates:\n"
for eco in sorted(ecosystems):
if eco == "npm":
config += ''' - package-ecosystem: "npm"
directory: "/"
schedule: { interval: "weekly", day: "monday" }
open-pull-requests-limit: 5
groups:
production-dependencies: { dependency-type: "production" }
development-dependencies: { dependency-type: "development" }
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-major"]
'''
elif eco == "composer":
config += ''' - package-ecosystem: "composer"
directory: "/"
schedule: { interval: "weekly" }
open-pull-requests-limit: 3
'''
elif eco == "pip":
config += ''' - package-ecosystem: "pip"
directory: "/"
schedule: { interval: "weekly" }
open-pull-requests-limit: 3
'''
return config
# Apply to all repos in a fleet
for repo in fleet_repos:
config = get_dependabot_config(repo)
if not config:
continue # skip repos with no lockfiles
# Get the default branch
r = subprocess.run(["gh", "api", f"/repos/camster91/{repo}"], ...)
branch = json.loads(r.stdout).get("default_branch", "main")
# PUT the config
body = {
"message": "ci: add Dependabot config (auto-detected package managers)",
"content": base64.b64encode(config.encode()).decode(),
"branch": branch,
}
r = subprocess.run(["gh", "api", "-X", "PUT", f"/repos/camster91/{repo}/contents/.github/dependabot.yml", "--input", json.dumps(body)], ...)
applied += 1
This pattern was used to add Dependabot to 35 repos in a fleet in one batch.
version-update:semver-major ignores — you might want major version bumps eventually, just not right now. Use groups: to batch updates instead.open-pull-requests-limit too high — 10+ open PRs become unmanageable. Stick to 3-5.Each Dependabot PR generates a CI run. If you have 35 repos with weekly Dependabot, that's:
GitHub Pro gives 2,000 min/month. A 35-repo fleet with Dependabot enabled is roughly 8-15% of the monthly budget. Within reason, but worth knowing.
.github/dependabot.yml in the repoopen-pull-requests-limitfleet-ci-audit — Use this first to identify which repos in the fleet need Dependabot. The audit's "no Dependabot" category is your work list.spending-limit-detector — Before adding Dependabot, check the spending limit. Dependabot PRs eat into your monthly Actions minutes.github-fleet-lint-cleanup — When Dependabot PRs fail CI on lint, the lint-cleanup pattern helps diagnose the root cause.prisma-fleet-migration — Dependabot often flags Prisma major version bumps. The lazy-proxy migration is the right response.Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub camster91/cam-fleet-bundle --plugin cam-fleet-ops