Is GitHub Dependabot Now Enterprise Ready with Grouped Updates?

Is GitHub Dependabot Now Enterprise Ready with Grouped Updates?

Discovering Dependabot many years ago was one of those moments of incredible excitement. It was not the same kind of excitement as when you finished creating and publishing that new feature to production, or even the same as when you got some amazing feedback about how your software helped save someone a ton of time… or maybe even changed their lives. This type of excitement is what you get when you realize someone else’s code is going to either change the way you develop and/or increase your quality of life. It is the epiphany that you get when you realize that this is the way it should have been all along… but for some reason wasn’t, and you could never place your finger on it. Dependabot was a breath of fresh air, in a world of DevSecOps that felt like my responsibility and requirements were ever-increasing. Dependabot can make at least a sliver of that pain go away.

This excitement grew even larger with GitHub’s acquisition of the Dependabot product and its now native integration and migration away from Dependabot-Preview to the Dependabot that we know today. GitHub took a good deal longer than I think most of us expected to make the transition, and for a good chunk of time, there were key features missing that should have been part of the MVP.

Almost There

With GitHub native integration of Dependabot, SPS Commerce very quickly took the first steps to offer standardized integration, examples, and organizational secrets for interacting with our private registries. From a Developer Experience perspective, we wanted all our internal teams and engineers to take advantage of this simple yet effective security best practice. Unfortunately, like anything at scale, it was not that simple. We continually found that Dependabot adoption would get hung up on integrating with the last bits of our teams’ workflows. Consistent adoption struggles:

  • Noise – The number of Pull Requests opened with a default configuration is rather noisy. Our initial approach had many teams configuring for daily or even hourly updates. This type of update felt like we should be able to just accept a Pull Request or two with Dependabot updates whenever they materialize. What we didn’t account for was the volume of updates that can happen, especially for certain libraries like AWS or other auto-incremented patches. This continually focused our teams on merging relatively low-value Pull Requests and shifting their context in and out of the real work. Not to mention it was annoying!
  • Granularity – Obviously the noise and annoyance level was related to the number of Pull Requests, or rather that EVERY package would be a separate branch. To make matters worse, by default, the pull request max limit was set to 10, and after closing the initial ten it felt like an endless task for 10 more in their place to open (not knowing how many dependency issues there might be on a large project). Merge conflicts are pretty regular as well, forcing you to merge one pull request and then wait for the rest to rebase and revalidate if there is a conflict.
  • Maturity – I blogged about this years back as well, but the lack of a maturity configuration is also unfortunate. The idea is that before accepting a new version of a package, I want to ensure it is at least a certain number of days old. This prevents me from having to update one patch update every day all week and instead just notify when a more stable patch version is available. This can be simulated in some cases by moving to a monthly update interval.
  • CI/CD – When opening 10, 20, or even 30 Pull Requests for dependency updates, especially if the update interval is monthly, this kicks off a decent-sized number of queued jobs for CI/CD. In some cases, the validation is pretty trivial. Multiply that across all the repositories in the organization and there is a substantial increase in expenditure and potential delay in compute resources that can impact other work. Additionally, after you merge one of the pull requests, the 29 other branches are rebased by default forcing them to kick off the CI status check all over again.
  • Package Groupings – Some packages that you have installed simply have to be updated together. The separate packages can often share a unified version number, but only updating one results in a build failure as both need to be updated together. This typically requires manual resolution on the Pull Request branch.

GitHub released more organizational governance controls. This enabled security teams to easily and broadly turn on Dependabot Security Alerts across the organization (backed by the Dependency Graph feature), also providing real-time SBOMs. Controls are available to turn on Dependabot Security Updates across the organization as well, though we found out very quickly the effect of this seemingly innocent addition had a large negative impact. While security alerts simply inform you about critical security issues, security updates create Pull Requests. Enabling across the organization in a single button click created Pull Requests at lightning speed across over 4,000 repositories, with each Pull Request potentially firing CI/CD integration requests and queued jobs for validation. While our centralized CI/CD platform was chugging through the queue we reached numerous limits and throttling, one in particular, in the CI/CD platform getting throttled for GitHub API requests for source code.

The adoption of Dependabot Security Alerts was global, but actual Security Updates are hit or miss without solving some of the notable issues above first.

Grouped Updates Arrive… Finally

In my blog post a few years ago on migrating to Dependabot Native, I talked about the need for Grouped Updates. This single feature can alone have a substantial impact on several of the problems we have discussed so far. Given the impact of this feature, we evaluated the possible migration to Renovate as an alternative that already has support for Grouped Updates (and plenty of other features). Ultimately we decided to wait for the feature from GitHub in an attempt to curb our tool sprawl and keep the ecosystem and scope tight. GitHub had originally indicated in our chats that they expected a beta of Grouped Updates would be available by the end of the year 2021, which unfortunately was not the case as it was substantially delayed for a good 18 months past that, but is finally available and in GA!

With grouped updates available, custom patterns can now enable any grouping of wildcarded package names that you might need, with built-in support for production and development dependency ecosystems. Grouped updates have a major impact on just about every issue area noted above:

  • Noise – Creating two or three groups for your packages still provides you with the flexibility to make intentional updates, but also means you’ll never have more than 2 or 3 Pull Requests open for Dependabot. In fact, you could go with one catch-all “*” pattern and only ever have one Pull Request with updates.
  • Granularity – With only a couple of Pull Requests, merging and handling conflicts on changed dependencies is much more straightforward, especially if you are not waiting for rebasing or other workflow.
  • CI/CD – Again limited branches and pull requests mean the usage of compute is MUCH MORE efficient in the broader organization as multiple dependency changes are validated in a single build as opposed to individually. This also means when there is a failure it’s a bit more difficult to debug. Like anything you will want to find the balance on granularity.
  • Package Groupings – This is inherently solved as the primary purpose of this feature.

Issues around package maturity have not been solved, but I have had a lot of success in moving to monthly update intervals, which seems reasonable for a regular update cadence of the dependencies. With Grouped Updates, I may feel more comfortable moving to weekly update intervals.

Here is an example of a typical .NET6 API dependabot.yml:

version: 2
updates:
  - package-ecosystem: nuget
    directory: /
    schedule:
      interval: monthly
    open-pull-requests-limit: 30
    groups:
      test-dependencies:
        patterns:
        - "MSTest.*"
        - "Microsoft.NET.Test.*"
        - "NSubstitute*"
        - "NetArchTest*"
      core-dependencies:
        patterns:
        - "SPSCommerce.*"
        - "Microsoft.Extensions.*"
        - "Microsoft.AspNetCore.*"
        update-types:
	- "minor"
	- "patch"
      otel:
        patterns:
        - "OpenTelemetry*"
      aws:
        patterns:
        - "AWSSDK.*"
    ignore:
    - dependency-name: "Microsoft.Extensions.*"
      update-types: ["version-update:semver-major"]
    - dependency-name: "Microsoft.AspNetCore.*"
      update-types: ["version-update:semver-major"]
    - dependency-name: "System.Text.Json"
      update-types: ["version-update:semver-major"]

This creates 4 standard pull request types that can be opened, with logical grouping in each. Open Telemetry (“otel”) and AWS packages are numerous and are helpful to position as a single Pull Request. But most importantly all Microsoft Extensions and .NET system references will be upgraded together. In my example, the intent is to only update framework packages for “minor” or “patch” updates as explicitly not upgrading beyond the existing LTS Support is desirable (see Update Types). All of these complexities can now be codified generically in the Dependabot configuration. Nice!

Enterprise Ready?

With the initial governance controls now available with grouped updates, I am hoping that Dependabot Version Updates is now more appropriately enterprise-ready than prior initiatives. We will continue to provide training, and recommendations and encourage the adoption of Dependabot at SPS Commerce given the impact on both security and Developer Experience, using the launch of Grouped Updates as a change event to re-engage in the initiative. I am hoping this is the first of many great new features and updates coming to Dependabot.

  • Maturity – Would love to have that maturity filter still!
  • Organizational Rollout – Enhanced governance considerations for how full version updates could be rolled out in broader sets of repository groupings from a security team perspective.
  • Shared Configuration – Maybe alongside organizational rollout, the ability to share pieces of or the entire configuration for the dependabot.yml (i.e. templates or workflows) would go a long way to aid the rollout and maintenance of the ecosystems.
  • Merge Queues – With GitHub Merge Queues available, first-class support for automated merge queues of version updates might be an advantage.

I believe also that Dependabot can and should play a major role in an organization’s Inner Source strategy. With the distribution of internal shared libraries, it is essential to keep new versions flowing and reduce the support of multiple active versions in a timely manner. Communication of updates is difficult but can be very simple and effective using Dependabot (for release notes as well). More to come in the future about SPS Commerce and its growing Inner Source strategy and best practices.

What other features and enhancements would you like to see as part of Dependabot?

Leave a Reply