build(deps): group Dependabot updates so related bumps arrive together - #126
Merged
Conversation
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 <noreply@anthropic.com>
bgard68
added a commit
that referenced
this pull request
Aug 17, 2026
…onTests (dapper) (#129) The two test projects on this branch had drifted apart: Microsoft.NET.Test.Sdk 18.9.0 (Integration) vs 18.8.1 (Unit) xunit.runner.visualstudio 4.0.0 (Integration) vs 3.1.5 (Unit) Main has both projects on 18.9.0 and 4.0.0. This is residue from the pre-grouping era: #114 and #115 came off dependabot/nuget/tests/TodoApp.IntegrationTests/dapper branches and edited only the project each was named for, leaving UnitTests behind. The grouped sweep introduced by #126 would have caught this up - it reads dependabot.yml from the default branch, so the dapper target-branch entries apply here too. That sweep ran on 2026-08-17 as run 32038120956 and died in setup, unable to download github/dependabot-action through a 429 during the GitHub partial outage that afternoon. Dependabot's own update jobs are not retryable ("This workflow run cannot be retried"), so the sweep never produced a pull request and the drift stayed put. Hence this by hand. Nothing was broken by the split: the two test projects do not reference each other, so there is no NU1605 downgrade to trip on and dapper's CI was green throughout. The cost was quieter - unit tests were running on a test runner a major version behind the integration tests. Only UnitTests' lock file changes. `dotnet restore --force-evaluate` rewrites all six on Windows, but the other five differ by line endings alone and were reverted rather than committed as churn. Verified locally on the 10.0.100 SDK, pinned via a temporary global.json because CI floats on 10.x and the machine defaults to a 10.0.400 preview: locked-mode restore passes with no NU1004, Release build is clean under TreatWarningsAsErrors, and all 98 tests pass - including the 65 unit tests now discovered and run by the 4.0.0 runner, which is the only real risk in a major runner bump. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
bgard68
added a commit
that referenced
this pull request
Aug 17, 2026
… PRs (#130) Dependabot regenerates packages.lock.json only for the projects whose .csproj it edits; every project consuming the bumped package transitively keeps its old lock file, and locked-mode restore fails the solution with NU1004. Grouping (#126) turned five such pull requests into one - this closes the loop on that one. The failure is not hypothetical: it broke three workflows across two branches on 2026-08-17 alone, and the fix each time was the same mechanical `dotnet restore --force-evaluate` done by hand. dependabot-lockfix.yml (default branch only, by workflow_run's rules) fires on any failed API/CodeQL/container run of a dependabot/nuget/** branch, regenerates the lock files, pushes the fix, and re-dispatches every required check on the fixed commit. The three GitHub constraints that dictate the shape are documented in the file: dependabot-actor runs get read-only tokens (hence workflow_run), GITHUB_TOKEN pushes trigger no workflows (hence explicit re-dispatch), and workflow_dispatch is the documented exception that makes the re-dispatch land. api-ci-cd.yml gains a `deploy` input (default true) and the deploy gate becomes github.ref == 'refs/heads/main' || (github.event_name == 'workflow_dispatch' && inputs.deploy) Until now ANY manual dispatch deployed, so an automated checks-only rerun of a Dependabot branch would have shipped that branch to the App Service. Default true keeps the existing operator flow: Run workflow on main with the box ticked deploys exactly as before. Dependabot branches forked before this commit reject a deploy=false dispatch with 422 Unexpected inputs - a loud no-op rather than a deploy, gone as soon as branches re-fork off the updated base. Verified: both files parse; the gate expression is push-safe (inputs is empty on push events, so main still auto-deploys via the first clause). The full loop gets its first live test on the next grouped nuget PR; until then the workflow is also manually dispatchable against any branch. Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stops today's two structural failures recurring. Both produced pull requests that were born unmergeable — red on creation, with no rebase or re-run that could ever clear them.
What ungrouped updates cost today
codeql-action— 8 pull requests, all permanently red.init,analyzeandupload-sarifmust run the same version, or the job fails:Dependabot opens one pull request per sub-action, so each one creates that mismatch on its own branch. None could go green alone; whichever merged first would break CI for the others. They were closed and replaced by three hand-written commits (#118, #119, #122) that moved the sub-actions together — the only shape that works.
NuGet lock files — 4 more. One bump changes every
packages.lock.jsonthat resolves it transitively:Dependabot regenerates only the first, so
dotnet restore --locked-modefails withNU1004. Replaced by #120 and #121.The change
github-actionsnugetgithub-actionsnugetnpmgithub-actionsActions group across all update types, because the sub-action version constraint holds whether the 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 — consistent with the existing
ignoreblocks for the licence-change majors.What this does not fix
Grouping does not fully solve the NuGet case. A grouped bump can still leave a dependent project's lock file stale, needing:
and a commit of the regenerated files. What changes is that it's one pull request to fix rather than five, and the group lands consistent rather than half-applied. Saying so here rather than overselling it.
The
ignore:blocks are untouched — grouping and ignoring are independent, and an ignored major stays ignored inside a group. Verified after the edit: all three blocks still parse with their original contents.Separate finding, not fixed here
The copies of this file on
dapperandfrontendhave drifted frommain's, despitefrontend's copy stating it is "kept byte-identical to main's so the two cannot contradict each other":mainhas theignore:blocks;dapperandfrontenddo notfrontendhas the NOTE header explaining it is inert;maindoes notNo behavioural impact — Dependabot only reads the default branch, so
main's copy is the live one and its ignore rules are in force. But the byte-identical claim is currently false, and the inert copies are stale. Worth a follow-up to either sync them or delete them; I have not touched them here since this pull request targetsmainonly.🤖 Generated with Claude Code