Skip to content

Commit 8b98af3

Browse files
Add NuGet package maintenance script and update tasks for automation
1 parent 8d19704 commit 8b98af3

File tree

6 files changed

+141
-1
lines changed

6 files changed

+141
-1
lines changed

.config/dotnet-tools.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"version": 1,
3+
"isRoot": true,
4+
"tools": {
5+
"dotnet-outdated-tool": {
6+
"version": "4.6.9",
7+
"commands": [
8+
"dotnet-outdated"
9+
]
10+
}
11+
}
12+
}

.vscode/tasks.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,23 @@
6060
"Release"
6161
],
6262
"problemMatcher": "$msCompile"
63+
},
64+
{
65+
"label": "update-nuget-packages",
66+
"type": "shell",
67+
"command": "pwsh",
68+
"args": [
69+
"-NoProfile",
70+
"-ExecutionPolicy",
71+
"Bypass",
72+
"-File",
73+
"${workspaceFolder}/scripts/update-nuget-packages.ps1"
74+
],
75+
"options": {
76+
"cwd": "${workspaceFolder}"
77+
},
78+
"detail": "Runs the repository NuGet upgrade script (dotnet-outdated + build/test).",
79+
"problemMatcher": "$msCompile"
6380
}
6481
]
6582
}

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@ This solution consists of three focused NuGet packages:
167167
- **[📖 Implementation Guide - API Consumers](docs/implementing-api-consumer.md)** - Guide for teams consuming APIs
168168
- **[� Versioned API Client Pattern](docs/implementing-versioned-api-client.md)** - Advanced pattern for multi-version API support
169169
- **[�📐 API Design Patterns](docs/api-design-v2.md)** - Understanding the underlying design principles
170+
- **[🧰 NuGet Package Maintenance](docs/package-maintenance.md)** - How Dependabot handles upgrades and how to run the manual script when needed
170171

171172
## Authentication
172173

docs/package-maintenance.md

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# NuGet Package Maintenance
2+
3+
The repository targets both `net9.0` and `net10.0`, so dependency updates must keep the two TFMs in sync. This page captures the automation that already exists and the non-standard manual process that can be used when Dependabot cannot unblock an update quickly enough.
4+
5+
## Default Path: Dependabot
6+
7+
- `.github/dependabot.yml` schedules daily `nuget` scans over `src/`, so each library receives upgrade PRs automatically.
8+
- Accept Dependabot PRs whenever possible. They already run the full CI matrix, ensuring `net9.0`/`net10.0` builds remain healthy.
9+
- If a dependency requires coordination across multiple repositories or needs additional context (e.g., SDK preview alignment), leave the manual flow below as a last resort and document the rationale in the PR.
10+
11+
## Non-Standard Manual Script
12+
13+
Only run the script when you need an expedited update outside Dependabot’s cadence (e.g., urgent security patch or coordinating a batch upgrade).
14+
15+
- **VS Code task (recommended):** `Terminal → Run Task… → update-nuget-packages`. This task shells into PowerShell, invokes the script with execution policy bypassed, and streams the build/test output in the integrated terminal.
16+
- **Direct PowerShell:** `pwsh ./scripts/update-nuget-packages.ps1`
17+
18+
What the script does:
19+
20+
1. Restores the local `.config/dotnet-tools.json` manifest and installs `dotnet-outdated-tool`.
21+
2. Executes `dotnet-outdated --upgrade` against `src/MX.Api.Abstractions.sln`, ensuring both target frameworks receive the same versions (the tool does not touch lock files; this repo relies on PackageReference flow only). Any tool failure stops the script immediately so you can resolve TFM-specific issues before proceeding.
22+
3. Builds and tests the solution (skipping `IntegrationTests`) so regressions in either `net9.0` or `net10.0` are caught immediately.
23+
24+
### Optional Parameters
25+
26+
- `-VersionLock <None|Major|Minor>` – default `Major`; stay within the current major line for shared dependencies unless you intentionally want cross-major upgrades (`None`).
27+
- `-IncludePrerelease` – allow preview packages (useful when the SDK is on a preview track).
28+
- `-IncludeTransitive` – also upgrade transitive dependencies when the solution depends on them indirectly.
29+
- `-SkipVerification` – avoid the build/test phase (only when another pipeline will run immediately). When using the VS Code task, pass extra switches by editing `.vscode/tasks.json` or running the script directly.
30+
31+
### Manual Command Output
32+
33+
The script updates project files in-place; review the diffs locally and open a single PR that summarizes the context (why Dependabot was bypassed, verification performed, etc.). Always follow up with the standard `dotnet build` / `dotnet test` tasks if you skipped verification.
34+
35+
## Framework-specific packages
36+
37+
Some dependencies publish different major versions per TFM (e.g., ASP.NET test host packages). Use conditional `ItemGroup` blocks to pin the correct line for each target framework:
38+
39+
```xml
40+
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
41+
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.11" />
42+
</ItemGroup>
43+
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
44+
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.0" />
45+
</ItemGroup>
46+
```
47+
48+
- Dependabot and `dotnet-outdated` evaluate each block independently, so they still surface upgrades within the respective major line.
49+
- Keep shared dependencies (xUnit, Moq, etc.) in the unconditional `ItemGroup`; only split packages that genuinely need divergent versions.
50+
- When onboarding a new TFM, duplicate the conditional block and set the appropriate version before running the script or Dependabot.

scripts/update-nuget-packages.ps1

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
[CmdletBinding()]
2+
param(
3+
[string]$SolutionPath = "src/MX.Api.Abstractions.sln",
4+
[ValidateSet("Major", "Minor", "None")]
5+
[string]$VersionLock = "None",
6+
[switch]$IncludePrerelease,
7+
[switch]$IncludeTransitive,
8+
[switch]$SkipVerification
9+
)
10+
11+
Set-StrictMode -Version Latest
12+
$ErrorActionPreference = "Stop"
13+
14+
$repoRoot = Resolve-Path (Join-Path $PSScriptRoot "..")
15+
$solutionFullPath = Join-Path $repoRoot $SolutionPath
16+
17+
if (-not (Test-Path $solutionFullPath)) {
18+
throw "Solution file '$SolutionPath' was not found at '$solutionFullPath'."
19+
}
20+
21+
Push-Location $repoRoot
22+
try {
23+
Write-Host "Restoring local dotnet tools (dotnet-outdated)" -ForegroundColor Cyan
24+
dotnet tool restore | Out-Null
25+
26+
$outdatedArgs = @(
27+
"tool", "run", "dotnet-outdated", $SolutionPath,
28+
"--upgrade",
29+
"--version-lock", $VersionLock
30+
)
31+
32+
if ($IncludeTransitive) {
33+
$outdatedArgs += "--include-transitive"
34+
}
35+
36+
if ($IncludePrerelease) {
37+
$outdatedArgs += "--pre-release"
38+
}
39+
40+
Write-Host "Upgrading NuGet packages while respecting multi-target frameworks (net9.0/net10.0)" -ForegroundColor Cyan
41+
& dotnet @outdatedArgs
42+
43+
if (-not $SkipVerification) {
44+
Write-Host "Running dotnet build to validate all target frameworks" -ForegroundColor Cyan
45+
& dotnet build $SolutionPath --configuration Release
46+
47+
Write-Host "Running dotnet test (excluding IntegrationTests)" -ForegroundColor Cyan
48+
& dotnet test $SolutionPath --configuration Release --filter "FullyQualifiedName!~IntegrationTests"
49+
}
50+
}
51+
finally {
52+
Pop-Location
53+
}

src/MX.Api.IntegrationTests/MX.Api.IntegrationTests.csproj

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
</PropertyGroup>
1010

1111
<ItemGroup>
12-
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.11" />
1312
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
1413
<PackageReference Include="Moq" Version="4.20.72" />
1514
<PackageReference Include="xunit" Version="2.9.3" />
@@ -23,6 +22,14 @@
2322
</PackageReference>
2423
</ItemGroup>
2524

25+
<ItemGroup Condition="'$(TargetFramework)' == 'net9.0'">
26+
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.11" />
27+
</ItemGroup>
28+
29+
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
30+
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="10.0.0" />
31+
</ItemGroup>
32+
2633
<ItemGroup>
2734
<ProjectReference Include="..\MX.Api.Abstractions\MX.Api.Abstractions.csproj" />
2835
<ProjectReference Include="..\MX.Api.Client\MX.Api.Client.csproj" />

0 commit comments

Comments
 (0)