Skip to content

Commit 598d8e9

Browse files
authored
Merge pull request #44 from johnlokerse/johnlokerse/dotnet-upgrade
Upgrade to dotnet 10 and added `upgrading-dotnet` skill
2 parents 2738d0b + 494e5c2 commit 598d8e9

File tree

5 files changed

+314
-14
lines changed

5 files changed

+314
-14
lines changed
Lines changed: 293 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,293 @@
1+
---
2+
name: upgrading-dotnet
3+
description: Upgrade .NET projects to newer versions. Use when upgrading TargetFramework in csproj/vbproj/fsproj files, migrating between .NET versions, configuring global.json, pinning SDK versions, updating CI/CD pipelines for .NET, or troubleshooting .NET upgrade issues.
4+
---
5+
6+
# .NET Project Upgrade Skill
7+
8+
## When to Use This Skill
9+
10+
- Upgrading project target frameworks (e.g., `net6.0``net9.0`)
11+
- Updating .NET SDK versions across projects
12+
- Migrating multiple projects in a solution
13+
- Version pinning and controlled rollouts
14+
- Updating CI/CD pipelines for new .NET versions
15+
- Preparing hosting environments for new runtimes
16+
17+
## Quick Start: Basic Upgrade Process
18+
19+
### 1. Identify Projects to Upgrade
20+
21+
List all project files that need upgrading:
22+
23+
```bash
24+
find . -name "*.csproj" -o -name "*.vbproj" -o -name "*.fsproj"
25+
```
26+
27+
### 2. Update Project Files (Minimum Required Change)
28+
29+
Open each project file (`.csproj`, `.vbproj`, or `.fsproj`) and update the `<TargetFramework>` property:
30+
31+
**Before:**
32+
33+
```xml
34+
<PropertyGroup>
35+
<TargetFramework>net8.0</TargetFramework>
36+
</PropertyGroup>
37+
```
38+
39+
**After (upgrading to .NET 9):**
40+
41+
```xml
42+
<PropertyGroup>
43+
<TargetFramework>net9.0</TargetFramework>
44+
</PropertyGroup>
45+
```
46+
47+
For multi-targeted projects, update `<TargetFrameworks>`:
48+
49+
```xml
50+
<PropertyGroup>
51+
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
52+
</PropertyGroup>
53+
```
54+
55+
### 3. Restore Workloads
56+
57+
If using specialized workloads (MAUI, ASP.NET, etc.):
58+
59+
```bash
60+
dotnet workload restore
61+
```
62+
63+
### 4. Build and Test
64+
65+
```bash
66+
dotnet build
67+
dotnet test
68+
```
69+
70+
The SDK will provide warnings and errors to guide further changes.
71+
72+
## Advanced: Version Pinning Strategies
73+
74+
### Pin SDK Version with global.json
75+
76+
Create or update `global.json` in your solution root to control which SDK version is used:
77+
78+
```bash
79+
dotnet new globaljson --sdk-version 9.0.100 --roll-forward latestFeature
80+
```
81+
82+
This ensures consistent builds across different machines and CI environments.
83+
84+
**File structure after:**
85+
86+
```text
87+
solution-root/
88+
├── global.json (pins SDK version)
89+
├── src/
90+
│ ├── Project1/
91+
│ └── Project2/
92+
└── tests/
93+
```
94+
95+
### Control Analyzer Behavior
96+
97+
Lock analyzer rules to a specific .NET version to prevent new warnings on upgrade:
98+
99+
```xml
100+
<PropertyGroup>
101+
<AnalysisLevel>9.0</AnalysisLevel>
102+
</PropertyGroup>
103+
```
104+
105+
This is useful when upgrading gradually—prevents new analyzer rules from breaking builds before you're ready to address them.
106+
107+
### Manage Package Versions
108+
109+
#### Option A: Central Package Management (Recommended)
110+
111+
Create `Directory.Packages.props` in solution root:
112+
113+
```xml
114+
<Project>
115+
<PropertyGroup>
116+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
117+
</PropertyGroup>
118+
119+
<ItemGroup>
120+
<PackageVersion Include="Microsoft.Extensions.AI" Version="9.10.1" />
121+
<PackageVersion Include="Azure.Identity" Version="1.17.0" />
122+
</ItemGroup>
123+
</Project>
124+
```
125+
126+
In project files, reference without version:
127+
128+
```xml
129+
<ItemGroup>
130+
<PackageReference Include="Microsoft.Extensions.AI" />
131+
<PackageReference Include="Azure.Identity" />
132+
</ItemGroup>
133+
```
134+
135+
#### Option B: Package Lock Files
136+
137+
Enable lock files to ensure reproducible restores:
138+
139+
```xml
140+
<PropertyGroup>
141+
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
142+
<RestoreLockedMode>true</RestoreLockedMode>
143+
</PropertyGroup>
144+
```
145+
146+
Generate lock file:
147+
148+
```bash
149+
dotnet restore
150+
```
151+
152+
## CI/CD Pipeline Updates
153+
154+
Update your CI/CD pipeline to use the new SDK version. For GitHub Actions:
155+
156+
**Before:**
157+
158+
```yaml
159+
- name: Setup .NET
160+
uses: actions/setup-dotnet@v4
161+
with:
162+
dotnet-version: '8.0'
163+
```
164+
165+
**After:**
166+
167+
```yaml
168+
- name: Setup .NET
169+
uses: actions/setup-dotnet@v4
170+
with:
171+
dotnet-version: '9.0'
172+
```
173+
174+
## Multi-Project Upgrade Checklist
175+
176+
Copy this checklist and track progress:
177+
178+
```text
179+
Upgrade Progress:
180+
- [ ] Review breaking changes for target .NET version
181+
- [ ] Update all .csproj files to new target framework
182+
- [ ] Run dotnet workload restore if needed
183+
- [ ] Build entire solution: dotnet build
184+
- [ ] Run full test suite: dotnet test
185+
- [ ] Update global.json if using version pinning
186+
- [ ] Update CI/CD pipeline configuration
187+
- [ ] Test in CI/CD environment
188+
- [ ] Commit changes
189+
```
190+
191+
## Breaking Changes and Migration
192+
193+
Check for breaking changes specific to your target version:
194+
195+
- [**.NET 9**](https://learn.microsoft.com/en-us/dotnet/core/compatibility/9.0)
196+
- [**.NET 10**](https://learn.microsoft.com/en-us/dotnet/core/compatibility/10.0)
197+
- [**ASP.NET Core**](https://learn.microsoft.com/en-us/aspnet/core/migration/)
198+
199+
## Hosting Environment Updates
200+
201+
### Docker
202+
203+
Update Dockerfile `FROM` statements:
204+
205+
```dockerfile
206+
# Old
207+
FROM mcr.microsoft.com/dotnet/aspnet:8.0
208+
209+
# New
210+
FROM mcr.microsoft.com/dotnet/aspnet:9.0
211+
```
212+
213+
### Azure App Service
214+
215+
Configuration changes are required through Azure Portal or IaC (e.g., Bicep, Terraform).
216+
217+
### Linux Servers
218+
219+
Install new .NET runtime via package manager:
220+
221+
```bash
222+
# Ubuntu/Debian
223+
sudo apt-get update
224+
sudo apt-get install -y dotnet-runtime-9.0
225+
```
226+
227+
## Troubleshooting
228+
229+
### Validation Loop
230+
231+
1. Run `dotnet build`
232+
2. If errors: review messages, fix issues, repeat step 1
233+
3. Run `dotnet test`
234+
4. If failures: fix tests, repeat step 3
235+
5. **Only proceed when both pass**
236+
237+
### Build Fails After Update
238+
239+
1. Check error messages—SDK provides guidance
240+
2. Review breaking changes for your target version
241+
3. Update NuGet packages that may have new version requirements
242+
4. Run `dotnet clean` and rebuild
243+
244+
### Tests Fail
245+
246+
- Run tests individually to isolate issues
247+
- Check for API changes in updated packages
248+
- Review test framework compatibility (e.g., xUnit, NUnit versions)
249+
250+
### CI/CD Pipeline Fails
251+
252+
- Verify new SDK version is available in CI environment
253+
- Check `global.json` is in repo root (CI should respect it)
254+
- Update any hardcoded version references in pipeline
255+
256+
## Key Resources
257+
258+
- [**.NET Official Upgrade Guide**](https://learn.microsoft.com/en-us/dotnet/core/install/upgrade)
259+
- [**global.json Reference**](https://learn.microsoft.com/en-us/dotnet/core/tools/global-json)
260+
- [**AnalysisLevel Property**](https://learn.microsoft.com/en-us/dotnet/core/project-sdk/msbuild-props#analysislevel)
261+
- [**ASP.NET Core Migration**](https://learn.microsoft.com/en-us/aspnet/core/migration/)
262+
263+
## Examples by Scenario
264+
265+
### Scenario 1: Simple Single-Project Upgrade
266+
267+
For a single `.csproj` project:
268+
269+
1. Update `<TargetFramework>net9.0</TargetFramework>`
270+
2. Run `dotnet build`
271+
3. Run `dotnet test`
272+
4. Commit with message: "Upgrade to .NET 9"
273+
274+
### Scenario 2: Multi-Project Solution with CI/CD
275+
276+
For solutions with multiple projects and GitHub Actions:
277+
278+
1. Update all `.csproj` files in the solution
279+
2. Create/update `global.json` in solution root
280+
3. Update `.github/workflows/*.yml` to use new version
281+
4. Run full test suite locally: `dotnet test`
282+
5. Push and verify CI passes
283+
6. Commit message: "Upgrade solution to .NET 9 (includes CI/CD updates)"
284+
285+
### Scenario 3: Gradual Multi-Version Support
286+
287+
For libraries supporting multiple .NET versions:
288+
289+
1. Update `<TargetFrameworks>net8.0;net9.0</TargetFrameworks>`
290+
2. Test on both versions: `dotnet test --framework net8.0 && dotnet test --framework net9.0`
291+
3. Document supported versions in README
292+
4. Gradually drop old version support in future releases
293+

.github/workflows/build.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121

2222
- uses: actions/setup-dotnet@v5
2323
with:
24-
dotnet-version: '9.0.x'
24+
dotnet-version: "10.0.x"
2525

2626
- name: Build
2727
run: |
@@ -38,7 +38,7 @@ jobs:
3838

3939
- uses: actions/setup-dotnet@v5
4040
with:
41-
dotnet-version: '9.0.x'
41+
dotnet-version: "10.0.x"
4242

4343
- name: Install Bicep
4444
run: |
@@ -66,8 +66,8 @@ jobs:
6666

6767
- uses: actions/setup-dotnet@v5
6868
with:
69-
dotnet-version: '9.0.x'
69+
dotnet-version: "10.0.x"
7070

7171
- name: Run Tests
7272
run: |
73-
dotnet test
73+
dotnet test
Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,28 @@
11
#!/usr/bin/env pwsh
22
[cmdletbinding()]
33
param(
4-
[Parameter(Mandatory=$true)][string]$Target
4+
[Parameter(Mandatory = $true)][string]$Target
55
)
66

77
$ErrorActionPreference = "Stop"
88

99
function ExecSafe([scriptblock] $ScriptBlock) {
1010
& $ScriptBlock
1111
if ($LASTEXITCODE -ne 0) {
12-
exit $LASTEXITCODE
12+
exit $LASTEXITCODE
1313
}
1414
}
1515

1616
$root = "$PSScriptRoot/../.."
1717
$extName = "azure-devops-extension"
1818

19+
# Get the target framework from the project file
20+
$csprojPath = "$root/src/DevOpsExtension.csproj"
21+
[xml]$csproj = Get-Content $csprojPath
22+
$targetFramework = $csproj.Project.PropertyGroup.TargetFramework | Where-Object { $_ } | Select-Object -First 1
23+
24+
Write-Host "Building for target framework: $targetFramework"
25+
1926
# build various flavors
2027
ExecSafe { dotnet publish --configuration Release $root -r osx-arm64 }
2128
ExecSafe { dotnet publish --configuration Release $root -r osx-x64 }
@@ -24,9 +31,9 @@ ExecSafe { dotnet publish --configuration Release $root -r win-x64 }
2431

2532
# publish to the registry
2633
ExecSafe { ~/.azure/bin/bicep publish-extension `
27-
--bin-osx-arm64 "$root/src/bin/Release/net9.0/osx-arm64/publish/$extName" `
28-
--bin-osx-x64 "$root/src/bin/Release/net9.0/osx-x64/publish/$extName" `
29-
--bin-linux-x64 "$root/src/bin/Release/net9.0/linux-x64/publish/$extName" `
30-
--bin-win-x64 "$root/src/bin/Release/net9.0/win-x64/publish/$extName.exe" `
31-
--target "$Target" `
32-
--force }
34+
--bin-osx-arm64 "$root/src/bin/Release/$targetFramework/osx-arm64/publish/$extName" `
35+
--bin-osx-x64 "$root/src/bin/Release/$targetFramework/osx-x64/publish/$extName" `
36+
--bin-linux-x64 "$root/src/bin/Release/$targetFramework/linux-x64/publish/$extName" `
37+
--bin-win-x64 "$root/src/bin/Release/$targetFramework/win-x64/publish/$extName.exe" `
38+
--target "$Target" `
39+
--force }

src/DevOpsExtension.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<PublishSingleFile>true</PublishSingleFile>
88
<SelfContained>true</SelfContained>
99
<InvariantGlobalization>true</InvariantGlobalization>
10-
<TargetFramework>net9.0</TargetFramework>
10+
<TargetFramework>net10.0</TargetFramework>
1111
<Nullable>enable</Nullable>
1212
<ImplicitUsings>enable</ImplicitUsings>
1313
</PropertyGroup>

tests/DevOpsExtension.Tests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net9.0</TargetFramework>
4+
<TargetFramework>net10.0</TargetFramework>
55
<Nullable>enable</Nullable>
66
<ImplicitUsings>enable</ImplicitUsings>
77
<IsPackable>false</IsPackable>

0 commit comments

Comments
 (0)