Renovate Update Handler
Renovate branches bump versions but can't adapt code to breaking changes. This skill picks up where Renovate left off: understand what changed, research the impact, fix the code, verify it works.
Step 1: Identify the Update
Determine which branch to work on:
- If already on a
renovate/*branch, use it. - Otherwise, list the Gitlab MRs:
PROJECT=$(git remote get-url origin | sed 's|.*[:/]\([^/]*/[^/]*\)\.git$|\1|') glab api graphql -f query=" { project(fullPath: \"$PROJECT\") { mergeRequests(state: opened, first: 100) { nodes { sourceBranch webUrl description headPipeline { status } } } } }" | jq '[ .data.project.mergeRequests.nodes[] | select(.sourceBranch | startswith("renovate/")) | { branch: .sourceBranch, url: .webUrl, change: ( .description | capture("`(?<from>[^`]+)` -> `(?<to>[^`]+)`") | "\(.from) -> \(.to)" ), pipeline: (.headPipeline.status // "none") } ]'- If the CLI is not available, stop here and tell the user to install it.
- Prefer the MRs where the pipeline did not fail.
- Ask the user which MR resp. branch to process.
Checkout the branch if not already on it, then inspect what changed:
BASE_BRANCH=$(git branch -r | grep -oE 'origin/(develop|main|master)' | head -1 | sed 's|origin/||'); \
git diff $(git merge-base HEAD $BASE_BRANCH)...HEAD -- \
'*.mod' '*/go.sum' \
'*/package.json' '*/package-lock.json' '*/yarn.lock' '*/pnpm-lock.yaml' \
'*/pom.xml' \
'*/Cargo.toml' '*/Cargo.lock' \
'*/requirements*.txt' '*/pyproject.toml' '*/poetry.lock' \
'*/Gemfile' '*/Gemfile.lock' \
'Dockerfile*' '*.bicep'
Parse the diff to extract:
- Package name(s) — e.g.,
com.example:artifact,@types/react,github.com/foo/bar - Old version → New version — look for
-and+lines in version files - Which directories are affected — which manifest files changed
- Which language/ecosystem — determines which playbook to follow in Step 4 and 5
Step 2: Research Breaking Changes
For each upgraded package, search for breaking changes in the version range:
- Search for
<package> <old_version> to <new_version> breaking changes migration - Search for
<package> changelog <new_version>or<package> release notes - For major version bumps (e.g., 1.x.x → 2.x.x), always look for a migration guide
- For minor version bumps (e.g., 1.2.x → 1.3.x), always look for breaking changes in release notes
Summarize: list any renamed APIs, removed functions, changed signatures, new required configuration, or changed behavior.
If there are no breaking changes (patch bump with clean changelog), note that and proceed quickly to Step 4.
Step 3: Analyze Codebase Usage
Search the codebase for usages of the upgraded package using patterns appropriate to the ecosystem:
- Go: grep for
"<package-path>"in*.gofiles - npm/Node.js: grep for
require('<package>'),from '<package>'in*.ts,*.tsx,*.jsfiles - Maven/Java: grep for
<groupId>,<artifactId>, or the class/package name in*.javafiles - Python: grep for
import <package>orfrom <package>in*.pyfiles - Rust: grep for the crate name in
*.rsfiles
Focus on the specific APIs that changed. Identify which files need updating.
Step 4: Adapt the Code
Apply the necessary changes based on the breaking changes you found:
- Rename renamed functions/types/methods
- Update changed function signatures or call sites
- Replace removed APIs with their equivalents
- Update configuration objects to match new schemas
- Add new required imports or remove obsolete ones
Make changes surgically — only what the version change requires. Don't refactor surrounding code.
After editing, run the post-update tidy/sync step for the ecosystem (see Language Playbooks below).
Step 5: Verify Build and Tests
Run build and tests in each affected directory using the appropriate commands from the Language Playbooks below.
If tests fail:
- Read the error output carefully — it usually points directly to what still needs changing.
- Check if the failure is a compile error (API mismatch) or a test assertion (behavior change).
- Fix the issue and re-run. If stuck, search for the specific error message + package name.
Step 6: Report
When done, summarize:
- What package(s) were upgraded and by how much
- What breaking changes existed (or "none found" for clean bumps)
- What code was changed and why
- Build/test status: passing or any remaining issues
If you couldn't resolve a failure, explain what you tried and stop here.
Step 7: Push branch
You must ask for confirmation to push the branch, if not confirmed stop here.
Push changes and verify the pipeline passes:
git push
Then poll for the new pipeline to complete:
MR=<mr-iid>
# Wait for pipeline to finish (poll every 30s)
while true; do
STATUS=$(glab mr view $MR -F json | jq -r '.head_pipeline.status')
echo "Pipeline status: $STATUS"
[[ "$STATUS" != "running" && "$STATUS" != "pending" && "$STATUS" != "created" ]] && break
sleep 30
done
echo "Final status: $STATUS"
If pipeline succeeded → proceed to Step 8.
If pipeline failed → fetch logs and go back to Step 4:
PIPELINE_ID=$(glab mr view $MR -F json | jq -r '.head_pipeline.id')
# Failed direct jobs
glab api "/projects/:id/pipelines/$PIPELINE_ID/jobs" | \
jq '[.[] | select(.status == "failed") | {id, name, stage}]'
# Failed bridge jobs → child pipelines
glab api "/projects/:id/pipelines/$PIPELINE_ID/bridges" | \
jq '[.[] | select(.status == "failed") | {name, child_id: .downstream_pipeline.id}]'
# For each failed child_id:
CHILD_ID=<child_id>
FAILED_JOB_ID=$(glab api "/projects/:id/pipelines/$CHILD_ID/jobs" | \
jq -r '[.[] | select(.status == "failed")] | first | .id')
# Fetch logs
glab api "/projects/:id/jobs/$FAILED_JOB_ID/trace"
Analyze logs, fix the issue (Step 4), then repeat from top of Step 7.
Step 8: Merge
You must ask for confirmation to merge the MR, if not confirmed stop here.
Before merging:
- Check that the MR build is successful.
- There must not be any open discussions.
- Add a comment to the MR telling what you did. Use the prefix text "Generated by Claude".
- GitLab:
glab mr note <mr-id> --message "Generated by Claude: ..."
- GitLab:
then merge with: glab mr merge <mr-id> --squash
After each merge, wait 5 seconds before merging the next MR to let the platform recover:
sleep 5
If a merge fails due to conflicts, rebase the branch and retry once: Rebase locally so conflicts can be resolved:
git fetch origin
git checkout <renovate-branch>
git rebase origin/<base-branch>
# resolve any conflicts, then:
git push --force-with-lease
After the push triggers a new pipeline and it passes, re-run the merge command.
If the retry also fails, leave the MR for now and move on.
Language Playbooks
Each playbook is self-contained. Jump to the one matching the ecosystem detected in Step 1. When a project uses multiple ecosystems, apply each relevant playbook.
Go
Detect: go.mod or go.sum changed.
Post-update tidy (run in each affected module directory after editing):
go mod tidy
Verify:
go build ./...
go test ./...
Common patterns:
- Major version import path changes:
github.com/foo/bar→github.com/foo/bar/v2— update all import statements in affected.gofiles. - Minor/patch:
go mod tidyis usually all that's needed.
Maven / Java
Detect: pom.xml changed.
Post-update sync (Maven resolves dependencies on the next build; no explicit sync needed):
# Optional: pre-download deps to check for resolution errors
mvn dependency:resolve -q
Verify (in the affected module directory, or root for full build):
mvn verify
Lint only:
mvn verify -Plint
Common patterns:
- Spring Boot / Spring Framework upgrades: check for deprecated
@Bean,SecurityFilterChain, or property key changes. - Jakarta EE namespace migration (
javax.*→jakarta.*): search all.javafiles for old namespace and update imports. - Major version bumps: check for removed APIs in the library's migration guide.
pom.xmlproperty version variables: Renovate typically updates the<version>inside<dependency>blocks — confirm the right property was updated if the project uses<properties>.
npm / Node.js
Detect: package.json, package-lock.json, yarn.lock, or pnpm-lock.yaml changed.
Post-update sync (install to update lockfile and node_modules):
npm install # or: yarn install / pnpm install
Verify:
npm run build # if a build step exists
npm test # or: npm run test / npx vitest run / npx jest
npm run lint # if a lint step exists
Common patterns:
- Type-only changes (
@types/*): search for type usages that match changed types, update annotations. - CJS → ESM migration: check for
require()usage that needs to becomeimport. - Major version bumps: check
peerDependencies— other packages may need updating too. - Minor/patch:
npm installto sync lockfile, then run tests. - Peer dependency conflicts: If
npm installfails with peer dep errors, do not add--legacy-peer-deps. That flag masks real incompatibilities and can cause subtle runtime failures. Instead, identify which packages conflict and resolve them properly.
Python
Detect: requirements*.txt, pyproject.toml, poetry.lock, or setup.py changed.
Post-update sync:
pip install -r requirements.txt # or: pip install -e . / poetry install
Verify:
python -m pytest # or: python -m unittest discover
Common patterns:
- Major version bumps: check for renamed modules or removed functions in the changelog.
- Minor/patch: sync dependencies and run tests.
Rust / Cargo
Detect: Cargo.toml or Cargo.lock changed.
Post-update sync:
cargo update # syncs Cargo.lock to the new version pins
Verify:
cargo build
cargo test
Common patterns:
- Trait or API changes: compiler errors will point directly to the affected lines.
- Major version bumps: update the version in
Cargo.tomland check for API changes.
Ruby / Bundler
Detect: Gemfile or Gemfile.lock changed.
Post-update sync:
bundle install
Verify:
bundle exec rspec # or: bundle exec rake test
Adding Support for a New Ecosystem
To add a new language/ecosystem to this skill, add a new ### subsection under Language Playbooks with:
- Detect: — what file pattern signals this ecosystem
- Post-update sync — command to sync/install after version bump
- Verify — build and test commands
- Common patterns — recurring issues specific to this ecosystem
Quick Reference
No code changes needed (most minor/patch bumps):
- Run tests to confirm nothing broke
Clean patch bump checklist:
- Go:
go mod tidy→go test ./... - Maven:
mvn verify - npm:
npm install→npm test - Python:
pip install -r requirements.txt→python -m pytest - Rust:
cargo update→cargo test