diff --git a/.github/releases.json b/.github/releases.json
index db213637684..8f5e9173ef6 100644
--- a/.github/releases.json
+++ b/.github/releases.json
@@ -35,17 +35,17 @@
"outOfSupportDate": "2025-05-11T00:00:00.000Z"
},
"9.0": {
- "tag": "v9.0.3",
+ "tag": "v9.0.4",
"minorReleaseDate": "2024-11-12T00:00:00.000Z",
- "patchReleaseDate": "2025-05-13T00:00:00.000Z",
+ "patchReleaseDate": "2025-08-06T00:00:00.000Z",
"supportedFrameworks": [
"net9.0"
]
},
"8.1": {
- "tag": "v8.1.1",
+ "tag": "v8.1.2",
"minorReleaseDate": "2025-02-11T00:00:00.000Z",
- "patchReleaseDate": "2025-05-14T00:00:00.000Z",
+ "patchReleaseDate": "2025-08-06T00:00:00.000Z",
"supportedFrameworks": [
"net8.0"
]
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 1142807f19e..8c2fce6cb63 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -29,7 +29,6 @@
"omnisharp.enableAsyncCompletion": true,
"omnisharp.enableEditorConfigSupport": true,
"omnisharp.enableRoslynAnalyzers": true,
- "omnisharp.organizeImportsOnFormat": true,
"omnisharp.autoStart": true,
// ms-vscode.powershell settings
@@ -47,5 +46,6 @@
"xml",
"msbuild",
"javascript"
- ]
+ ],
+ "dotnet.formatting.organizeImportsOnFormat": true
}
diff --git a/documentation/releaseNotes/releaseNotes.v8.1.2.md b/documentation/releaseNotes/releaseNotes.v8.1.2.md
new file mode 100644
index 00000000000..f5abf0af9f8
--- /dev/null
+++ b/documentation/releaseNotes/releaseNotes.v8.1.2.md
@@ -0,0 +1,7 @@
+Today we are releasing the 8.1.2 build of the `dotnet monitor` tool. This release includes:
+
+- Updated dependencies
+
+
+
+If you would like to provide additional feedback to the team [please fill out this survey](https://aka.ms/dotnet-monitor-survey?src=rn).
\ No newline at end of file
diff --git a/documentation/releaseNotes/releaseNotes.v9.0.4.md b/documentation/releaseNotes/releaseNotes.v9.0.4.md
new file mode 100644
index 00000000000..b2e1d049ad7
--- /dev/null
+++ b/documentation/releaseNotes/releaseNotes.v9.0.4.md
@@ -0,0 +1,7 @@
+Today we are releasing the 9.0.4 build of the `dotnet monitor` tool. This release includes:
+
+- Updated dependencies
+
+
+
+If you would like to provide additional feedback to the team [please fill out this survey](https://aka.ms/dotnet-monitor-survey?src=rn).
\ No newline at end of file
diff --git a/documentation/releases.md b/documentation/releases.md
index b757800cd95..de20cc2a32a 100644
--- a/documentation/releases.md
+++ b/documentation/releases.md
@@ -4,8 +4,8 @@
| Version | Original Release Date | Latest Patch Version | Patch Release Date | End of Support | Runtime Frameworks |
| --- | --- | --- | --- | --- | --- |
-| 9.0 | November 12, 2024 | [9.0.3](https://github.com/dotnet/dotnet-monitor/releases/tag/v9.0.3) | May 13, 2025 | | net9.0 |
-| 8.1 | February 11, 2025 | [8.1.1](https://github.com/dotnet/dotnet-monitor/releases/tag/v8.1.1) | May 14, 2025 | | net8.0 |
+| 9.0 | November 12, 2024 | [9.0.4](https://github.com/dotnet/dotnet-monitor/releases/tag/v9.0.4) | August 6, 2025 | | net9.0 |
+| 8.1 | February 11, 2025 | [8.1.2](https://github.com/dotnet/dotnet-monitor/releases/tag/v8.1.2) | August 6, 2025 | | net8.0 |
## Out of support versions
diff --git a/eng/dependabot/independent/Versions.props b/eng/dependabot/independent/Versions.props
index 66565c614ad..30faab75923 100644
--- a/eng/dependabot/independent/Versions.props
+++ b/eng/dependabot/independent/Versions.props
@@ -6,7 +6,7 @@
1.14.2
12.25.0
12.23.0
- 3.11.0
+ 3.12.0
1.6.24
4.3.2
5.0.0
diff --git a/eng/dependabot/net9.0/Versions.props b/eng/dependabot/net9.0/Versions.props
index bf866651513..8ac69b4c5fe 100644
--- a/eng/dependabot/net9.0/Versions.props
+++ b/eng/dependabot/net9.0/Versions.props
@@ -2,16 +2,16 @@
- 9.0.7
+ 9.0.8
- 9.0.7
+ 9.0.8
- 9.0.7
+ 9.0.8
- 9.0.7
+ 9.0.8
9.0.4
- 9.0.7
+ 9.0.8
diff --git a/eng/pipelines/dotnet-monitor-release.yml b/eng/pipelines/dotnet-monitor-release.yml
index d406bf92c3f..afb469b6514 100644
--- a/eng/pipelines/dotnet-monitor-release.yml
+++ b/eng/pipelines/dotnet-monitor-release.yml
@@ -22,6 +22,144 @@ variables:
value: ${{ parameters.IsTestRun }}
readonly: true
+ # There are restrictions on what we can do in a release pipeline.
+ # - We cannot publish artifacts (which means the azcopy logs are now not published just written out)
+ # - We cannot checkout the source code
+ # - All powershell scripts were inlined in the pipeline.
+ # - Darc installation is done via tasks instead of darc-init.
+ # - We share scripts between the validation and publish stages as variables.
+
+ # Future improvements / TODO
+ # - Move the scripts into yaml template assuming the release job allows it
+ # - Save the results of build version / release version from the validation job and use it in the release job
+ # - Validate that dotnetcli can be used for checksums
+
+- name: GetBarIdScript
+ value: |
+ $ErrorActionPreference = 'Stop'
+ Set-StrictMode -Version 2.0
+
+ $BuildId = "$(resources.pipeline.Build.runID)"
+ $TaskVariableName = 'BarId'
+
+ if ([String]::IsNullOrEmpty($env:System_AccessToken)) {
+ Write-Error 'System access token missing, this script needs access.'
+ }
+
+ $tagsUri = "${env:SYSTEM_TEAMFOUNDATIONCOLLECTIONURI}${env:SYSTEM_TEAMPROJECT}/_apis/build/builds/$BuildId/tags?api-version=6.0"
+ $buildData = Invoke-RestMethod `
+ -Uri $tagsUri `
+ -Method 'GET' `
+ -Headers @{ 'accept' = 'application/json'; 'Authorization' = "Bearer ${env:System_AccessToken}" }
+
+ Write-Verbose 'BuildData:'
+ $buildDataJson = $buildData | ConvertTo-Json
+ Write-Verbose $buildDataJson
+
+ $barId = -1;
+ $buildData.Value | Foreach-Object {
+ if ($_.StartsWith('BAR ID - ')) {
+ if ($barId -ne -1) {
+ Write-Error 'Multiple BAR IDs found in tags.'
+ }
+ $barId = $_.SubString(9)
+ }
+ }
+
+ if ($barId -eq -1) {
+ Write-Error 'Failed to get BAR ID from tags.'
+ }
+
+ Write-Verbose "BAR ID: $barId"
+
+ Write-Host "##vso[task.setvariable variable=$TaskVariableName]$barId"
+ Write-Output $barId
+ readonly: true
+- name: GetReleaseVersionScript
+ value: |
+ $ErrorActionPreference = 'Stop'
+ Set-StrictMode -Version 2.0
+
+ $BarId = "$(BarId)"
+ $TaskVariableName = 'ReleaseVersion'
+
+ try {
+ # Use DARC tool to get build information
+ $darcPath = "$(Agent.ToolsDirectory)/darc/darc.exe"
+
+ if (!(Test-Path $darcPath)) {
+ Write-Error "DARC tool not found at $darcPath"
+ }
+
+ # Get build information using DARC
+ $buildInfo = & $darcPath get-build --id $BarId --output-format json --extended --ci
+ if ($LASTEXITCODE -ne 0) {
+ Write-Error "DARC get-build command failed with exit code $LASTEXITCODE"
+ }
+
+ $buildData = $buildInfo | ConvertFrom-Json
+
+ [array]$matchingData = $buildData.assets | Where-Object { $_.name -match '^dotnet-monitor$' }
+
+ if (!$matchingData -or $matchingData.Length -ne 1) {
+ Write-Error 'Unable to obtain release version'
+ }
+
+ $version = $matchingData[0].version
+
+ Write-Host "Release Version: $version"
+
+ Write-Host "##vso[task.setvariable variable=$TaskVariableName]$version"
+ Write-Output $version
+ }
+ catch {
+ Write-Error "Failed to get release version: $($_.Exception.Message)"
+ throw
+ }
+ readonly: true
+- name: GetBuildVersionScript
+ value: |
+ $ErrorActionPreference = 'Stop'
+ Set-StrictMode -Version 2.0
+
+ $BarId = "$(BarId)"
+ $TaskVariableName = 'BuildVersion'
+
+ try {
+ # Use DARC tool to get build information
+ $darcPath = "$(Agent.ToolsDirectory)/darc/darc.exe"
+
+ if (!(Test-Path $darcPath)) {
+ Write-Error "DARC tool not found at $darcPath"
+ }
+
+ # Get build information using DARC
+ $buildInfo = & $darcPath get-build --id $BarId --output-format json --extended --ci
+ if ($LASTEXITCODE -ne 0) {
+ Write-Error "DARC get-build command failed with exit code $LASTEXITCODE"
+ }
+
+ $buildData = $buildInfo | ConvertFrom-Json
+
+ [array]$matchingData = $buildData.assets | Where-Object { $_.name -match 'MergedManifest.xml$' -and $_.nonShipping }
+
+ if (!$matchingData -or $matchingData.Length -ne 1) {
+ Write-Error 'Unable to obtain build version.'
+ }
+
+ $version = $matchingData[0].version
+
+ Write-Host "Build Version: $version"
+
+ Write-Host "##vso[task.setvariable variable=$TaskVariableName]$version"
+ Write-Output $version
+ }
+ catch {
+ Write-Error "Failed to get build version: $($_.Exception.Message)"
+ throw
+ }
+ readonly: true
+
resources:
pipelines:
- pipeline: Build
@@ -52,13 +190,27 @@ extends:
steps:
- download: none
+ - task: UseDotNet@2
+ displayName: Install .NET 9
+ inputs:
+ packageType: 'sdk'
+ version: '9.x'
+ installationPath: $(Agent.ToolsDirectory)/dotnet
+
+ - task: AzureCLI@2
+ displayName: Install DARC Tool
+ inputs:
+ azureSubscription: "Darc: Maestro Production"
+ scriptType: ps
+ scriptLocation: inlineScript
+ inlineScript: |
+ dotnet tool install microsoft.dotnet.darc --tool-path "$(Agent.ToolsDirectory)/darc" --add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json --prerelease
+
- task: PowerShell@2
displayName: Get BAR ID
inputs:
- filePath: $(Build.SourcesDirectory)/eng/release/Scripts/GetBarId.ps1
- arguments: >-
- -BuildId $(resources.pipeline.Build.runID)
- -TaskVariableName 'BarId'
+ targetType: 'inline'
+ script: $(GetBarIdScript)
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
@@ -67,20 +219,16 @@ extends:
inputs:
azureSubscription: "Darc: Maestro Production"
scriptType: ps
- scriptPath: $(Build.SourcesDirectory)/eng/release/Scripts/GetReleaseVersion.ps1
- arguments: >-
- -BarId $(BarId)
- -TaskVariableName 'ReleaseVersion'
+ scriptLocation: inlineScript
+ inlineScript: $(GetReleaseVersionScript)
- task: AzureCLI@2
displayName: Get Build Version
inputs:
azureSubscription: "Darc: Maestro Production"
scriptType: ps
- scriptPath: $(Build.SourcesDirectory)/eng/release/Scripts/GetBuildVersion.ps1
- arguments: >-
- -BarId $(BarId)
- -TaskVariableName 'BuildVersion'
+ scriptLocation: inlineScript
+ inlineScript: $(GetBuildVersionScript)
- powershell: |
$buildName = "${env:ReleaseVersion} [${env:BuildVersion}]"
@@ -100,6 +248,9 @@ extends:
jobs:
- deployment: PublishToStorageAccounts
+ templateContext:
+ type: releaseJob
+ isProduction: true
displayName: Publish to Storage Accounts
${{ if eq(parameters.IsTestRun, 'true') }}:
@@ -126,24 +277,75 @@ extends:
runOnce:
deploy:
steps:
- - checkout: self
- download: none
+ - task: UseDotNet@2
+ displayName: Install .NET 9
+ inputs:
+ packageType: 'sdk'
+ version: '9.x'
+ installationPath: $(Agent.ToolsDirectory)/dotnet
+
+ - task: AzureCLI@2
+ displayName: Install DARC Tool
+ inputs:
+ azureSubscription: "Darc: Maestro Production"
+ scriptType: ps
+ scriptLocation: inlineScript
+ inlineScript: |
+ dotnet tool install microsoft.dotnet.darc --tool-path "$(Agent.ToolsDirectory)/darc" --add-source https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json --prerelease
+
- task: PowerShell@2
displayName: Install AzCopy
inputs:
- filePath: $(Build.SourcesDirectory)/eng/release/Scripts/InstallAzCopy.ps1
- arguments: >-
- -ToolsDirectory $(Agent.ToolsDirectory)
- -TaskVariableName 'AzCopyPath'
+ targetType: 'inline'
+ script: |
+ $ErrorActionPreference = 'Stop'
+ Set-StrictMode -Version 2.0
+
+ $ToolsDirectory = "$(Agent.ToolsDirectory)"
+ $TaskVariableName = 'AzCopyPath'
+
+ $url = 'https://aka.ms/downloadazcopy-v10-windows'
+ $basePath = Join-Path $ToolsDirectory 'azcopy'
+
+ $zipPath = Join-Path $basePath 'azcopy.zip'
+ $toolDirPath = Join-Path $basePath 'azcopy'
+ $azCopyPath = Join-Path $toolDirPath 'azcopy.exe'
+
+ if (Test-Path $azCopyPath) {
+ Write-Verbose 'Already installed'
+ } else {
+ if (!(Test-Path $basePath)) {
+ New-Item -ItemType 'Directory' -Path $basePath | Out-Null
+ }
+
+ Write-Verbose 'Fetching...'
+ Invoke-WebRequest -Uri $url -OutFile $zipPath
+
+ Write-Verbose 'Unzipping...'
+ Expand-Archive -LiteralPath $zipPath -Force -DestinationPath $basePath
+
+ # There should only be one directory that is named like 'azcopy_windows_amd64_'
+ Write-Verbose 'Renaming...'
+ $unpackDirName = Get-ChildItem -Path $basePath -Directory -Name
+ $unpackDirPath = Join-Path $basePath $unpackDirName
+ Rename-Item -Path $unpackDirPath -NewName 'azcopy'
+
+ # Delete zip
+ Remove-Item -Path $zipPath
+
+ Write-Verbose 'Finished'
+ }
+
+ Write-Host "##vso[task.setvariable variable=$TaskVariableName]$azCopyPath"
+ Write-Output $azCopyPath
- task: PowerShell@2
displayName: Get BAR ID
inputs:
- filePath: $(Build.SourcesDirectory)/eng/release/Scripts/GetBarId.ps1
- arguments: >-
- -BuildId $(resources.pipeline.Build.runID)
- -TaskVariableName 'BarId'
+ targetType: 'inline'
+ script: $(GetBarIdScript)
env:
SYSTEM_ACCESSTOKEN: $(System.AccessToken)
@@ -152,20 +354,16 @@ extends:
inputs:
azureSubscription: "Darc: Maestro Production"
scriptType: ps
- scriptPath: $(Build.SourcesDirectory)/eng/release/Scripts/GetReleaseVersion.ps1
- arguments: >-
- -BarId $(BarId)
- -TaskVariableName 'ReleaseVersion'
+ scriptLocation: inlineScript
+ inlineScript: $(GetReleaseVersionScript)
- task: AzureCLI@2
displayName: Get Build Version
inputs:
azureSubscription: "Darc: Maestro Production"
scriptType: ps
- scriptPath: $(Build.SourcesDirectory)/eng/release/Scripts/GetBuildVersion.ps1
- arguments: >-
- -BarId $(BarId)
- -TaskVariableName 'BuildVersion'
+ scriptLocation: inlineScript
+ inlineScript: $(GetBuildVersionScript)
- powershell: Install-PackageProvider -Name NuGet -Force -Scope CurrentUser
displayName: Install NuGet PowerShell Package Provider
@@ -194,24 +392,147 @@ extends:
# Save the service principal details to the environment so that azcopy can use them
addSpnToEnvironment: true
scriptType: ps
- scriptLocation: scriptPath
- scriptPath: $(Build.SourcesDirectory)/eng/release/Scripts/PublishToBlobAccounts.ps1
- arguments: >-
- -AzCopyPath $(AzCopyPath)
- -BuildVersion $(BuildVersion)
- -ReleaseVersion $(ReleaseVersion)
- -DestinationAccountName $(DestinationAccountName)
- -DestinationSasTokenBase64 $Env:DestinationSasTokenBase64
- -ChecksumsAccountName $(ChecksumsAccountName)
- -WhatIf:${{ format('${0}', parameters.IsDryRun) }}
+ scriptLocation: inlineScript
+ inlineScript: |
+ $ErrorActionPreference = 'Stop'
+ Set-StrictMode -Version 2.0
+
+ $AzCopyPath = "$(AzCopyPath)"
+ $BuildVersion = "$(BuildVersion)"
+ $ReleaseVersion = "$(ReleaseVersion)"
+ $DestinationAccountName = "$(DestinationAccountName)"
+ $DestinationSasTokenBase64 = $Env:DestinationSasTokenBase64
+ $ChecksumsAccountName = "$(ChecksumsAccountName)"
+ $WhatIfPreference = $${{ parameters.IsDryRun }}
+
+ # Use the OAuth token that was obtained by the az cli when it logged in.
+ $Env:AZCOPY_AUTO_LOGIN_TYPE="AZCLI"
+
+ $sourceAccountName = 'dotnetstage'
+ $sourceContainerName = 'dotnet-monitor'
+ $destinationContainerName = 'dotnet'
+
+ function Generate-Source-Uri{
+ [CmdletBinding()]
+ Param(
+ [Parameter(Mandatory=$true)][string]$AssetType
+ )
+
+ return "https://$sourceAccountName.blob.core.windows.net/$sourceContainerName/$BuildVersion/${AssetType}Assets/*"
+ }
+
+ function Generate-Destination-Uri{
+ [CmdletBinding()]
+ Param(
+ [Parameter(Mandatory=$true)][string]$AccountName
+ )
+
+ return "https://$AccountName.blob.core.windows.net/$destinationContainerName/diagnostics/monitor/$ReleaseVersion"
+ }
+
+ function Transfer-File{
+ [CmdletBinding(SupportsShouldProcess)]
+ Param(
+ [Parameter(Mandatory=$true)][string]$From,
+ [Parameter(Mandatory=$true)][string]$To,
+ [Parameter(Mandatory=$false)][string]$ToToken = $null
+ )
+
+ if ($ToToken -and ($ToToken[0] -ne '?')) {
+ $ToToken = '?' + $ToToken
+ }
+
+ Write-Host "Copy $From -> $To"
+
+ if ($From -eq $to) {
+ Write-Host 'Skipping copy because source and destination are the same.'
+ } else {
+ [array]$azCopyArgs = "$From"
+ $azCopyArgs += "$To$ToToken"
+ $azCopyArgs += "--s2s-preserve-properties"
+ $azCopyArgs += "--s2s-preserve-access-tier=false"
+ if ($WhatIfPreference) {
+ $azCopyArgs += "--dry-run"
+ }
+ & $AzCopyPath cp @azCopyArgs
+ }
+ }
+
+ # Create source URI
+ $sourceUri = Generate-Source-Uri `
+ -AssetType 'Blob'
+
+ # Create destination URI
+ $destinationUri = Generate-Destination-Uri `
+ -AccountName $DestinationAccountName
+
+ # Copy files to destination account
+ Transfer-File `
+ -From $sourceUri `
+ -To $destinationUri `
+ -ToToken ([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($DestinationSasTokenBase64)))
+
+ # Create source checksums URI
+ $checksumsSourceUri = Generate-Source-Uri `
+ -AssetType 'Checksum'
+
+ # Create checksums destination URI
+ $checksumsDestinationUri = Generate-Destination-Uri `
+ -AccountName $ChecksumsAccountName
+
+ # Copy checksums to checksum account
+ Transfer-File `
+ -From $checksumsSourceUri `
+ -To $checksumsDestinationUri
env:
DestinationSasTokenBase64: $(DotNetCliDelegationSasTokenBase64)
- - task: 1ES.PublishBuildArtifacts@1
- displayName: Publish Logs
+ - task: PowerShell@2
+ displayName: Display AzCopy Logs
inputs:
- PathtoPublish: '$(USERPROFILE)\.azcopy'
- PublishLocation: Container
- ArtifactName: AzCopyLogs
+ targetType: 'inline'
+ script: |
+ $ErrorActionPreference = 'Continue'
+
+ $azCopyLogDir = Join-Path $env:USERPROFILE '.azcopy'
+
+ Write-Host "Checking AzCopy logs directory: $azCopyLogDir"
+
+ if (Test-Path $azCopyLogDir) {
+ Write-Host "AzCopy logs directory exists."
+
+ # Get all log files
+ $logFiles = Get-ChildItem -Path $azCopyLogDir -File -Recurse | Sort-Object LastWriteTime -Descending
+
+ if ($logFiles.Count -eq 0) {
+ Write-Host "No log files found in AzCopy directory."
+ } else {
+ Write-Host "Found $($logFiles.Count) log file(s):"
+
+ foreach ($logFile in $logFiles) {
+ Write-Host ""
+ Write-Host "========================================="
+ Write-Host "Log File: $($logFile.FullName)"
+ Write-Host "Size: $($logFile.Length) bytes"
+ Write-Host "Last Modified: $($logFile.LastWriteTime)"
+ Write-Host "========================================="
+
+ try {
+ $content = Get-Content -Path $logFile.FullName -Raw
+ if ([string]::IsNullOrWhiteSpace($content)) {
+ Write-Host "Log file is empty."
+ } else {
+ Write-Host $content
+ }
+ } catch {
+ Write-Host "Error reading log file: $($_.Exception.Message)"
+ }
+
+ Write-Host ""
+ }
+ }
+ } else {
+ Write-Host "AzCopy logs directory does not exist: $azCopyLogDir"
+ }
continueOnError: true
condition: succeededOrFailed()