diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
index 1b8c58ce..0eae3250 100644
--- a/.config/dotnet-tools.json
+++ b/.config/dotnet-tools.json
@@ -3,14 +3,14 @@
"isRoot": true,
"tools": {
"powershell": {
- "version": "7.5.0",
+ "version": "7.5.1",
"commands": [
"pwsh"
],
"rollForward": false
},
"dotnet-coverage": {
- "version": "17.13.1",
+ "version": "17.14.2",
"commands": [
"dotnet-coverage"
],
@@ -24,7 +24,7 @@
"rollForward": false
},
"docfx": {
- "version": "2.78.2",
+ "version": "2.78.3",
"commands": [
"docfx"
],
diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
index 6952a419..938b19f8 100644
--- a/.devcontainer/Dockerfile
+++ b/.devcontainer/Dockerfile
@@ -1,5 +1,5 @@
# Refer to https://hub.docker.com/_/microsoft-dotnet-sdk for available versions
-FROM mcr.microsoft.com/dotnet/sdk:9.0.102-noble
+FROM mcr.microsoft.com/dotnet/sdk:9.0.300-noble@sha256:9f7bd4d010026e15a57d9cf876f2f7d08c3eeed6a0ea987b8c5ba8c75e68e948
# Installing mono makes `dotnet test` work without errors even for net472.
# But installing it takes a long time, so it's excluded by default.
diff --git a/.github/actions/publish-artifacts/action.yaml b/.github/actions/publish-artifacts/action.yaml
index 2a75c4d2..1f345fe6 100644
--- a/.github/actions/publish-artifacts/action.yaml
+++ b/.github/actions/publish-artifacts/action.yaml
@@ -14,46 +14,46 @@ runs:
- name: 📢 Upload project.assets.json files
if: always()
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: projectAssetsJson-${{ runner.os }}
path: ${{ runner.temp }}/_artifacts/projectAssetsJson
continue-on-error: true
- name: 📢 Upload variables
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: variables-${{ runner.os }}
path: ${{ runner.temp }}/_artifacts/Variables
continue-on-error: true
- name: 📢 Upload build_logs
if: always()
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: build_logs-${{ runner.os }}
path: ${{ runner.temp }}/_artifacts/build_logs
continue-on-error: true
- name: 📢 Upload testResults
if: always()
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: testResults-${{ runner.os }}
path: ${{ runner.temp }}/_artifacts/testResults
continue-on-error: true
- name: 📢 Upload coverageResults
if: always()
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: coverageResults-${{ runner.os }}
path: ${{ runner.temp }}/_artifacts/coverageResults
continue-on-error: true
- name: 📢 Upload symbols
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: symbols-${{ runner.os }}
path: ${{ runner.temp }}/_artifacts/symbols
continue-on-error: true
- name: 📢 Upload deployables
- uses: actions/upload-artifact@v4
+ uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: deployables-${{ runner.os }}
path: ${{ runner.temp }}/_artifacts/deployables
diff --git a/.github/renovate.json b/.github/renovate.json
index 72080431..4789cb20 100644
--- a/.github/renovate.json
+++ b/.github/renovate.json
@@ -1,52 +1,9 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
- "extends": ["config:recommended"],
- "semanticCommits": "disabled",
- "labels": ["dependencies"],
- "packageRules": [
- {
- "matchPackageNames": ["nbgv", "nerdbank.gitversioning"],
- "groupName": "nbgv and nerdbank.gitversioning updates"
- },
- {
- "matchPackageNames": ["xunit*"],
- "groupName": "xunit"
- },
- {
- "matchDatasources": ["dotnet-version", "docker"],
- "matchDepNames": ["dotnet-sdk", "mcr.microsoft.com/dotnet/sdk"],
- "groupName": "Dockerfile and global.json updates"
- },
- {
- "matchPackageNames": ["*"],
- "allowedVersions": "!/-g[a-f0-9]+$/"
- },
- {
- "matchPackageNames": [
- "System.Collections.Immutable",
- "System.Composition*",
- "System.Diagnostics.DiagnosticSource",
- "System.IO.Pipelines",
- "System.Reflection.Metadata",
- "System.Text.Json",
- "System.Threading.Tasks.Dataflow",
- "Microsoft.Bcl.AsyncInterfaces"
- ],
- "allowedVersions": "<9.0",
- "groupName": "Included in .NET runtime"
- },
- {
- "matchPackageNames": ["Microsoft.VisualStudio.Internal.MicroBuild*"],
- "groupName": "microbuild"
- },
- {
- "matchPackageNames": ["Microsoft.VisualStudio.*"],
- "groupName": "Visual Studio SDK"
- },
- {
- "matchPackageNames": ["Microsoft.VisualStudio.*"],
- "matchUpdateTypes": ["patch"],
- "enabled": false
- }
- ]
+ "extends": [
+ "github>microsoft/vs-renovate-presets:microbuild",
+ "github>microsoft/vs-renovate-presets:vs_main_dependencies",
+ "github>microsoft/vs-renovate-presets:dotnet_packages_LTS"
+ ],
+ "packageRules": []
}
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 70b779b5..0a8f8215 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -25,7 +25,7 @@ jobs:
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
- name: ⚙ Install prerequisites
@@ -35,10 +35,10 @@ jobs:
name: 📚 Generate documentation
- name: Upload artifact
- uses: actions/upload-pages-artifact@v3
+ uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
with:
path: docfx/_site
- name: Deploy to GitHub Pages
id: deployment
- uses: actions/deploy-pages@v4
+ uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4
diff --git a/.github/workflows/libtemplate-update.yml b/.github/workflows/libtemplate-update.yml
index 53df80ff..7d0a67a0 100644
--- a/.github/workflows/libtemplate-update.yml
+++ b/.github/workflows/libtemplate-update.yml
@@ -17,7 +17,7 @@ jobs:
contents: write
pull-requests: write
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
fetch-depth: 0 # avoid shallow clone so nbgv can do its work.
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
deleted file mode 100644
index 766ebaf5..00000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,88 +0,0 @@
-name: 🎁 Release
-
-on:
- release:
- types: [published]
- workflow_dispatch:
- inputs:
- ship_run_id:
- description: ID of the GitHub workflow run to ship
- required: true
-
-run-name: ${{ github.ref_name }}
-
-permissions:
- actions: read
- contents: write
-
-jobs:
- release:
- runs-on: ubuntu-24.04
- steps:
- - name: ⚙️ Initialization
- shell: pwsh
- run: |
- if ('${{ secrets.NUGET_API_KEY }}') {
- Write-Host "NUGET_API_KEY secret detected. NuGet packages will be pushed."
- echo "NUGET_API_KEY_DEFINED=true" >> $env:GITHUB_ENV
- }
-
- - name: 🔎 Search for build of ${{ github.ref }}
- shell: pwsh
- id: findrunid
- env:
- GH_TOKEN: ${{ github.token }}
- run: |
- if ('${{ inputs.ship_run_id }}') {
- $runid = '${{ inputs.ship_run_id }}'
- } else {
- $restApiRoot = '/repos/${{ github.repository }}'
-
- # Resolve the tag reference to a commit sha
- $resolvedRef = gh api `
- -H "Accept: application/vnd.github+json" `
- -H "X-GitHub-Api-Version: 2022-11-28" `
- $restApiRoot/git/ref/tags/${{ github.ref_name }} `
- | ConvertFrom-Json
- $commitSha = $resolvedRef.object.sha
-
- Write-Host "Resolved ${{ github.ref_name }} to $commitSha"
-
- $releases = gh run list -R ${{ github.repository }} -c $commitSha -w .github/workflows/build.yml -s success --json databaseId,startedAt `
- | ConvertFrom-Json | Sort-Object startedAt -Descending
-
- if ($releases.length -eq 0) {
- Write-Error "No successful builds found for ${{ github.ref }}."
- } elseif ($releases.length -gt 1) {
- Write-Warning "More than one successful run found for ${{ github.ref }}. Artifacts from the most recent successful run will ship."
- }
-
- $runid = $releases[0].databaseId
- }
-
- Write-Host "Using artifacts from run-id: $runid"
-
- Echo "runid=$runid" >> $env:GITHUB_OUTPUT
-
- - name: 🔻 Download deployables artifacts
- uses: actions/download-artifact@v4
- with:
- name: deployables-Linux
- path: ${{ runner.temp }}/deployables
- run-id: ${{ steps.findrunid.outputs.runid }}
- github-token: ${{ github.token }}
-
- - name: 💽 Upload artifacts to release
- shell: pwsh
- if: ${{ github.event.release.assets_url }} != ''
- env:
- GH_TOKEN: ${{ github.token }}
- run: |
- Get-ChildItem '${{ runner.temp }}/deployables' |% {
- Write-Host "Uploading $($_.Name) to release..."
- gh release -R ${{ github.repository }} upload "${{ github.ref_name }}" $_.FullName
- }
-
- - name: 🚀 Push NuGet packages
- run: dotnet nuget push ${{ runner.temp }}/deployables/*.nupkg --source https://api.nuget.org/v3/index.json -k '${{ secrets.NUGET_API_KEY }}'
- if: ${{ env.NUGET_API_KEY_DEFINED == 'true' }}
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 58d4fb6a..158b7d92 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -82,3 +82,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
+```
diff --git a/Directory.Build.props b/Directory.Build.props
index 8d649c7e..df07c8bb 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -7,6 +7,7 @@
$(RepoRootPath)bin\$(MSBuildProjectName)\
$(RepoRootPath)bin\Packages\$(Configuration)\NuGet\
$(RepoRootPath)bin\Packages\$(Configuration)\Vsix\$(Platform)\
+ $(VSIXOutputPath)
enable
enable
latest
@@ -38,6 +39,11 @@
snupkg
+
+ 13
+ 16.9
+
+
@@ -56,4 +62,6 @@
$(RepositoryUrl)/releases/tag/v$(Version)
+
+
diff --git a/Directory.Build.targets b/Directory.Build.targets
index d1a3c22e..0e0366b5 100644
--- a/Directory.Build.targets
+++ b/Directory.Build.targets
@@ -1,9 +1,5 @@
-
- 13
- 16.9
-
@@ -12,6 +8,4 @@
-
-
diff --git a/Directory.Packages.props b/Directory.Packages.props
index ddcdc05e..c71a6835 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -12,10 +12,10 @@
-
+
-
-
+
+
diff --git a/SUPPORT.md b/SUPPORT.md
new file mode 100644
index 00000000..0f876b3e
--- /dev/null
+++ b/SUPPORT.md
@@ -0,0 +1,16 @@
+# Support
+
+## How to file issues and get help
+
+This project uses GitHub Issues to track bugs and feature requests.
+Please search the existing issues before filing new issues to avoid duplicates.
+For new issues, file your bug or feature request as a new Issue.
+
+Note that this repo is primarily used for Visual Studio and related products and support will be focused on those scenarios.
+
+## Microsoft Support Policy
+
+Microsoft support for this software is available only for its use in officially supported products such as Visual Studio.
+Support and servicing is limited to the latest released version.
+For more information, see [Visual Studio Product Lifecycle and Servicing](https://learn.microsoft.com/visualstudio/productinfo/vs-servicing).
+Assisted support is available from a professional support engineer by opening a ticket with the [Microsoft assisted support team](https://support.serviceshub.microsoft.com/supportforbusiness/onboarding).
diff --git a/azure-pipelines/NuGetSbom.props b/azure-pipelines/NuGetSbom.props
new file mode 100644
index 00000000..dbfee864
--- /dev/null
+++ b/azure-pipelines/NuGetSbom.props
@@ -0,0 +1,6 @@
+
+
+ true
+ 2
+
+
diff --git a/azure-pipelines/NuGetSbom.targets b/azure-pipelines/NuGetSbom.targets
deleted file mode 100644
index a2599e88..00000000
--- a/azure-pipelines/NuGetSbom.targets
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
- true
- $(TargetsForTfmSpecificBuildOutput);IncludeSbomInNupkg
-
-
-
-
-
-
-
-
diff --git a/azure-pipelines/build.yml b/azure-pipelines/build.yml
index 55c0b97a..ba91c5c7 100644
--- a/azure-pipelines/build.yml
+++ b/azure-pipelines/build.yml
@@ -71,6 +71,10 @@ parameters:
type: boolean
default: true
+- name: PublishCodeCoverage
+ type: boolean
+ default: true
+
# Whether this is a special one-off build for inserting into VS for a validation insertion PR (that will never be merged).
- name: SkipCodesignVerify
type: boolean
@@ -279,8 +283,16 @@ jobs:
- macOS
pool: ${{ parameters.windowsPool }} # Use Windows agent because PublishSymbols task requires it (https://github.com/microsoft/azure-pipelines-tasks/issues/13821).
condition: succeededOrFailed()
+ variables:
+ ONEES_ENFORCED_CODEQL_ENABLED: false # CodeQL runs on build jobs, we don't need it here
${{ if eq(variables['system.collectionId'], '011b8bdf-6d56-4f87-be0d-0092136884d9') }}:
templateContext:
+ ${{ if not(parameters.RealSign) }}:
+ mb:
+ signing: # if the build is test-signed, install the signing plugin so that CSVTestSignPolicy.xml is available
+ enabled: true
+ zipSources: false
+ signType: test
outputParentDirectory: $(Build.ArtifactStagingDirectory)
outputs:
- output: pipelineArtifact
@@ -299,7 +311,7 @@ jobs:
parameters:
EnableLinuxBuild: ${{ parameters.EnableLinuxBuild }}
EnableMacOSBuild: ${{ parameters.EnableMacOSBuild }}
- - ${{ if parameters.RunTests }}:
+ - ${{ if and(parameters.RunTests, parameters.PublishCodeCoverage) }}:
- template: publish-codecoverage.yml
parameters:
EnableLinuxBuild: ${{ parameters.EnableLinuxBuild }}
diff --git a/azure-pipelines/dotnet.yml b/azure-pipelines/dotnet.yml
index 180e36c2..2abca9eb 100644
--- a/azure-pipelines/dotnet.yml
+++ b/azure-pipelines/dotnet.yml
@@ -8,7 +8,7 @@ parameters:
steps:
-- script: dotnet build -t:build,pack --no-restore -c $(BuildConfiguration) -warnAsError -warnNotAsError:NU1901,NU1902,NU1903,NU1904 /bl:"$(Build.ArtifactStagingDirectory)/build_logs/build.binlog"
+- script: dotnet build -t:build,pack --no-restore -c $(BuildConfiguration) -warnAsError -warnNotAsError:NU1901,NU1902,NU1903,NU1904,LOCTASK002 /bl:"$(Build.ArtifactStagingDirectory)/build_logs/build.binlog"
displayName: 🛠 dotnet build
- ${{ if not(parameters.IsOptProf) }}:
diff --git a/azure-pipelines/microbuild.after.yml b/azure-pipelines/microbuild.after.yml
index e2107433..025de4f5 100644
--- a/azure-pipelines/microbuild.after.yml
+++ b/azure-pipelines/microbuild.after.yml
@@ -9,7 +9,7 @@ parameters:
type: boolean
steps:
-- ${{ if not(parameters.SkipCodesignVerify) }}: # skip CodesignVerify on validation builds because we don't even test-sign nupkg's.
+- ${{ if not(parameters.SkipCodesignVerify) }}:
- task: MicroBuildCodesignVerify@3
displayName: 🔍 Verify Signed Files
inputs:
diff --git a/azure-pipelines/official.yml b/azure-pipelines/official.yml
index e3240ca5..3d4852f3 100644
--- a/azure-pipelines/official.yml
+++ b/azure-pipelines/official.yml
@@ -29,6 +29,10 @@ parameters:
displayName: Include APIScan with compliance tools
type: boolean
default: true
+- name: PublishCodeCoverage
+ displayName: Publish code coverage
+ type: boolean
+ default: true
resources:
repositories:
@@ -48,14 +52,14 @@ extends:
codeSignValidation:
enabled: true
break: true
- additionalTargetsGlobPattern: -|Variables-*\*.ps1;-|APIScanInputs-*\**;-|test_symbols-*\**;-|MicroBuild\**
+ additionalTargetsGlobPattern: -|Variables-*\*.ps1;-|LocBin-*\**;-|APIScanInputs-*\**;-|test_symbols-*\**;-|MicroBuild\**
policheck:
enabled: true
exclusionsFile: $(System.DefaultWorkingDirectory)\azure-pipelines\PoliCheckExclusions.xml
suppression:
suppressionFile: $(System.DefaultWorkingDirectory)\azure-pipelines\falsepositives.gdnsuppress
sbom:
- enabled: true
+ enabled: false # Skip 1ES SBOM because microbuild has our own sbom system
stages:
- stage: Build
variables:
@@ -79,6 +83,7 @@ extends:
os: macOS
EnableMacOSBuild: ${{ parameters.EnableMacOSBuild }}
RunTests: ${{ parameters.RunTests }}
+ PublishCodeCoverage: ${{ parameters.PublishCodeCoverage }}
- template: /azure-pipelines/prepare-insertion-stages.yml@self
parameters:
RealSign: true
diff --git a/azure-pipelines/prepare-insertion-stages.yml b/azure-pipelines/prepare-insertion-stages.yml
index ff752cd6..18eda020 100644
--- a/azure-pipelines/prepare-insertion-stages.yml
+++ b/azure-pipelines/prepare-insertion-stages.yml
@@ -18,6 +18,8 @@ stages:
- job: symbol_archive
displayName: Archive symbols
pool: VSEngSS-MicroBuild2022-1ES
+ variables:
+ ONEES_ENFORCED_CODEQL_ENABLED: false # CodeQL runs on build stages, we don't need it here
steps:
- checkout: none
- download: current
@@ -61,6 +63,8 @@ stages:
${{ else }}:
nuGetFeedType: internal
publishVstsFeed: vs-impl # Leave this as-is, since non-signed builds must not be pushed to public feeds.
+ variables:
+ ONEES_ENFORCED_CODEQL_ENABLED: false # CodeQL runs on build stages, we don't need it here
steps:
- checkout: none
- download: current
diff --git a/azure-pipelines/unofficial.yml b/azure-pipelines/unofficial.yml
index 32f8de41..6564ea45 100644
--- a/azure-pipelines/unofficial.yml
+++ b/azure-pipelines/unofficial.yml
@@ -36,6 +36,10 @@ parameters:
displayName: Enable Production SDL
type: boolean
default: false
+- name: PublishCodeCoverage
+ displayName: Publish code coverage
+ type: boolean
+ default: true
resources:
repositories:
@@ -64,7 +68,7 @@ extends:
enabled: ${{ parameters.EnableProductionSDL }}
exclusionsFile: $(System.DefaultWorkingDirectory)\azure-pipelines\PoliCheckExclusions.xml
sbom:
- enabled: ${{ parameters.EnableProductionSDL }}
+ enabled: false # Skip 1ES SBOM because microbuild has our own sbom system
stages:
- stage: Build
variables:
@@ -88,3 +92,4 @@ extends:
os: macOS
EnableMacOSBuild: ${{ parameters.EnableMacOSBuild }}
RunTests: ${{ parameters.RunTests }}
+ PublishCodeCoverage: ${{ parameters.PublishCodeCoverage }}
diff --git a/azure-pipelines/vs-insertion.yml b/azure-pipelines/vs-insertion.yml
index fcfc0a71..9812bc25 100644
--- a/azure-pipelines/vs-insertion.yml
+++ b/azure-pipelines/vs-insertion.yml
@@ -32,6 +32,8 @@ extends:
- job: insertion
displayName: VS insertion
pool: VSEngSS-MicroBuild2022-1ES
+ templateContext:
+ outputParentDirectory: $(Pipeline.Workspace)/CI
steps:
- checkout: none
- powershell: Write-Host "##vso[build.updatebuildnumber]$(resources.pipeline.CI.runName)"
diff --git a/azure-pipelines/vs-validation.yml b/azure-pipelines/vs-validation.yml
index 2fa5086d..3a40395e 100644
--- a/azure-pipelines/vs-validation.yml
+++ b/azure-pipelines/vs-validation.yml
@@ -5,6 +5,12 @@
trigger: none # We only want to trigger manually or based on resources
pr: none
+# parameters:
+# - name: ShouldSkipOptimize # Uncomment this and references to it below when setting EnableOptProf to true in build.yml.
+# displayName: Skip OptProf optimization
+# type: boolean
+# default: false
+
resources:
repositories:
- repository: MicroBuildTemplate
@@ -26,16 +32,16 @@ extends:
stages:
- stage: Build
variables:
- DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
- NUGET_PACKAGES: $(Agent.TempDirectory)/.nuget/packages/
- BuildConfiguration: Release
- SkipCodesignVerify: true
+ - template: /azure-pipelines/BuildStageVariables.yml@self
+ - name: SkipCodesignVerify
+ value: true
jobs:
- template: /azure-pipelines/build.yml@self
parameters:
Is1ESPT: true
RealSign: false
+ # ShouldSkipOptimize: ${{ parameters.ShouldSkipOptimize }}
windowsPool: VSEngSS-MicroBuild2022-1ES
linuxPool:
name: AzurePipelines-EO
diff --git a/global.json b/global.json
index 20b589f8..3d0b9e2d 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "9.0.102",
+ "version": "9.0.300",
"rollForward": "patch",
"allowPrerelease": false
},
diff --git a/test/Microsoft.VisualStudio.Validation.Tests/AssertDialogSuppression.cs b/test/Microsoft.VisualStudio.Validation.Tests/AssertDialogSuppression.cs
index a67ebf85..7a571def 100644
--- a/test/Microsoft.VisualStudio.Validation.Tests/AssertDialogSuppression.cs
+++ b/test/Microsoft.VisualStudio.Validation.Tests/AssertDialogSuppression.cs
@@ -33,6 +33,14 @@ public AssertDialogSuppression()
this.originalAssertUiSetting = assertDialogListener.AssertUiEnabled;
assertDialogListener.AssertUiEnabled = false;
}
+
+ // Xunit.v3 v2 also adds a TraceListener that throws on failure, so remove that too.
+ // See also https://github.com/xunit/xunit/issues/3317.
+ // My mechanism for removing the listener is designed to work before and after that issue is resolved.
+ if (Trace.Listeners.OfType().FirstOrDefault() is { } listener)
+ {
+ Trace.Listeners.Remove(listener);
+ }
#endif
}
diff --git a/tools/Get-3rdPartySymbolFiles.ps1 b/tools/Get-3rdPartySymbolFiles.ps1
new file mode 100644
index 00000000..ef6bbef2
--- /dev/null
+++ b/tools/Get-3rdPartySymbolFiles.ps1
@@ -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
+ }
+}
diff --git a/tools/Get-SymbolFiles.ps1 b/tools/Get-SymbolFiles.ps1
index b5063cec..70656c0f 100644
--- a/tools/Get-SymbolFiles.ps1
+++ b/tools/Get-SymbolFiles.ps1
@@ -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)
}
diff --git a/tools/Install-DotNetSdk.ps1 b/tools/Install-DotNetSdk.ps1
index e08571bc..402b4307 100755
--- a/tools/Install-DotNetSdk.ps1
+++ b/tools/Install-DotNetSdk.ps1
@@ -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."
@@ -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)
+ }
}
}
@@ -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"
+ }
}
}
diff --git a/tools/artifacts/symbols.ps1 b/tools/artifacts/symbols.ps1
index 9e2c7bd5..b5882678 100644
--- a/tools/artifacts/symbols.ps1
+++ b/tools/artifacts/symbols.ps1
@@ -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;
}