Skip to content

build: prevent version drift with CPM and Dependabot grouping - #135

Merged
Cat5Dog2 merged 2 commits into
mainfrom
chore/central-package-management
Aug 5, 2026
Merged

build: prevent version drift with CPM and Dependabot grouping#135
Cat5Dog2 merged 2 commits into
mainfrom
chore/central-package-management

Conversation

@Cat5Dog2

@Cat5Dog2 Cat5Dog2 commented Aug 5, 2026

Copy link
Copy Markdown
Owner

Merge order: #133, then this PR.
The base here is chore/deps-2026-08 (#133). Because the repository has delete_branch_on_merge: false, the base will not retarget to main automatically once #133 lands — GitHub only retargets when the head branch is deleted. It has to be pointed at main by hand, and since full-regression is a strict required check, this branch then needs re-basing onto the updated main and a fresh CI run.

#134 has been folded into this PR and closed, following review. That removes the stacked-base problem and cuts production deploys from three to two.

Corrections from review

Three claims in the original version were wrong. Thanks for catching them.

1. "Dependabot does not watch dotnet-tools.json" — incorrect

It has since 2024: discovery in dependabot-core#8889, update analysis in dependabot-core#10269.

The real reason dotnet-ef was stranded on 10.0.9 is that the scan directories were only /src/** and /tests/**, and the manifest sits at the repository root. Adding "/" brings it into scope, and adding dotnet-ef to the aspnetcore-efcore group means it now moves in the same PR as EF Core.

2. Grouping every GitHub Action together is too broad

The original rationale — that a group was needed to update one action across several workflows — was simply wrong. Dependabot already emits one PR per action spanning every workflow that uses it; #130 updated setup-dotnet across five files with no grouping at all.

A group would only make unrelated major bumps share a PR and a CI failure, so the group is removed. Only the limit increase (2 → 5) remains.

3. "Updates that hit the limit are dropped and never return" — overstated

The accurate statement is that PR creation is deferred until a slot frees up, and that the deferral is never reported. Corrected in both the commit messages and this description.

Why both CPM and the Dependabot config are needed

The drift here came in three distinct kinds:

Kind Example Fixed by grouping Fixed by CPM
Release train drift Design/Tools 10.0.10 vs SqlServer 10.0.9
Cross-project drift Web.Tests 18.6.0 vs E2ETests 18.7.0
Out-of-scan drift dotnet-ef 10.0.9 ❌ — needs "/"

Grouping lowers how often versions are allowed to diverge, but the structure that permits divergence survives. Under CPM a version exists in exactly one place, so cross-project drift becomes unrepresentable rather than merely unlikely.

Changes

Commit 1 — CPM

  • New Directory.Packages.props at the repository root (20 PackageVersion entries)
  • Version= attributes stripped from the three project files (26 PackageReference entries)

Commit 2 — Dependabot configuration

  • "/" added to the nuget scan directories
  • nuget groups added: aspnetcore-efcore (including dotnet-ef), test-tooling, azure
  • nuget limit 5 → 10
  • github-actions limit 2 → 5, with no group

Design decision: literal versions, not shared MSBuild properties

Conventional CPM style would bundle the 10.0.x packages behind something like $(MicrosoftPlatformVersion). This PR writes literals instead.

The indirection is only worth having if Dependabot can resolve and rewrite it. If it cannot, the failure mode is precisely the silent one this whole exercise is about: no PR gets opened, and nothing announces it. Keeping ASP.NET Core and EF Core moving in step is already the aspnetcore-efcore group's job, so the property buys little and risks a lot. The reasoning is recorded in a comment at the top of Directory.Packages.props.

Verification

Resolved versions are identical to #133, confirmed with dotnet list package across all three projects. The CPM migration changes no versions.

  • scripts/build.ps1 — 0 warnings, 0 errors
  • scripts/test.ps1240 passed, 0 failed
  • scripts/test-e2e.ps1 -InstallBrowsers8 passed, 0 failed
  • scripts/format.ps1 — OK

With CPM enabled, any PackageReference still carrying a Version= fails the build with NU1008, so the build itself catches an incomplete migration.

To confirm after merging

Parsing the YAML does not prove that discovery and grouping behave as intended. Once this reaches the default branch, check the Dependabot Update logs to confirm both Directory.Packages.props and dotnet-tools.json are actually detected.

The manifest is at the repository root rather than .config/dotnet-tools.json, so that placement in particular is worth confirming empirically. If it goes undetected, moving it under .config/ is the fallback.

🤖 Generated with Claude Code

@Cat5Dog2
Cat5Dog2 force-pushed the chore/deps-2026-08 branch from b4680b2 to d5de28f Compare August 5, 2026 01:56
@Cat5Dog2
Cat5Dog2 force-pushed the chore/central-package-management branch from 6847c0e to ed9108c Compare August 5, 2026 02:00
@Cat5Dog2 Cat5Dog2 changed the title build: centralize package versions with CPM build: 依存管理の再発防止(CPM + Dependabot 設定) Aug 5, 2026
@Cat5Dog2 Cat5Dog2 changed the title build: 依存管理の再発防止(CPM + Dependabot 設定) build: prevent version drift with CPM and Dependabot grouping Aug 5, 2026
@Cat5Dog2
Cat5Dog2 changed the base branch from chore/deps-2026-08 to main August 5, 2026 03:16
Cat5Dog2 and others added 2 commits August 5, 2026 12:16
Moves all PackageVersion entries into a root Directory.Packages.props and
strips the inline versions from the three project files.

The drift this repo just hit was cross-project: Web.Tests sat on Test SDK
18.6.0 while E2ETests was on 18.7.0, and nothing in the build objected.
Under CPM that state is unrepresentable, because the version exists in
exactly one place. Dependabot grouping reduces how often the versions are
allowed to diverge; CPM removes the ability to express the divergence at
all. They address the same failure from different ends.

Versions are written as literals rather than shared MSBuild properties,
which departs from the usual CPM style. A $(Var) indirection is only
worth having if Dependabot can resolve and rewrite it, and if it cannot,
the failure is the silent one this whole exercise is about: no PR gets
opened and nothing announces that. Keeping ASP.NET Core and EF Core
moving together is already handled by the aspnetcore-efcore group, so the
indirection buys little and risks a lot.

Resolved versions are unchanged from the previous commit: verified with
dotnet list package across all three projects. Build clean, 240 unit
tests, 8 Playwright E2E tests, dotnet format --verify-no-changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Three changes to the nuget ecosystem, plus a correction to an earlier
claim of mine.

Scan directories gain "/". Both the CPM manifest added in the previous
commit and the existing dotnet-tools.json live at the repository root,
which /src/** and /tests/** do not cover. This, not a gap in Dependabot,
is why dotnet-ef sat on 10.0.9 while EF Core moved: Dependabot has
discovered and analyzed dotnet-tools.json since 2024
(dependabot-core#8889 and #10269). An earlier commit message in this
branch stated the opposite and was wrong.

Grouping ASP.NET Core, EF Core and dotnet-ef together is the substantive
fix. They ship as one train, and splitting them into separate PRs is what
let Design/Tools drift ahead of SqlServer. Major bumps stay ungrouped so
something like ImageSharp 3.x to 4.0 still lands on its own.

The limit goes from five to ten. At the limit Dependabot defers opening
the remaining PRs to a later run rather than dropping them, but nothing
reports the deferral, so four packages sat on 10.0.9 with no PR and no
signal.

github-actions is deliberately left ungrouped. Dependabot already emits
one PR per action across every workflow that uses it, which is what #130
did for setup-dotnet across five files, so a group adds nothing there
while making unrelated major bumps share a PR and a CI failure.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@Cat5Dog2
Cat5Dog2 force-pushed the chore/central-package-management branch from ed9108c to 425ea66 Compare August 5, 2026 03:17
@Cat5Dog2
Cat5Dog2 merged commit 0712d73 into main Aug 5, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant