Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
32fa187
Update mcr.microsoft.com/dotnet/sdk:9.0.202-noble Docker digest to dc…
renovate[bot] Mar 24, 2025
268a3af
Update dependency xunit.v3 to v2 (#353)
renovate[bot] Apr 6, 2025
d4ce11e
Update Dockerfile and global.json updates to v9.0.203 (#364)
renovate[bot] Apr 9, 2025
2fb29d7
Update docs to use MergeFrom-Template.ps1
AArnott Apr 16, 2025
23cd85a
Fix lang service reporting C# 7.3 errors in Error List
AArnott Apr 22, 2025
1a8cb76
Update actions/download-artifact digest to d3f86a1
renovate[bot] Apr 28, 2025
8dc9804
Update dependency powershell to 7.5.1
renovate[bot] Apr 28, 2025
1ddad47
Update mcr.microsoft.com/dotnet/sdk:9.0.203-noble Docker digest to c8…
renovate[bot] Apr 28, 2025
508b839
Update xunit (#370)
renovate[bot] May 4, 2025
8fe4f14
Add support for a repo to hard-code extra SDKs that must be installed
AArnott May 6, 2025
0e0b8be
Merge pull request #371 from AArnott/multipleSDKs
AArnott May 6, 2025
3b421ec
Add script for collecting 3rd party symbol files
AArnott May 7, 2025
5cc3d59
Reapply "Avoid `dotnet format` hang"
AArnott Apr 24, 2025
e84bdc6
Fix 3rd party symbol archival
AArnott May 9, 2025
56aaaf0
Update Dockerfile and global.json updates to v9.0.300 (#372)
renovate[bot] May 14, 2025
94431e7
Update dependency Microsoft.NET.Test.Sdk to 17.14.0
AArnott May 20, 2025
08b8fab
Update mcr.microsoft.com/dotnet/sdk:9.0.300-noble Docker digest to 9f…
renovate[bot] May 29, 2025
25a0aa4
Update becheran/mlc action to v0.22.0 (#374)
renovate[bot] May 29, 2025
7974fd3
Update dependency Microsoft.NET.Test.Sdk to 17.14.1
AArnott Jun 3, 2025
df32f51
Update xunit
renovate[bot] Jun 7, 2025
0c41b21
Update Dockerfile and global.json updates to v9.0.301 (#376)
renovate[bot] Jun 11, 2025
4e511af
Add copilot swe agent setup instructions (#377)
AArnott Jun 11, 2025
231dae9
Touch-up name of github workflow
AArnott Jun 11, 2025
1a7db8d
Update mcr.microsoft.com/dotnet/sdk:9.0.301-noble Docker digest to 21…
renovate[bot] Jun 20, 2025
f84cb0f
Update mcr.microsoft.com/dotnet/sdk:9.0.301-noble Docker digest to f3…
renovate[bot] Jun 20, 2025
d1219b5
Update dependency powershell to 7.5.2
renovate[bot] Jun 25, 2025
c14a73b
Re-enable static graph nuget restore
AArnott Jun 29, 2025
5396018
Update becheran/mlc action to v1 (#383)
renovate[bot] Jul 8, 2025
d9522ff
Update mcr.microsoft.com/dotnet/sdk:9.0.301-noble Docker digest to 23…
renovate[bot] Jul 8, 2025
200f811
Update mcr.microsoft.com/dotnet/sdk:9.0.301-noble Docker digest to 4f…
renovate[bot] Jul 8, 2025
11467d8
Update .NET SDK to v9.0.302
renovate[bot] Jul 9, 2025
eef5eee
Update dependency xunit.v3 to v3 (#387)
renovate[bot] Jul 14, 2025
6b1c4db
Update dependency xunit.runner.visualstudio to 3.1.2 (#386)
renovate[bot] Jul 14, 2025
2102e05
Update mcr.microsoft.com/dotnet/sdk:9.0.302-noble Docker digest to d4…
renovate[bot] Jul 15, 2025
fe71729
Update dependency xunit.runner.visualstudio to 3.1.3
renovate[bot] Jul 16, 2025
77f38d4
Update Dockerfile and global.json updates to v9.0.303 (#394)
renovate[bot] Jul 18, 2025
0ac37ff
Merge the main branch from https://github.com/aarnott/Library.Template
AArnott Jul 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"powershell": {
"version": "7.5.0",
"version": "7.5.2",
"commands": [
"pwsh"
],
Expand Down
2 changes: 1 addition & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Refer to https://hub.docker.com/_/microsoft-dotnet-sdk for available versions
FROM mcr.microsoft.com/dotnet/sdk:9.0.202-noble@sha256:332e0362dd210a10348d436a5fb7f87aeec28c2c53ac2c3c2659e57c22294d0e
FROM mcr.microsoft.com/dotnet/sdk:9.0.303-noble@sha256:af75742bd2f6fd148504951b57a983bc410191729bf543eae467528d1bc175e5

# Installing mono makes `dotnet test` work without errors even for net472.
# But installing it takes a long time, so it's excluded by default.
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,6 @@ jobs:
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: 🔗 Markup Link Checker (mlc)
uses: becheran/mlc@c925f90a9a25e16e4c4bfa29058f6f9ffa9f0d8c # v0.21.0
uses: becheran/mlc@18a06b3aa2901ca197de59c8b0b1f54fdba6b3fa # v1.0.0
with:
args: --do-not-warn-for-redirect-to https://learn.microsoft.com*,https://dotnet.microsoft.com/*,https://dev.azure.com/*,https://app.codecov.io/* -p docfx
41 changes: 41 additions & 0 deletions .github/workflows/copilot-setup-steps.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: 💪🏼 Copilot Setup Steps

# Automatically run the setup steps when they are changed to allow for easy validation, and
# allow manual testing through the repository's "Actions" tab
on:
workflow_dispatch:
push:
branches:
- main
paths:
- .github/workflows/copilot-setup-steps.yml
pull_request:
paths:
- .github/workflows/copilot-setup-steps.yml

jobs:
# The job MUST be called `copilot-setup-steps` or it will not be picked up by Copilot.
copilot-setup-steps:
runs-on: ubuntu-latest
# Set the permissions to the lowest permissions possible needed for your steps.
# Copilot will be given its own token for its operations.
permissions:
# If you want to clone the repository as part of your setup steps, for example to install dependencies, you'll need the `contents: read` permission. If you don't clone the repository in your setup steps, Copilot will do this for you automatically after the steps complete.
contents: read

# You can define any steps you want, and they will run before the agent starts.
# If you do not check out your code, Copilot will do this for you.
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
- name: ⚙ Install prerequisites
run: |
./init.ps1 -UpgradePrerequisites -NoNuGetCredProvider
dotnet --info

# Print mono version if it is present.
if (Get-Command mono -ErrorAction SilentlyContinue) {
mono --version
}
shell: pwsh
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ jobs:
Echo "runid=$runid" >> $env:GITHUB_OUTPUT

- name: 🔻 Download deployables artifacts
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
with:
name: deployables-Linux
path: ${{ runner.temp }}/deployables
Expand Down
14 changes: 14 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,17 @@ Configuration is in the `.github/renovate.json` file.
When changing the renovate.json file, follow [these validation steps](https://docs.renovatebot.com/config-validation/).

If Renovate is not creating pull requests when you expect it to, check that the [Renovate GitHub App](https://github.com/apps/renovate) is configured for your account or repo.

## Merging latest from Library.Template

### Maintaining your repo based on this template

The best way to keep your repo in sync with Library.Template's evolving features and best practices is to periodically merge the template into your repo:
`
```ps1
git fetch
git checkout origin/main
.\tools\MergeFrom-Template.ps1
# resolve any conflicts, then commit the merge commit.
git push origin -u HEAD
```
8 changes: 6 additions & 2 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
<EnableDynamicPlatformResolution>true</EnableDynamicPlatformResolution>

<!-- Opt in till https://github.com/NuGet/Home/issues/9803 makes this the default. -->
<!-- Opt back out until an SDK with the fix for https://github.com/NuGet/Home/issues/12177 is generally available. -->
<RestoreUseStaticGraphEvaluation>false</RestoreUseStaticGraphEvaluation>
<RestoreUseStaticGraphEvaluation>true</RestoreUseStaticGraphEvaluation>

<!-- This entire repo has just one version.json file, so compute the version once and share with all projects in a large build. -->
<GitVersionBaseDirectory>$(MSBuildThisFileDirectory)</GitVersionBaseDirectory>
Expand All @@ -45,6 +44,11 @@
<SymbolPackageFormat>snupkg</SymbolPackageFormat>
</PropertyGroup>

<PropertyGroup>
<LangVersion Condition="'$(MSBuildProjectExtension)'=='.csproj'">13</LangVersion>
<LangVersion Condition="'$(MSBuildProjectExtension)'=='.vbproj'">16.9</LangVersion>
</PropertyGroup>

<ItemGroup>
<AdditionalFiles Include="$(MSBuildThisFileDirectory)stylecop.json" Link="stylecop.json" />
</ItemGroup>
Expand Down
4 changes: 0 additions & 4 deletions Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<LangVersion Condition="'$(Language)'=='C#'">13</LangVersion>
<LangVersion Condition="'$(Language)'=='VB'">16.9</LangVersion>
</PropertyGroup>
<ItemGroup>
<!-- Avoid compile error about missing namespace when combining ImplicitUsings with .NET Framework target frameworks. -->
<Using Remove="System.Net.Http" Condition="'$(TargetFrameworkIdentifier)'=='.NETFramework'" />
Expand Down
11 changes: 6 additions & 5 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,22 @@
<PackageVersion Include="System.IO.Pipes" Version="4.3.0" />
<PackageVersion Include="System.Runtime.CompilerServices.Unsafe" Version="6.1.0" />
<PackageVersion Include="System.Text.Json" Version="8.0.5" />
<PackageVersion Include="xunit.v3.extensibility.core" Version="1.1.0" />
<PackageVersion Include="xunit.v3.extensibility.core" Version="3.0.0" />
<PackageVersion Include="xunit.combinatorial" Version="2.0.24" />
</ItemGroup>
<ItemGroup Label="Library.Template">
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.13.0" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.0.2" />
<PackageVersion Include="xunit.v3" Version="1.1.0" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.3" />
<PackageVersion Include="xunit.v3" Version="3.0.0" />
</ItemGroup>
<ItemGroup>
<!-- Put repo-specific GlobalPackageReference items in this group. -->
</ItemGroup>
<ItemGroup Label="Library.Template">
<GlobalPackageReference Include="CSharpIsNullAnalyzer" Version="0.1.593" />
<GlobalPackageReference Include="DotNetAnalyzers.DocumentationAnalyzers" Version="1.0.0-beta.59" />
<GlobalPackageReference Include="Nerdbank.GitVersioning" Version="3.7.115" />
<!-- The condition works around https://github.com/dotnet/sdk/issues/44951 -->
<GlobalPackageReference Include="Nerdbank.GitVersioning" Version="3.7.115" Condition="!('$(TF_BUILD)'=='true' and '$(dotnetformat)'=='true')" />
<GlobalPackageReference Include="PolySharp" Version="1.15.0" />
<GlobalPackageReference Include="StyleCop.Analyzers.Unstable" Version="1.2.0.556" />
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"sdk": {
"version": "9.0.202",
"version": "9.0.303",
"rollForward": "patch",
"allowPrerelease": false
}
Expand Down
91 changes: 91 additions & 0 deletions tools/Get-3rdPartySymbolFiles.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
Function Get-FileFromWeb([Uri]$Uri, $OutFile) {
$OutDir = Split-Path $OutFile
if (!(Test-Path $OutFile)) {
Write-Verbose "Downloading $Uri..."
if (!(Test-Path $OutDir)) { New-Item -ItemType Directory -Path $OutDir | Out-Null }
try {
(New-Object System.Net.WebClient).DownloadFile($Uri, $OutFile)
}
finally {
# This try/finally causes the script to abort
}
}
}

Function Unzip($Path, $OutDir) {
$OutDir = (New-Item -ItemType Directory -Path $OutDir -Force).FullName
Add-Type -AssemblyName System.IO.Compression.FileSystem

# Start by extracting to a temporary directory so that there are no file conflicts.
[System.IO.Compression.ZipFile]::ExtractToDirectory($Path, "$OutDir.out")

# Now move all files from the temp directory to $OutDir, overwriting any files.
Get-ChildItem -Path "$OutDir.out" -Recurse -File | ForEach-Object {
$destinationPath = Join-Path -Path $OutDir -ChildPath $_.FullName.Substring("$OutDir.out".Length).TrimStart([io.path]::DirectorySeparatorChar, [io.path]::AltDirectorySeparatorChar)
if (!(Test-Path -Path (Split-Path -Path $destinationPath -Parent))) {
New-Item -ItemType Directory -Path (Split-Path -Path $destinationPath -Parent) | Out-Null
}
Move-Item -Path $_.FullName -Destination $destinationPath -Force
}
Remove-Item -Path "$OutDir.out" -Recurse -Force
}

Function Get-SymbolsFromPackage($id, $version) {
$symbolPackagesPath = "$PSScriptRoot/../obj/SymbolsPackages"
New-Item -ItemType Directory -Path $symbolPackagesPath -Force | Out-Null
$nupkgPath = Join-Path $symbolPackagesPath "$id.$version.nupkg"
$snupkgPath = Join-Path $symbolPackagesPath "$id.$version.snupkg"
$unzippedPkgPath = Join-Path $symbolPackagesPath "$id.$version"
Get-FileFromWeb -Uri "https://www.nuget.org/api/v2/package/$id/$version" -OutFile $nupkgPath
Get-FileFromWeb -Uri "https://www.nuget.org/api/v2/symbolpackage/$id/$version" -OutFile $snupkgPath

Unzip -Path $nupkgPath -OutDir $unzippedPkgPath
Unzip -Path $snupkgPath -OutDir $unzippedPkgPath

Get-ChildItem -Recurse -LiteralPath $unzippedPkgPath -Filter *.pdb | % {
# Collect the DLLs/EXEs as well.
$rootName = Join-Path $_.Directory $_.BaseName
if ($rootName.EndsWith('.ni')) {
$rootName = $rootName.Substring(0, $rootName.Length - 3)
}

$dllPath = "$rootName.dll"
$exePath = "$rootName.exe"
if (Test-Path $dllPath) {
$BinaryImagePath = $dllPath
}
elseif (Test-Path $exePath) {
$BinaryImagePath = $exePath
}
else {
Write-Warning "`"$_`" found with no matching binary file."
$BinaryImagePath = $null
}

if ($BinaryImagePath) {
Write-Output $BinaryImagePath
Write-Output $_.FullName
}
}
}

Function Get-PackageVersion($id) {
$versionProps = [xml](Get-Content -LiteralPath $PSScriptRoot\..\Directory.Packages.props)
$version = $versionProps.Project.ItemGroup.PackageVersion | ? { $_.Include -eq $id } | % { $_.Version }
if (!$version) {
Write-Error "No package version found in Directory.Packages.props for the package '$id'"
}

$version
}

# All 3rd party packages for which symbols packages are expected should be listed here.
# These must all be sourced from nuget.org, as it is the only feed that supports symbol packages.
$3rdPartyPackageIds = @()

$3rdPartyPackageIds | % {
$version = Get-PackageVersion $_
if ($version) {
Get-SymbolsFromPackage -id $_ -version $version
}
}
2 changes: 1 addition & 1 deletion tools/Get-SymbolFiles.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ $PDBs |% {
}
} |% {
# Collect the DLLs/EXEs as well.
$rootName = "$($_.Directory)/$($_.BaseName)"
$rootName = Join-Path $_.Directory $_.BaseName
if ($rootName.EndsWith('.ni')) {
$rootName = $rootName.Substring(0, $rootName.Length - 3)
}
Expand Down
57 changes: 34 additions & 23 deletions tools/Install-DotNetSdk.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ if (!(Test-Path $DotNetInstallScriptRoot)) { New-Item -ItemType Directory -Path
$DotNetInstallScriptRoot = Resolve-Path $DotNetInstallScriptRoot

# Look up actual required .NET SDK version from global.json
$sdkVersion = & "$PSScriptRoot/variables/DotNetSdkVersion.ps1"
$sdks = @(New-Object PSObject -Property @{ Version = & "$PSScriptRoot/variables/DotNetSdkVersion.ps1" })

# Sometimes a repo requires extra SDKs to be installed (e.g. msbuild.locator scenarios running in tests).
# In such a circumstance, a precise SDK version or a channel can be added as in the example below:
# $sdks += New-Object PSObject -Property @{ Channel = '8.0' }

If ($IncludeX86 -and ($IsMacOS -or $IsLinux)) {
Write-Verbose "Ignoring -IncludeX86 switch because 32-bit runtimes are only supported on Windows."
Expand Down Expand Up @@ -191,13 +195,16 @@ if ($InstallLocality -eq 'machine') {
$DotNetInstallDir = '/usr/share/dotnet'
} else {
$restartRequired = $false
if ($PSCmdlet.ShouldProcess(".NET SDK $sdkVersion", "Install")) {
Install-DotNet -Version $sdkVersion -Architecture $arch
$restartRequired = $restartRequired -or ($LASTEXITCODE -eq 3010)

if ($IncludeX86) {
Install-DotNet -Version $sdkVersion -Architecture x86
$sdks |% {
if ($_.Version) { $version = $_.Version } else { $version = $_.Channel }
if ($PSCmdlet.ShouldProcess(".NET SDK $_", "Install")) {
Install-DotNet -Version $version -Architecture $arch
$restartRequired = $restartRequired -or ($LASTEXITCODE -eq 3010)

if ($IncludeX86) {
Install-DotNet -Version $version -Architecture x86
$restartRequired = $restartRequired -or ($LASTEXITCODE -eq 3010)
}
}
}

Expand Down Expand Up @@ -296,29 +303,33 @@ $DotNetInstallScriptPathExpression = "& '$DotNetInstallScriptPathExpression'"
$anythingInstalled = $false
$global:LASTEXITCODE = 0

if ($PSCmdlet.ShouldProcess(".NET SDK $sdkVersion", "Install")) {
$anythingInstalled = $true
Invoke-Expression -Command "$DotNetInstallScriptPathExpression -Version $sdkVersion -Architecture $arch -InstallDir $DotNetInstallDir $switches"
$sdks |% {
if ($_.Version) { $parameters = '-Version', $_.Version } else { $parameters = '-Channel', $_.Channel }

if ($LASTEXITCODE -ne 0) {
Write-Error ".NET SDK installation failure: $LASTEXITCODE"
exit $LASTEXITCODE
}
} else {
Invoke-Expression -Command "$DotNetInstallScriptPathExpression -Version $sdkVersion -Architecture $arch -InstallDir $DotNetInstallDir $switches -DryRun"
}

if ($IncludeX86) {
if ($PSCmdlet.ShouldProcess(".NET x86 SDK $sdkVersion", "Install")) {
if ($PSCmdlet.ShouldProcess(".NET SDK $_", "Install")) {
$anythingInstalled = $true
Invoke-Expression -Command "$DotNetInstallScriptPathExpression -Version $sdkVersion -Architecture x86 -InstallDir $DotNetX86InstallDir $switches"
Invoke-Expression -Command "$DotNetInstallScriptPathExpression $parameters -Architecture $arch -InstallDir $DotNetInstallDir $switches"

if ($LASTEXITCODE -ne 0) {
Write-Error ".NET x86 SDK installation failure: $LASTEXITCODE"
Write-Error ".NET SDK installation failure: $LASTEXITCODE"
exit $LASTEXITCODE
}
} else {
Invoke-Expression -Command "$DotNetInstallScriptPathExpression -Version $sdkVersion -Architecture x86 -InstallDir $DotNetX86InstallDir $switches -DryRun"
Invoke-Expression -Command "$DotNetInstallScriptPathExpression $parameters -Architecture $arch -InstallDir $DotNetInstallDir $switches -DryRun"
}

if ($IncludeX86) {
if ($PSCmdlet.ShouldProcess(".NET x86 SDK $_", "Install")) {
$anythingInstalled = $true
Invoke-Expression -Command "$DotNetInstallScriptPathExpression $parameters -Architecture x86 -InstallDir $DotNetX86InstallDir $switches"

if ($LASTEXITCODE -ne 0) {
Write-Error ".NET x86 SDK installation failure: $LASTEXITCODE"
exit $LASTEXITCODE
}
} else {
Invoke-Expression -Command "$DotNetInstallScriptPathExpression $parameters -Architecture x86 -InstallDir $DotNetX86InstallDir $switches -DryRun"
}
}
}

Expand Down
3 changes: 3 additions & 0 deletions tools/artifacts/symbols.ps1
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
$BinPath = [System.IO.Path]::GetFullPath("$PSScriptRoot/../../bin")
$3rdPartyPath = [System.IO.Path]::GetFullPath("$PSScriptRoot/../../obj/SymbolsPackages")
if (!(Test-Path $BinPath)) { return }
$symbolfiles = & "$PSScriptRoot/../Get-SymbolFiles.ps1" -Path $BinPath | Get-Unique
$3rdPartyFiles = & "$PSScriptRoot/../Get-3rdPartySymbolFiles.ps1"

@{
"$BinPath" = $SymbolFiles;
"$3rdPartyPath" = $3rdPartyFiles;
}
Loading