From 6c7ce1f05519f66fd467fe23aad1c04a65cec788 Mon Sep 17 00:00:00 2001 From: bgard68 <30295154+bgard68@users.noreply.github.com> Date: Mon, 17 Aug 2026 09:04:39 -0500 Subject: [PATCH] build(deps): group Dependabot updates so related bumps arrive together Ungrouped, two classes of update are born unmergeable, and both cost a day on 2026-08-17. codeql-action's init, analyze and upload-sarif must run the same version or the job fails with "Loaded a configuration file for version X, but running version Y". Dependabot opens one pull request per sub-action, so each one creates that mismatch on its own branch: none can go green alone, and no rebase helps, because nothing about the base branch is wrong. Eight such pull requests were open across three branches, all permanently red, all eventually closed and replaced by three hand-written commits that moved the sub-actions together. A NuGet bump changes every packages.lock.json that resolves it transitively - five of them for one Microsoft.EntityFrameworkCore bump. Dependabot regenerates only the lock file belonging to the project it edited, so restore fails with NU1004. Four more pull requests, same fate. Actions are grouped across all update types, because the sub-action constraint holds whether the bump is major, minor or patch. NuGet and npm group minor and patch only, so a major still arrives alone and gets read properly - which is what the existing ignore blocks are already protecting against for the licence-change majors. Grouping does not fully solve the NuGet case: a bump can still leave a dependent project's lock file stale, needing `dotnet restore TodoApp.sln --force-evaluate` and a commit of the regenerated files. What it changes is that this is one pull request to fix rather than five, and the group lands consistent rather than half-applied. The ignore blocks are unchanged - grouping and ignoring are independent, and an ignored major stays ignored inside a group. Co-Authored-By: Claude Opus 5 --- .github/dependabot.yml | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index de16a5d..01b6a6d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,6 +1,26 @@ # Dependabot version updates - keeps GitHub Actions and NuGet dependencies current. # Alerts must also be enabled in the repo Settings for these to surface. # https://docs.github.com/code-security/dependabot/dependabot-version-updates +# +# Every ecosystem below is GROUPED, so related updates arrive as one pull request rather than one +# per package. That is not tidiness — ungrouped, two classes of update are born unmergeable: +# +# 1. github-actions: codeql-action's init, analyze and upload-sarif must run the SAME version, or +# the job fails with "Loaded a configuration file for version X, but running version Y". One +# pull request per sub-action means each one creates that mismatch on its own branch, so none +# of them can go green alone and no rebase can help. On 2026-08-17 there were eight such pull +# requests open across three branches, all permanently red. +# +# 2. nuget: one package bump changes every packages.lock.json that resolves it transitively - +# five of them for a single Microsoft.EntityFrameworkCore bump. Dependabot regenerates only +# the lock file of the project it edited, so `dotnet restore --locked-mode` fails with NU1004. +# Grouping does not fully solve this (a bump can still leave a dependent project's lock file +# stale, needing `dotnet restore TodoApp.sln --force-evaluate`), but it turns five broken pull +# requests into one that needs fixing once. +# +# Actions are grouped across ALL update types, because the sub-action version constraint holds +# regardless of whether a bump is major, minor or patch. NuGet and npm group minor and patch only, +# so a major still arrives on its own and gets read properly. version: 2 updates: # GitHub Actions used in .github/workflows (actions/checkout, azure/login, gitleaks, etc.) @@ -9,6 +29,9 @@ updates: schedule: interval: "weekly" open-pull-requests-limit: 5 + groups: + github-actions: + patterns: ["*"] # NuGet packages across the solution (TodoApp.sln at the repo root) - package-ecosystem: "nuget" @@ -16,6 +39,10 @@ updates: schedule: interval: "weekly" open-pull-requests-limit: 5 + groups: + nuget: + patterns: ["*"] + update-types: ["minor", "patch"] # Held at the last permissively licensed major, pending a planned refactor. # # FluentAssertions 8 moved to the Xceed Community License and MediatR 13 to a @@ -47,6 +74,9 @@ updates: schedule: interval: "weekly" open-pull-requests-limit: 5 + groups: + github-actions: + patterns: ["*"] - package-ecosystem: "nuget" directory: "/" @@ -54,6 +84,10 @@ updates: schedule: interval: "weekly" open-pull-requests-limit: 5 + groups: + nuget: + patterns: ["*"] + update-types: ["minor", "patch"] # Held at the last permissively licensed major, pending a planned refactor. # # FluentAssertions 8 moved to the Xceed Community License and MediatR 13 to a @@ -85,6 +119,10 @@ updates: schedule: interval: "weekly" open-pull-requests-limit: 5 + groups: + npm: + patterns: ["*"] + update-types: ["minor", "patch"] # Held pending the same planned refactor as the NuGet majors above. React 19 # changes rendering and effect semantics; jsdom 30 and jest-dom 8 change what # the test environment does underneath those. Upgrading them piecemeal means @@ -108,3 +146,6 @@ updates: schedule: interval: "weekly" open-pull-requests-limit: 5 + groups: + github-actions: + patterns: ["*"]