Recce address-dependabot
Use when consolidating open Dependabot PRs into a single branch. Fetches all open Dependabot PRs from the repo, applies dependency updates locally, tests for breakage, and creates a single PR that closes all Dependabot PRs.
git clone https://github.com/DataRecce/recce
T=$(mktemp -d) && git clone --depth=1 https://github.com/DataRecce/recce "$T" && mkdir -p ~/.claude/skills && cp -r "$T/.claude/skills/address-dependabot" ~/.claude/skills/datarecce-recce-address-dependabot && rm -rf "$T"
.claude/skills/address-dependabot/skill.mdAddress Dependabot
Consolidate all open Dependabot pull requests into a single tested branch and PR.
Invocation
/address-dependabot
Process
digraph address_dependabot { rankdir=TB; node [shape=box, style=filled, fillcolor=lightblue]; fetch [label="1. FETCH\nList open Dependabot PRs\nvia gh pr list", fillcolor="#ccffcc"]; collect [label="2. COLLECT\nRead each PR diff\nNote package + version changes", fillcolor="#ccccff"]; classify [label="2b. CLASSIFY\nSplit changes by target:\nroot-only vs published packages", fillcolor="#ffcccc"]; branch [label="3. BRANCH\nCreate chore/dependabot\nfrom main", fillcolor="#e6f3ff"]; apply [label="4. APPLY\nUpdate dependencies\nrespecting package boundaries", fillcolor="#fff3e6"]; migrate [label="5. MIGRATE\nCheck for breaking changes\nRun codemods if needed", fillcolor="#ffe6cc"]; test [label="6. TEST\nRun full test suite\nLint, type-check, build", fillcolor="#e6ffe6"]; green [label="All green?", shape=diamond, fillcolor="#fff3e6"]; commit [label="7. COMMIT\nStage + commit with sign-off", fillcolor="#ffe6f3"]; pr [label="8. PR\nCreate PR referencing\nall Dependabot PRs", fillcolor="#f3e6ff"]; url [label="9. OUTPUT\nPR URL", fillcolor=lightgreen]; fetch -> collect; collect -> classify; classify -> branch; branch -> apply; apply -> migrate; migrate -> test; test -> green; green -> commit [label="yes"]; green -> apply [label="no — fix issues"]; commit -> pr; pr -> url; }
Published Package Boundary Rules
This repo contains
@datarecce/ui, a published npm package consumed by external projects. Its dependencies field is a contract with consumers. This shapes how dependency updates are applied.
The Three Zones
| Zone | File | Who sees it | Bump freely? |
|---|---|---|---|
| Root app | | Monorepo only | Yes |
| Published deps | | npm consumers | No |
| Published devDeps | | Monorepo only | Yes |
| Storybook | | Monorepo only | Yes |
| Lockfile | | Monorepo only | Yes (auto) |
When to bump @datarecce/ui
dependencies
@datarecce/uiOnly raise the minimum version floor in
@datarecce/ui's dependencies when:
- The code actually uses an API introduced in the newer version
- A security fix in the dependency is critical and consumers must have it
- A bug in the old version causes
to malfunction@datarecce/ui
Do NOT bump
@datarecce/ui dependency floors just because Dependabot suggests it. Dependabot does not understand published package consumer impact.
Example
Dependabot wants
@codemirror/state: ^6.5.0 raised to ^6.6.0:
- Root
: Update tojs/package.json
-- this controls what the monorepo installs^6.6.0
: Keepjs/packages/ui/package.json
-- consumers on 6.5.x should not be forced to update unless our code requires 6.6 features^6.5.0
Reference:
js/packages/ui/DEPENDENCIES.md for the full consumer dependency contract.
Phase 1: Fetch Open Dependabot PRs
List all open PRs authored by Dependabot:
gh pr list --author "app/dependabot" --state open --json number,title,url,headRefName,body --limit 100
If no PRs found, report "No open Dependabot PRs" and stop.
Save the list -- you will need the PR numbers for the closing references in Phase 8.
Phase 2: Collect and Collate Changes
For each Dependabot PR, extract the dependency update details:
gh pr diff <number> --name-only gh pr view <number> --json body,title
Build a manifest of all required changes:
- Package name and ecosystem (npm, pip, GitHub Actions, Docker, etc.)
- Current version -> Target version
- Files affected (package.json, requirements.txt, pyproject.toml, Dockerfile, .github/workflows/*.yml, etc.)
Group updates by ecosystem for efficient batch processing.
Phase 2b: Classify Changes by Target
For each npm package update, determine which zone it belongs to:
- Read
to identify which packages arejs/packages/ui/package.json
dependencies vs devDependencies@datarecce/ui - For each Dependabot-proposed change to
dependencies:js/packages/ui/package.json- Check if the version floor bump is required (API change, security fix, bug fix)
- If NOT required: mark as "root-only" -- apply to
and lockfile, skipjs/package.json@datarecce/ui - If required: mark as "all" -- apply everywhere
- Changes to
devDependencies: apply freelyjs/packages/ui/package.json - Changes to
: apply freelyjs/packages/storybook/package.json - Changes to
(root): apply freelyjs/package.json
Output a classification table before proceeding to Phase 4:
| Package | Target Version | @datarecce/ui dep? | Bump ui floor? | Reason |
|---|---|---|---|---|
| next | 16.1.7 | No | N/A | Root-only |
| @codemirror/state | ^6.6.0 | Yes | No | No API requirement |
| some-pkg | ^2.0.0 | Yes | Yes | Security fix CVE-XXXX |
Phase 3: Create Local Branch
git checkout main git pull origin main git checkout -b chore/dependabot
Phase 4: Apply Dependency Updates
Apply updates grouped by ecosystem, respecting the classification from Phase 2b.
npm / pnpm (package.json)
For packages classified as root-only (most
@datarecce/ui deps):
# Update ONLY in root js/package.json # Edit the version specifier in js/package.json # Do NOT touch js/packages/ui/package.json dependencies
For packages classified as all (confirmed API/security requirement):
# Update in both root js/package.json AND js/packages/ui/package.json
For
@datarecce/ui devDependencies and storybook packages:
# Update freely in their respective package.json files
After all edits, regenerate the lockfile:
pnpm --dir js install
Python (requirements*.txt / pyproject.toml)
source .venv/bin/activate && which python uv lock --upgrade-package <package> # Or for pinned deps: edit pyproject.toml and run uv lock
GitHub Actions (.github/workflows/*.yml)
Edit workflow files directly to update action versions (e.g.,
actions/checkout@v4.2.0 -> actions/checkout@v4.2.1).
Docker (Dockerfile)
Edit base image tags as specified by Dependabot.
Other ecosystems
Read the Dependabot PR body for specific update instructions. Apply manually if no automated tooling fits.
Important: After applying all updates, verify lockfiles are consistent:
# For pnpm projects pnpm --dir js install --frozen-lockfile || pnpm --dir js install
Phase 5: Check for Breaking Changes and Migrations
For each major version bump:
- Check the package's CHANGELOG or release notes (use
or WebFetch)gh release list -R <owner>/<repo> - Search for migration guides
- Look for deprecated API usage in the codebase:
# Search for imports/usage of updated packages rg "<package-name>" --type-add 'src:*.{ts,tsx,js,jsx,py}' -t src - Apply any required codemods or manual migrations
Package-Specific Migrations
: Any time this package is updated, run:@biomejs/biome
cd js && pnpm biome migrate --write
This updates
biome.json schema references and applies any config migrations for the new version. Always commit the resulting biome.json changes alongside the version bump.
If a migration is unclear or risky, ask the user for clarification before proceeding.
Phase 6: Test Everything
Run the full quality gate for each ecosystem affected:
Frontend (if npm/pnpm packages changed)
# Activate nave for Node.js NAVE_DIR=~/.nave && NAVE_VER=$(cat js/.nvmrc) && \ [ -d "$NAVE_DIR/installed/$NAVE_VER/bin" ] && \ export PATH="$NAVE_DIR/installed/$NAVE_VER/bin:$PATH" cd js && pnpm lint cd js && pnpm type:check cd js && pnpm test cd js && pnpm run build
Backend (if Python packages changed)
source .venv/bin/activate && which python make format && make flake8 && make test
Infrastructure (if CDK/Docker changed)
# Verify CDK synth still works cd cdk && npx cdk synth --quiet
CI workflows (if GitHub Actions changed)
Validate YAML syntax and review action version compatibility.
If tests fail:
- Read the error carefully
- Check if it's related to the dependency update
- Fix the issue (update imports, API calls, config)
- Re-run tests
- If the fix is non-trivial, ask the user before proceeding
Phase 7: Commit
Stage all changed files and commit:
git add <specific-files> cat > /tmp/dependabot-commit-msg.txt << 'COMMIT_EOF' chore(deps): consolidate dependabot updates Updates: - <package1>: v1.0.0 -> v2.0.0 - <package2>: v3.1.0 -> v3.2.0 ... @datarecce/ui dependency floors unchanged (consumer-facing). Co-Authored-By: Claude <noreply@anthropic.com> COMMIT_EOF git commit -s -F /tmp/dependabot-commit-msg.txt
List every updated package and version range in the commit body. Note whether
@datarecce/ui dependency floors were changed and why.
Phase 8: Push and Create PR
git push -u origin chore/dependabot
Write the PR body to a temp file. The PR body MUST include
for every Dependabot PR so they auto-close when merged:Closes #<number>
cat > /tmp/dependabot-pr-body.md << 'PR_EOF' ## Summary Consolidates the following Dependabot PRs into a single tested update: - Closes #<pr1> -- <title1> - Closes #<pr2> -- <title2> - Closes #<pr3> -- <title3> ... ### Changes | Package | From | To | Ecosystem | |---------|------|----|-----------| | pkg1 | v1.0 | v2.0 | npm | | pkg2 | v3.1 | v3.2 | pip | ... ### @datarecce/ui Impact <State whether any @datarecce/ui dependency floors were changed.> <If changed, explain why (API requirement, security fix).> <If unchanged, state: "No consumer-facing dependency changes."> ## Test plan - [x] All frontend tests pass - [x] All backend tests pass - [x] Lint passes - [x] Type-check passes - [x] Build succeeds - [ ] Manual verification (if applicable) Generated with [Claude Code](https://claude.ai/code) PR_EOF gh pr create --base main \ --title "chore(deps): consolidate dependabot updates" \ --body-file /tmp/dependabot-pr-body.md
Phase 9: Output
Print the PR URL so the user can review it.
Summarize:
- Total number of Dependabot PRs addressed
- Packages updated (with version changes)
- Whether
consumer-facing dependencies were changed (and why or why not)@datarecce/ui - Any issues encountered or manual steps needed
Iron Rules
| Rule | Why |
|---|---|
| Fetch PRs first. Never guess which packages need updating. | Dependabot PRs are the source of truth. |
| Classify before applying. Determine root-only vs published for every npm change. | Blindly bumping floors breaks consumers. |
Never bump dep floors without justification. | Its are a contract with npm consumers. |
| Record all PR numbers. Every Dependabot PR must appear in the closing references. | Missing a means a stale PR lingers. |
| Test before PR. Full test suite must pass. | A broken consolidation PR defeats the purpose. |
| Ask on major bumps. If a major version has breaking changes you can't resolve, ask the user. | Silent breakage is worse than pausing. |
One branch, one PR. All updates go in , one PR. | The goal is consolidation, not more PRs. |
Temp file for PR body. Use , never inline . | Special characters break shell escaping. |
Sign-off on commits. Always flag (DCO required). | Repository policy. |
Specific git add. Stage files by name, not . | Prevents accidental inclusions. |
When Stuck
| Problem | Fix |
|---|---|
| Dependabot PR has merge conflicts | Ignore that PR's diff; apply the version update manually from the target version |
| Lockfile won't regenerate cleanly | Delete the lockfile, reinstall from scratch, verify tests pass |
| Major version bump breaks tests | Check migration guide, apply fixes, ask user if unclear |
| GitHub Actions version not found | Check the action's releases page for the correct tag |
| Mixed ecosystem updates conflict | Apply one ecosystem at a time, test between each |
Unsure if floor bump is needed | Default to NOT bumping. Check DEPENDENCIES.md. Ask the user if genuinely unclear. |