Bulk Merging Dependabot Pull Requests

I recently enabled Dependabot to help track updates to my dependencies and keep them current. The user experience has been a pleasant one with simple configuration and timely pull requests but I’ve quickly come to dread one specific thing - the Updating Of The Rubocop. I have quite a lot of ruby bases repositories and I like to use rubocop as a basic safety net and second set of eyes so it’s in heavy use, which is great until the version changes.

It starts a low rumble of thunder in the CI system and appears as a sudden stampede of emails -

GMail inbox with lots of unread TravisCI emails

Opening up GitHub reveals the horrifying truth, Issues have been opened and assigned! Dun Dun Dun!

GitHub UI showing a raised Issue

I only have about 80 repos and I find the idea of going to each issue, reviewing, approving, and merging to be numbing. Luckily, my technical co-workers, who have an eye watering 1,600 repo in their main GitHub organisation have already done their suffering and written the Bulk Merger to solve this problem. Unfortunately this code is currently tied to GDS in a few small places, so I’ve forked it and removed the hard coded values so anyone can run it while we decide how to feed those changes into upstream. For now you can grab Deans Forked Bulk Merger.

In the below example I’ll show how to install it and manage the merging of a new version of the rubocop gem. GDS are big fans of rbenv so I’ll be using that to manage the dependencies the bulk merger needs.

# get the code
git clone https://github.com/deanwilson/bulk-merger.git
cd bulk-merger

# install the specific ruby version - skip this is using system ruby
rbenv install
Installing ruby-2.6.5...

# get the dependencies
bundle install

We are now ready to start using the tool. First I set my GITHUB_TOKEN so I can avoid being throttled by the API limits

export GITHUB_TOKEN=111111111111111111111111111111111111111

I can now use the review command to list all the relevant pull requests and review them in preparation for merging.

$ GITHUB_TOPIC=NONE GITHUB_USER=deanwilson ./review rubocop
Searching for PRs containing 'rubocop'
Found 22 unreviewed PRs:

- 'Update rubocop requirement from ~> 0.77.0 to ~> 0.78.0' (https://github.com/deanwilson/puppet-lint-world_writable_files-check/pull/18) 
- 'Update rubocop requirement from ~> 0.77.0 to ~> 0.78.0' (https://github.com/deanwilson/puppet-lint-no_erb_template-check/pull/13) 
... snip ...

Being quite an untrusting person I clicked through to a small sample of the PRs to ensure everything looked OK. At $WORK we have our repos configured to reject merges unless the tests pass so our test harnesses help reduce the risk of a bad bulk update. I can now run the merge command and have all the requests merged to master in a single command.

GITHUB_TOPIC=NONE GITHUB_USER=deanwilson ./merge rubocop

This will list all the founds PRs, show which of them have been reviewed, and prompt me to merge them. Even with forking upstream and adding the ability to specify a user using this tool was much faster than clicking through the web UI by hand and less likely to result in me missing a few.

This kind of small incidental tool is a great example of the benefits an organisation can provide when working in the open. We’d never be able to get time allocated to write this as a deliberately available thing but by scratching our own itch in a publicly visible way (odd imagery) other people can easily benefit from the idea and the code.

I’ve included an example of the whole workflow over a reduced set of gem version bumps

Screen grab of running bulk-merge against rubocop