From ffbded2fe9185b0424031bcbf44ef0ffea07617f Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Fri, 21 Nov 2025 11:20:28 -0400 Subject: [PATCH 1/7] - Added global.json to restrict our SDK to the single supported version, currently 9.0. - Using global.json to install .NET SDKs everywhere except when we may need ARM64. - Removed unnecessary installation of .NET SDKs and runtimes where they aren't needed. - Added all target frameworks to the x86 test runs. - Updated documentation related to SDKs. - Removed runtime ARM64 architecture detection in favour of explicit parameters for the test jobs that use ARM64. - Suppressing CredScan errors related to test secrets. --- .config/CredScanSuppressions.json | 11 +- BUILDGUIDE.md | 9 ++ README.md | 12 +- .../templates/jobs/ci-build-nugets-job.yml | 7 ++ .../templates/jobs/ci-code-coverage-job.yml | 16 ++- .../templates/jobs/ci-run-tests-job.yml | 98 +++++++++++----- .../templates/stages/ci-run-tests-stage.yml | 2 + ...ld-all-configurations-signed-dlls-step.yml | 47 +++----- .../templates/steps/ci-prebuild-step.yml | 24 ---- .../templates/steps/ci-project-build-step.yml | 15 --- .../templates/steps/ensure-dotnet-version.yml | 108 ------------------ .../common/templates/steps/pre-build-step.yml | 55 +++++---- eng/pipelines/dotnet-sqlclient-ci-core.yml | 8 +- eng/pipelines/jobs/stress-tests-ci-job.yml | 8 +- .../stages/stress-tests-ci-stage.yml | 2 +- .../steps/compound-build-akv-step.yml | 83 ++++++-------- eng/pipelines/steps/install-dotnet-arm64.yml | 73 ++++++++++++ global.json | 29 +++++ src/Microsoft.Data.SqlClient.sln | 2 +- 19 files changed, 309 insertions(+), 300 deletions(-) delete mode 100644 eng/pipelines/common/templates/steps/ensure-dotnet-version.yml create mode 100644 eng/pipelines/steps/install-dotnet-arm64.yml create mode 100644 global.json diff --git a/.config/CredScanSuppressions.json b/.config/CredScanSuppressions.json index 1bac9b0d92..1780d0ab51 100644 --- a/.config/CredScanSuppressions.json +++ b/.config/CredScanSuppressions.json @@ -1,6 +1,7 @@ { "tool": "Credential Scanner", - "suppressions": [ + "suppressions": + [ { "file": "src/Microsoft.Data.SqlClient/tests/tools/TDS/TDS.Servers/TDSServerArguments.cs", "justification": "Test projects should be skipped" @@ -12,6 +13,14 @@ { "file": "doc/samples/SqlConnectionStringBuilder.cs", "justification": "Documentation could include sample data and can be ignored" + }, + { + "file": "src/Microsoft.Data.SqlClient/tests/UnitTests/Fixtures/AlwaysEncrypted/NativeColumnEncryptionKeyCertificateBaselineFixture.cs", + "justification": "Test projects should be skipped" + }, + { + "file": "src/Microsoft.Data.SqlClient/tests/UnitTests/Resources/AlwaysEncrypted/NativeColumnEncryptionKeyBaseline/Certificate.pfx", + "justification": "Test projects should be skipped" } ] } diff --git a/BUILDGUIDE.md b/BUILDGUIDE.md index efeb747cad..e29e9d2356 100644 --- a/BUILDGUIDE.md +++ b/BUILDGUIDE.md @@ -2,6 +2,15 @@ This document provides all the necessary details to build the driver and run tests present in the repository. +## .NET SDK + +The projects in this repo require the .NET 9.0 SDK to build. Please ensure you +have the latest version of that SDK installed. + +Tests and tools may require different .NET Runtimes that may be installed +independently. For example, tests targeting .NET 8.0 will need that runtime +installed. + ## Visual Studio Pre-Requisites This project should be built with Visual Studio 2019+ for the best compatibility. The required set of components are provided in the below file: diff --git a/README.md b/README.md index 0397bae238..1a066c52d4 100644 --- a/README.md +++ b/README.md @@ -27,15 +27,15 @@ When targeting .NET on Windows, a package reference to [Microsoft.Data.SqlClient | Topic | Link to File | | :---- | :------------- | -| Coding Style | [coding-style.md](/policy/coding-style.md) | | Best Practices | [coding-best-practices.md](/policy/coding-best-practices.md) | -| Review Process | [review-process.md](/policy/review-process.md) | -| Guidelines for building the driver | [BUILDGUIDE.md](BUILDGUIDE.md) | -| Guidelines for Contributors | [CONTRIBUTING.md](CONTRIBUTING.md) | -| Changelog for all driver releases | [CHANGELOG.md](CHANGELOG.md) | -| Support Policy | [SUPPORT.md](SUPPORT.md) | +| Build Guide | [BUILDGUIDE.md](/BUILDGUIDE.md) | +| Changelog | [CHANGELOG.md](CHANGELOG.md) | | Code of Conduct | [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) | +| Coding Style | [coding-style.md](/policy/coding-style.md) | +| Contributing | [CONTRIBUTING.md](CONTRIBUTING.md) | | Copyright Information | [COPYRIGHT.md](COPYRIGHT.md) | +| Review Process | [review-process.md](/policy/review-process.md) | +| Support Policy | [SUPPORT.md](SUPPORT.md) | ## Our Featured Contributors diff --git a/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml b/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml index 7b72820534..785453a41a 100644 --- a/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml @@ -46,6 +46,13 @@ jobs: - ${{ if ne(parameters.prebuildSteps, '') }}: - ${{ parameters.prebuildSteps }} # extra steps to run before the build like downloading sni and the required configuration + # Install whichever .NET SDKs are specified in our global.json. + - task: UseDotNet@2 + displayName: Install .NET SDKs + inputs: + packageType: sdk + useGlobalJson: true + - template: ../steps/ci-project-build-step.yml@self parameters: platform: ${{ parameters.platform }} diff --git a/eng/pipelines/common/templates/jobs/ci-code-coverage-job.yml b/eng/pipelines/common/templates/jobs/ci-code-coverage-job.yml index d849ef27a7..ab8e607809 100644 --- a/eng/pipelines/common/templates/jobs/ci-code-coverage-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-code-coverage-job.yml @@ -60,16 +60,14 @@ jobs: - pwsh: 'Get-ChildItem env: | Sort-Object Name' displayName: '[Debug] List Environment Variables' - - template: ../steps/ensure-dotnet-version.yml@self - parameters: - packageType: sdk - version: '10.0' - - - template: ../steps/ensure-dotnet-version.yml@self - parameters: - packageType: runtime - version: '9.0' + # Install whichever .NET SDKs are specified in our global.json. + - task: UseDotNet@2 + displayName: Install .NET SDKs + inputs: + packageType: sdk + useGlobalJson: true + # Install additional dotnet tools. - pwsh: | dotnet tool install --global dotnet-coverage dotnet tool install --global dotnet-reportgenerator-globaltool diff --git a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml index a2b7bdc2fa..8fa3d3fcdf 100644 --- a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml @@ -81,6 +81,11 @@ parameters: # The timeout, in minutes, for this job. - name: timeout type: number + + # True if this is an ARM64 job. + - name: isArm64 + type: boolean + default: false jobs: - job: ${{ format('{0}', coalesce(parameters.jobDisplayName, parameters.image, 'unknown_image')) }} @@ -102,6 +107,46 @@ jobs: value: '$(dotnetx86Path)' steps: + + # Install .NET SDKs and runtimes. These may be needed for the pre-build + # steps. + # + # We can use the standard UseDotNet@2 task for non-ARM64 jobs. + - ${{ if eq(parameters.isArm64, false) }}: + - task: UseDotNet@2 + displayName: Install .NET SDKs + inputs: + packageType: sdk + useGlobalJson: true + + - task: UseDotNet@2 + displayName: Install .NET 8 Runtime + inputs: + packageType: runtime + version: 8.x + + # For ARM64, we need to use our custom step to work around a bug in + # UseDotNet@2: + # + # [BUG]: UseDotNet task installs x86 build + # https://github.com/microsoft/azure-pipelines-tasks/issues/20300 + # + - ${{ else }}: + - template: ../../../steps/install-dotnet-arm64.yml@self + parameters: + debug: ${{ parameters.debug }} + installType: SDK + # GOTCHA: We always use global.json for SDK version except on ARM64, + # where we have to specify it here. This must be kept synchronized with + # the SDK version in global.json. + version: 9.0 + + - template: ../../../steps/install-dotnet-arm64.yml@self + parameters: + debug: ${{ parameters.debug }} + installType: Runtime + version: 8.0 + - ${{ if ne(parameters.prebuildSteps, '') }}: - ${{ parameters.prebuildSteps }} # extra steps to run before the build like downloading sni and the required configuration @@ -121,6 +166,12 @@ jobs: } displayName: 'Verify Password' + - ${{ if eq(parameters.buildType, 'Project') }}: + - template: ../steps/ci-project-build-step.yml@self + parameters: + build: allNoDocs + buildConfiguration: ${{ parameters.buildConfiguration }} + - ${{ if ne(parameters.configProperties, '{}') }}: - template: ../steps/update-config-file-step.yml@self # update config.json file parameters: @@ -253,33 +304,28 @@ jobs: # it should be acceptable to just install a specific version in all cases. # @TODO: This setup is very confusing. Ideally we should just be utilizing the dotnet installation # earlier in the job. There has to be a cleaner way of doing this. - # As it stands now, we install dotnet LTS if we're running netfx tests, and the appropriate netX - # version if we're running netcore tests. Technically LTS is not supported by the UseDotNet task - # but we know we're using install-dotnet since we're on windows (for now ... this will not work - # forever and needs a serious rethinking). - ${{ if ne(variables['dotnetx86RootPath'], '') }}: - - ${{ if startswith(parameters.targetFramework, 'net4')}}: - - template: ../steps/ensure-dotnet-version.yml - parameters: - installDir: "$(dotnetx86RootPath)" - packageType: "sdk" - usePreview: "false" - version: "LTS" - windowsArchitecture: "x86" - - ${{ else }}: - - script: | - set FrameworkVersion=${{ parameters.targetFramework }} - echo %FrameworkVersion% - set TrimmedFrameworkVersion=%FrameworkVersion:~3% - echo %TrimmedFrameworkVersion% - echo ##vso[task.setvariable variable=netVersionX86]%TrimmedFrameworkVersion% - displayName: "Trim dotnet version" - - template: ../steps/ensure-dotnet-version.yml - parameters: - installDir: "$(dotnetx86RootPath)" - packageType: "sdk" - usePreview: "false" - version: $(netVersionX86) + # Install whichever .NET SDKs are specified in our global.json. + - task: UseDotNet@2 + displayName: Install .NET SDKs + inputs: + installationPath: $(dotnetx86RootPath) + packageType: sdk + useGlobalJson: true + env: + # Override the architecture to install for x86. + PROCESSOR_ARCHITECTURE: x86 + + # Install the .NET 8.0 runtime to run tests that target it. + - task: UseDotNet@2 + displayName: Install .NET 8.0 Runtime + inputs: + installationPath: $(dotnetx86RootPath) + packageType: runtime + version: 8.x + env: + # Override the architecture to install for x86. + PROCESSOR_ARCHITECTURE: x86 - template: ../steps/run-all-tests-step.yml@self parameters: diff --git a/eng/pipelines/common/templates/stages/ci-run-tests-stage.yml b/eng/pipelines/common/templates/stages/ci-run-tests-stage.yml index 363535aa7e..7676574451 100644 --- a/eng/pipelines/common/templates/stages/ci-run-tests-stage.yml +++ b/eng/pipelines/common/templates/stages/ci-run-tests-stage.yml @@ -72,6 +72,7 @@ stages: publishTestResults: true configSqlFor: ${{ config.value.configSqlFor }} operatingSystem: ${{ config.value.operatingSystem }} + isArm64: ${{ eq(config.value.isArm64, 'true') }} ${{if ne(config.value.configProperties, '{}') }}: ${{ each x86TF in config.value.configProperties.x86TestTargetFrameworks }}: ${{ if eq(x86TF, targetFramework) }}: @@ -103,6 +104,7 @@ stages: publishTestResults: true configSqlFor: ${{ config.value.configSqlFor }} operatingSystem: ${{ config.value.operatingSystem }} + isArm64: ${{ eq(config.value.isArm64, 'true') }} ${{if and(eq(usemanagedSNI, false), ne(config.value.configProperties, '{}')) }}: ${{ each x86TF in config.value.configProperties.x86TestTargetFrameworks }}: ${{ if eq(x86TF, targetFramework) }}: diff --git a/eng/pipelines/common/templates/steps/build-all-configurations-signed-dlls-step.yml b/eng/pipelines/common/templates/steps/build-all-configurations-signed-dlls-step.yml index ef19650643..21bb9d35c8 100644 --- a/eng/pipelines/common/templates/steps/build-all-configurations-signed-dlls-step.yml +++ b/eng/pipelines/common/templates/steps/build-all-configurations-signed-dlls-step.yml @@ -25,34 +25,23 @@ parameters: - MSS steps: -- task: DownloadSecureFile@1 - displayName: 'Download Key Pair' - inputs: - secureFile: netfxKeypair.snk - retryCount: 5 - -- task: UseDotNet@2 - displayName: 'Use .NET 10.x sdk' - inputs: - packageType: sdk - version: '10.x' - -- task: UseDotNet@2 - displayName: 'Use .NET 9.x runtime' - inputs: - packageType: runtime - version: '9.x' - -- task: UseDotNet@2 - displayName: 'Install .NET 8.x runtime' - inputs: - packageType: runtime - version: '8.x' + - task: DownloadSecureFile@1 + displayName: 'Download Key Pair' + inputs: + secureFile: netfxKeypair.snk + retryCount: 5 -- ${{ if eq(parameters.product, 'MDS') }}: - - task: MSBuild@1 - displayName: 'BuildAllConfigurations using build.proj' + # Install whichever .NET SDKs are specified in our global.json. + - task: UseDotNet@2 + displayName: Install .NET SDKs inputs: - solution: '**/build.proj' - configuration: '${{parameters.buildConfiguration }}' - msbuildArguments: '-p:AssemblyFileVersion=${{parameters.AssemblyFileVersion }} -t:BuildAllConfigurations -p:GenerateNuget=false -p:SigningKeyPath=$(Agent.TempDirectory)\netfxKeypair.snk' + packageType: sdk + useGlobalJson: true + + - ${{ if eq(parameters.product, 'MDS') }}: + - task: MSBuild@1 + displayName: 'BuildAllConfigurations using build.proj' + inputs: + solution: '**/build.proj' + configuration: '${{parameters.buildConfiguration }}' + msbuildArguments: '-p:AssemblyFileVersion=${{parameters.AssemblyFileVersion }} -t:BuildAllConfigurations -p:GenerateNuget=false -p:SigningKeyPath=$(Agent.TempDirectory)\netfxKeypair.snk' diff --git a/eng/pipelines/common/templates/steps/ci-prebuild-step.yml b/eng/pipelines/common/templates/steps/ci-prebuild-step.yml index 4920482059..3774363ec3 100644 --- a/eng/pipelines/common/templates/steps/ci-prebuild-step.yml +++ b/eng/pipelines/common/templates/steps/ci-prebuild-step.yml @@ -25,24 +25,6 @@ parameters: - Package steps: -- template: ensure-dotnet-version.yml - parameters: - packageType: sdk - usePreview: false - version: 10.0 - -- template: ensure-dotnet-version.yml - parameters: - packageType: runtime - usePreview: false - version: 9.0 - -- template: ensure-dotnet-version.yml - parameters: - packageType: runtime - usePreview: false - version: 8.0 - - ${{if eq(parameters.debug, true)}}: - powershell: | Get-ChildItem env: | Sort-Object Name @@ -61,9 +43,3 @@ steps: parameters: downloadedNugetPath: $(Pipeline.Workspace)\${{parameters.artifactName }} debug: ${{ parameters.debug }} - -- ${{ else }}: # project - - template: ci-project-build-step.yml@self - parameters: - build: allNoDocs - buildConfiguration: ${{ parameters.buildConfiguration }} diff --git a/eng/pipelines/common/templates/steps/ci-project-build-step.yml b/eng/pipelines/common/templates/steps/ci-project-build-step.yml index 2b40aa8216..919958e8a2 100644 --- a/eng/pipelines/common/templates/steps/ci-project-build-step.yml +++ b/eng/pipelines/common/templates/steps/ci-project-build-step.yml @@ -37,21 +37,6 @@ parameters: - allNoDocs steps: -- template: ./ensure-dotnet-version.yml@self - parameters: - packageType: 'sdk' - version: '10.0' - -- template: ./ensure-dotnet-version.yml@self - parameters: - packageType: 'runtime' - version: '9.0' - -- template: ./ensure-dotnet-version.yml@self - parameters: - packageType: 'runtime' - version: '8.0' - - ${{ if or(eq(parameters.operatingSystem, 'Windows'), eq(parameters.operatingSystem, 'deferedToRuntime')) }}: - ${{ if or(eq(parameters.build, 'MDS'), eq(parameters.build, 'all'), eq(parameters.build, 'allNoDocs')) }}: - task: MSBuild@1 diff --git a/eng/pipelines/common/templates/steps/ensure-dotnet-version.yml b/eng/pipelines/common/templates/steps/ensure-dotnet-version.yml deleted file mode 100644 index fd6ba9674b..0000000000 --- a/eng/pipelines/common/templates/steps/ensure-dotnet-version.yml +++ /dev/null @@ -1,108 +0,0 @@ -################################################################################# -# Licensed to the .NET Foundation under one or more agreements. # -# The .NET Foundation licenses this file to you under the MIT license. # -# See the LICENSE file in the project root for more information. # -################################################################################# - -# Installs dotnet sdk/runtime using UseDotNet on non-windows agents, but uses a custom ps script -# for installation on Windows. -# -# Reason for not using UseDotNet task: -# [BUG]: UseDotNet task installs x86 build on Windows arm64 -# https://github.com/microsoft/azure-pipelines-tasks/issues/20300 - -parameters: - - # Directory where dotnet binaries should be installed. If not specified, defaults to the - # agent's tools directory. - name: installDir - type: string - default: '' - - - # Whether to install the full SDK or the "dotnet" runtime - name: packageType - type: string - values: - - runtime - - sdk - - - # Whether to enable preview versions of dotnet - name: usePreview - type: boolean - default: false - - - # Version to install - supports full major.minor.patch, but can be shortened to major.minor - # to get the latest within a given channel. Do not append .x to the end (as per UseDotNet), - # it is not supported by dotnet-install script, and we will add it if we use UseDotNet task. - name: version - type: string - - - # Specifies the architecture to install, only applies on Windows agents. If not provided, - # defaults to the same architecture as the agent. - name: windowsArchitecture - type: string - default: '' - values: - - '' - - 'x86' - - 'x64' - - 'arm64' - -steps: - # Note: as much as I'd love to use template expressions here, I can't because ${{ }} is - # evaluated at compile time, while Agent is not known until runtime. - - powershell: |- - # Propagate parameters from pipeline ####################### - $agentToolsDir = '$(Agent.ToolsDirectory)' - echo "agentToolsDir= $agentToolsDir" - - $architecture = '${{ parameters.windowsArchitecture }}' - echo "architecture= $architecture" - - $installDir = '${{ parameters.installDir }}' - echo "installDir= $installDir" - - $packageType = '${{ parameters.packageType }}' - echo "packageType= $packageType" - - $usePreview = '${{ parameters.usePreview }}' - echo "usePreview= $usePreview" - - $version = '${{ parameters.version }}' - echo "version= $version" - - # Install dotnet ########################################### - Invoke-WebRequest -Uri "https://builds.dotnet.microsoft.com/dotnet/scripts/v1/dotnet-install.ps1" -OutFile "dotnet-install.ps1" - - $installDir = If ($installDir) { $installDir } Else { $agentToolsDir } - $installParams = @{ - Architecture = $architecture - Channel = $version - InstallDir = $installDir - Quality = If ($usePreview) { "GA" } Else { "preview" } - } - - if ($packageType -eq 'runtime') { - $installParams.add('Runtime', 'dotnet') - } - - & ./dotnet-install.ps1 @installParams - Remove-Item dotnet-install.ps1 -ErrorAction:Ignore - - # Propagate values back out to pipeline #################### - Write-Host "##vso[task.setvariable variable=DOTNET_ROOT]${installDir}" - Write-Host "##vso[task.prependpath]${installDir}" - displayName: 'Install dotnet ${{ parameters.version }} ${{ parameters.packageType }} for Windows ${{ parameters.windowsArchitecture }}' - condition: eq(variables['Agent.OS'], 'Windows_NT') - - - task: UseDotNet@2 - displayName: 'Install dotnet ${{ parameters.version }} ${{ parameters.packageType }}' - inputs: - ${{ if ne(parameters.installDir, '') }}: - installationPath: '${{ parameters.installDir }}' - ${{ else }}: - installationPath: '$(Agent.ToolsDirectory)' - packageType: '${{ parameters.packageType }}' - version: '${{ parameters.version }}.x' - - includePreviewVersions: '${{ parameters.usePreview }}' - condition: ne(variables['Agent.OS'], 'Windows_NT') diff --git a/eng/pipelines/common/templates/steps/pre-build-step.yml b/eng/pipelines/common/templates/steps/pre-build-step.yml index cfcd9a46f8..5a0d01b30d 100644 --- a/eng/pipelines/common/templates/steps/pre-build-step.yml +++ b/eng/pipelines/common/templates/steps/pre-build-step.yml @@ -4,33 +4,38 @@ # See the LICENSE file in the project root for more information. # ################################################################################# steps: -- template: ./ensure-dotnet-version.yml@self - parameters: - packageType: 'sdk' - version: '10.0' - usePreview: false + # Install whichever .NET SDKs are specified in our global.json. + - task: UseDotNet@2 + displayName: Install .NET SDKs + inputs: + packageType: sdk + useGlobalJson: true -- template: ./ensure-dotnet-version.yml@self - parameters: - packageType: 'runtime' - version: '9.0' + # Install the .NET 9.0 runtime to run tests that target it. + - task: UseDotNet@2 + displayName: Install .NET 9.0 Runtime + inputs: + packageType: runtime + version: 9.x -- template: ./ensure-dotnet-version.yml@self - parameters: - packageType: 'runtime' - version: '8.0' + # Install the .NET 8.0 runtime to run tests that target it. + - task: UseDotNet@2 + displayName: Install .NET 8.0 Runtime + inputs: + packageType: runtime + version: 8.x -- script: SET - displayName: 'Print Environment Variables' + - script: SET + displayName: 'Print Environment Variables' -- powershell: | - # use sqlcmd to try to connect to localdb - $svc_name = "SQLBrowser" - Get-Service $svc_name | Select-Object -Property Name, StartType, Status - Set-Service -StartupType Automatic $svc_name - net start $svc_name - Get-Service $svc_name | Select-Object -Property Name, StartType, Status - displayName: 'Start SQLBrowser' + - powershell: | + # use sqlcmd to try to connect to localdb + $svc_name = "SQLBrowser" + Get-Service $svc_name | Select-Object -Property Name, StartType, Status + Set-Service -StartupType Automatic $svc_name + net start $svc_name + Get-Service $svc_name | Select-Object -Property Name, StartType, Status + displayName: 'Start SQLBrowser' -- task: NuGetToolInstaller@1 - displayName: 'Use NuGet' + - task: NuGetToolInstaller@1 + displayName: 'Use NuGet' diff --git a/eng/pipelines/dotnet-sqlclient-ci-core.yml b/eng/pipelines/dotnet-sqlclient-ci-core.yml index 77ee594aaf..9f796e768d 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-core.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-core.yml @@ -220,7 +220,7 @@ stages: pool: ${{parameters.defaultPoolName }} # pool name images: # list of images to run tests on Win22_Sql19_x86: ADO-MMS22-SQL19 # stage display name: image name from the pool - TargetFrameworks: [net8.0] #[net462, net8.0] # list of target frameworks to run + TargetFrameworks: [net462, net8.0, net9.0] netcoreVersionTestUtils: ${{parameters.netcoreVersionTestUtils }} buildPlatforms: ${{parameters.buildPlatforms }} testSets: ${{parameters.testSets }} # [1, 2, 3] # list of test sets to run @@ -241,7 +241,7 @@ stages: LocalDbSharedInstanceName: $(LocalDbSharedInstanceName) AliasName: $(SQLAliasName) # extra config properties - x86TestTargetFrameworks: [net8.0] # target frameworks should run tests on x86 + x86TestTargetFrameworks: [net462, net8.0, net9.0] SQLRootPath: $(SQL19RootPath) enableLocalDB: true # instanceName: default: MSSQLSERVER @@ -291,7 +291,7 @@ stages: pool: ${{parameters.defaultPoolName }} images: Win22_Sql22_x86: ADO-MMS22-SQL22 - TargetFrameworks: [net462] + TargetFrameworks: [net462, net8.0, net9.0] netcoreVersionTestUtils: ${{parameters.netcoreVersionTestUtils }} buildPlatforms: ${{parameters.buildPlatforms }} testSets: ${{parameters.testSets }} @@ -312,7 +312,7 @@ stages: LocalDbSharedInstanceName: $(LocalDbSharedInstanceName) AliasName: $(SQLAliasName) # extra config properties - x86TestTargetFrameworks: [net462] # target frameworks should run tests on x86 as well + x86TestTargetFrameworks: [net462, net8.0, net9.0] SQLRootPath: $(SQL22RootPath) enableLocalDB: true diff --git a/eng/pipelines/jobs/stress-tests-ci-job.yml b/eng/pipelines/jobs/stress-tests-ci-job.yml index 2e01470fe5..2155e542da 100644 --- a/eng/pipelines/jobs/stress-tests-ci-job.yml +++ b/eng/pipelines/jobs/stress-tests-ci-job.yml @@ -131,14 +131,14 @@ jobs: steps: - # Install the .NET 9.0 SDK. + # Install whichever .NET SDKs are specified in our global.json. - task: UseDotNet@2 - displayName: Install .NET 9.0 SDK + displayName: Install .NET SDKs inputs: packageType: sdk - version: 9.x + useGlobalJson: true - # Install the .NET 8.0 runtime. + # Install the .NET 8.0 runtime to run tests that target it. - task: UseDotNet@2 displayName: Install .NET 8.0 Runtime inputs: diff --git a/eng/pipelines/stages/stress-tests-ci-stage.yml b/eng/pipelines/stages/stress-tests-ci-stage.yml index b7cea84b82..1a2ace53c0 100644 --- a/eng/pipelines/stages/stress-tests-ci-stage.yml +++ b/eng/pipelines/stages/stress-tests-ci-stage.yml @@ -60,7 +60,7 @@ parameters: - name: netFrameworkTestRuntimes displayName: .NET Framework Test Runtimes type: object - default: [net462, net47, net471, net472, net48, net481] + default: [net462] # The verbosity level for the dotnet CLI commands. - name: verbosity diff --git a/eng/pipelines/steps/compound-build-akv-step.yml b/eng/pipelines/steps/compound-build-akv-step.yml index 2dd21d8514..aa9ea67d23 100644 --- a/eng/pipelines/steps/compound-build-akv-step.yml +++ b/eng/pipelines/steps/compound-build-akv-step.yml @@ -10,54 +10,43 @@ # @TODO: NugetPackageVersion should not be used for MDS package version parameters: - - name: assemblyFileVersion - type: string + - name: assemblyFileVersion + type: string - - name: buildConfiguration - type: string - values: - - Debug - - Release + - name: buildConfiguration + type: string + values: + - Debug + - Release - - name: mdsPackageVersion - type: string + - name: mdsPackageVersion + type: string steps: - - task: DownloadSecureFile@1 - displayName: 'Download Signing Key' - inputs: - retryCount: 5 - secureFile: 'netfxKeypair.snk' - - - task: UseDotNet@2 - displayName: 'Install .NET 10.x SDK' - inputs: - packageType: 'sdk' - version: '10.x' - - - task: UseDotNet@2 - displayName: 'Install .NET 9.x Runtime' - inputs: - packageType: 'runtime' - version: '9.x' - - - task: UseDotNet@2 - displayName: 'Install .NET 8.x Runtime' - inputs: - packageType: 'runtime' - version: '8.x' - - - task: MSBuild@1 - displayName: 'Build.proj - BuildAkv' - inputs: - solution: '$(REPO_ROOT)/build.proj' - configuration: '${{ parameters.buildConfiguration }}' - msbuildArguments: >- - -t:BuildAkv - -p:AssemblyFileVersion=${{ parameters.assemblyFileVersion }} - -p:NugetPackageVersion=${{ parameters.mdsPackageVersion }} - -p:ReferenceType=Package - -p:SigningKeyPath=$(Agent.TempDirectory)/netfxKeypair.snk - - - script: tree /a /f $(BUILD_OUTPUT) - displayName: Output Build Output Tree + - task: DownloadSecureFile@1 + displayName: 'Download Signing Key' + inputs: + retryCount: 5 + secureFile: 'netfxKeypair.snk' + + # Install whichever .NET SDKs are specified in our global.json. + - task: UseDotNet@2 + displayName: Install .NET SDKs + inputs: + packageType: sdk + useGlobalJson: true + + - task: MSBuild@1 + displayName: 'Build.proj - BuildAkv' + inputs: + solution: '$(REPO_ROOT)/build.proj' + configuration: '${{ parameters.buildConfiguration }}' + msbuildArguments: >- + -t:BuildAkv + -p:AssemblyFileVersion=${{ parameters.assemblyFileVersion }} + -p:NugetPackageVersion=${{ parameters.mdsPackageVersion }} + -p:ReferenceType=Package + -p:SigningKeyPath=$(Agent.TempDirectory)/netfxKeypair.snk + + - script: tree /a /f $(BUILD_OUTPUT) + displayName: Output Build Output Tree diff --git a/eng/pipelines/steps/install-dotnet-arm64.yml b/eng/pipelines/steps/install-dotnet-arm64.yml new file mode 100644 index 0000000000..8bfa1e29e1 --- /dev/null +++ b/eng/pipelines/steps/install-dotnet-arm64.yml @@ -0,0 +1,73 @@ +################################################################################ +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################ + +# Installs the dotnet SDK or Runtime for ARM64 using the dotnet-install.ps1 +# script. This avoids a bug in UseDotNet@2: +# +# [BUG]: UseDotNet task installs x86 build +# https://github.com/microsoft/azure-pipelines-tasks/issues/20300 + +parameters: + + # True to enable debug logging. + - name: debug + type: boolean + default: false + + # Whether to install the full SDK or the "dotnet" runtime + - name: installType + type: string + values: + - Runtime + - SDK + + # SDK or Runtime version to install. + # + # See dotnet-install.ps1 documentation for version format: + # + # https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script + # + - name: version + type: string + +steps: + + - pwsh: |- + #------------------------------------------------------------------------ + # Download the dotnet-install.ps1 script + + Invoke-WebRequest -Uri "https://builds.dotnet.microsoft.com/dotnet/scripts/v1/dotnet-install.ps1" -OutFile "dotnet-install.ps1" + + #------------------------------------------------------------------------ + # Install dotnet + + $installParams = @{ + Architecture = "arm64" + Channel = "${{ parameters.version }}" + InstallDir = "$(Agent.ToolsDirectory)" + Quality = "GA" + } + + if ('${{ parameters.installType }}' -eq 'Runtime') { + $installParams.add('Runtime', 'dotnet') + } + + & ./dotnet-install.ps1 -Verbose @installParams + + #---------------------------------------------------------------------- + # Remove the install script. + + Remove-Item dotnet-install.ps1 -ErrorAction:Ignore + + #---------------------------------------------------------------------- + # Set the DOTNET_ROOT environment variable, and add the tools dir to the + # path. These values propagate back out to the pipeline and are used by + # subsequent steps. + + Write-Host "##vso[task.setvariable variable=DOTNET_ROOT]$(Agent.ToolsDirectory)" + Write-Host "##vso[task.prependpath]$(Agent.ToolsDirectory)" + + displayName: Install .NET ${{ parameters.version }} ${{ parameters.installType }} for ARM64 diff --git a/global.json b/global.json new file mode 100644 index 0000000000..b0b5938971 --- /dev/null +++ b/global.json @@ -0,0 +1,29 @@ +{ + "sdk": + { + // We currently require the .NET 10 SDK to build and test the project. + // + // We specify the most recent release, and let rollForward pick the latest + // available suitable SDK per the rollForward setting. + // + // We must specify a complete version here since this file is also used by + // the Azure Pipelines UseDotNet@2 task, which doesn't support wildcards, + // and won't roll-forward. It uses the version verbatim. + // + // GOTCHA: This file is only used by the dotnet CLI and related tools. + // Other toolchains (IDEs like Visual Studio, the .NET Framework MSBuild + // system, etc.) may use their own installed SDKs unless configured + // otherwise. + // + "version": "10.0.100", + + // Any 10.x version is acceptable. + "rollForward": "latestMinor", + + // Do not allow pre-release versions. + // + // Set this to true if you are testing the viability of pre-release SDK + // versions in your local workspace. + "allowPrerelease": false + } +} diff --git a/src/Microsoft.Data.SqlClient.sln b/src/Microsoft.Data.SqlClient.sln index 6696a8a31d..2369d884f0 100644 --- a/src/Microsoft.Data.SqlClient.sln +++ b/src/Microsoft.Data.SqlClient.sln @@ -255,7 +255,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "steps", "steps", "{EABE3A3E ..\eng\pipelines\common\templates\steps\configure-sql-server-step.yml = ..\eng\pipelines\common\templates\steps\configure-sql-server-step.yml ..\eng\pipelines\common\templates\steps\configure-sql-server-win-step.yml = ..\eng\pipelines\common\templates\steps\configure-sql-server-win-step.yml ..\eng\pipelines\common\templates\steps\copy-dlls-for-test-step.yml = ..\eng\pipelines\common\templates\steps\copy-dlls-for-test-step.yml - ..\eng\pipelines\common\templates\steps\ensure-dotnet-version.yml = ..\eng\pipelines\common\templates\steps\ensure-dotnet-version.yml ..\eng\pipelines\common\templates\steps\esrp-code-signing-step.yml = ..\eng\pipelines\common\templates\steps\esrp-code-signing-step.yml ..\eng\pipelines\common\templates\steps\generate-nuget-package-step.yml = ..\eng\pipelines\common\templates\steps\generate-nuget-package-step.yml ..\eng\pipelines\common\templates\steps\override-sni-version.yml = ..\eng\pipelines\common\templates\steps\override-sni-version.yml @@ -297,6 +296,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "steps", "steps", "{AD738BD4 ..\eng\pipelines\steps\compound-publish-symbols-step.yml = ..\eng\pipelines\steps\compound-publish-symbols-step.yml ..\eng\pipelines\steps\roslyn-analyzers-akv-step.yml = ..\eng\pipelines\steps\roslyn-analyzers-akv-step.yml ..\eng\pipelines\steps\script-output-environment-variables-step.yml = ..\eng\pipelines\steps\script-output-environment-variables-step.yml + ..\eng\pipelines\steps\install-dotnet-arm64.yml = ..\eng\pipelines\steps\install-dotnet-arm64.yml EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Data.SqlClient.UnitTests", "Microsoft.Data.SqlClient\tests\UnitTests\Microsoft.Data.SqlClient.UnitTests.csproj", "{4461063D-2F2B-274C-7E6F-F235119D258E}" From 7d5298e8277e01d57c252054a2fdd43425406c10 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Thu, 4 Dec 2025 15:22:09 -0400 Subject: [PATCH 2/7] - Removing leftover .NET 9 in a few places. --- .github/workflows/codeql.yml | 6 +----- BUILDGUIDE.md | 2 +- eng/pipelines/common/templates/jobs/ci-run-tests-job.yml | 6 ++++++ .../common/templates/steps/prepare-test-db-step.yml | 2 +- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index c5a76de2be..2197bda5f6 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -60,11 +60,7 @@ jobs: - name: Setup .NET Core SDK uses: actions/setup-dotnet@v5.0.1 with: - # TODO: Update this to .NET 10 once PR #3686 is complete. - # TODO: Replace this with global-json-file once PR #3797 is complete. - dotnet-version: 9.x - dotnet-quality: ga - #global-json-file: global.json + global-json-file: global.json # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/BUILDGUIDE.md b/BUILDGUIDE.md index e29e9d2356..c168d4cd18 100644 --- a/BUILDGUIDE.md +++ b/BUILDGUIDE.md @@ -4,7 +4,7 @@ This document provides all the necessary details to build the driver and run tes ## .NET SDK -The projects in this repo require the .NET 9.0 SDK to build. Please ensure you +The projects in this repo require the .NET 10.0 SDK to build. Please ensure you have the latest version of that SDK installed. Tests and tools may require different .NET Runtimes that may be installed diff --git a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml index 8fa3d3fcdf..c2a5133819 100644 --- a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml @@ -139,6 +139,12 @@ jobs: # GOTCHA: We always use global.json for SDK version except on ARM64, # where we have to specify it here. This must be kept synchronized with # the SDK version in global.json. + version: 10.0 + + - template: ../../../steps/install-dotnet-arm64.yml@self + parameters: + debug: ${{ parameters.debug }} + installType: Runtime version: 9.0 - template: ../../../steps/install-dotnet-arm64.yml@self diff --git a/eng/pipelines/common/templates/steps/prepare-test-db-step.yml b/eng/pipelines/common/templates/steps/prepare-test-db-step.yml index 3e01a7a9dc..250fab772a 100644 --- a/eng/pipelines/common/templates/steps/prepare-test-db-step.yml +++ b/eng/pipelines/common/templates/steps/prepare-test-db-step.yml @@ -10,7 +10,7 @@ parameters: - name: targetFramework type: string - default: net9.0 + default: net10.0 steps: - task: DotNetCoreCLI@2 From c83462d1e95b8b925d9f481beb11f5a3a2635125 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Fri, 5 Dec 2025 08:39:19 -0400 Subject: [PATCH 3/7] - Added missing .NET 9 Runtime for the test jobs. --- eng/pipelines/common/templates/jobs/ci-run-tests-job.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml index c2a5133819..a5e6da7b2d 100644 --- a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml @@ -119,6 +119,12 @@ jobs: packageType: sdk useGlobalJson: true + - task: UseDotNet@2 + displayName: Install .NET 9 Runtime + inputs: + packageType: runtime + version: 9.x + - task: UseDotNet@2 displayName: Install .NET 8 Runtime inputs: From 9834c94149db2fea0e0baf9b5b3e19003bb43b61 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Fri, 5 Dec 2025 16:38:10 -0400 Subject: [PATCH 4/7] - Created separate PowerShell script to install .NET for ARM64. - Updated install-dotnet template to handle all cases of .NET SDK and Runtime installation for the pipelines. --- .editorconfig | 4 +- .../templates/jobs/ci-build-nugets-job.yml | 8 +- .../templates/jobs/ci-code-coverage-job.yml | 10 +- .../templates/jobs/ci-run-tests-job.yml | 85 ++-------- ...ld-all-configurations-signed-dlls-step.yml | 8 +- .../common/templates/steps/pre-build-step.yml | 24 +-- eng/pipelines/jobs/stress-tests-ci-job.yml | 17 +- .../steps/compound-build-akv-step.yml | 8 +- eng/pipelines/steps/install-dotnet-arm64.ps1 | 150 ++++++++++++++++++ eng/pipelines/steps/install-dotnet-arm64.yml | 73 --------- eng/pipelines/steps/install-dotnet.yml | 110 +++++++++++++ 11 files changed, 295 insertions(+), 202 deletions(-) create mode 100644 eng/pipelines/steps/install-dotnet-arm64.ps1 delete mode 100644 eng/pipelines/steps/install-dotnet-arm64.yml create mode 100644 eng/pipelines/steps/install-dotnet.yml diff --git a/.editorconfig b/.editorconfig index cbc3fa7858..9d8000b43f 100644 --- a/.editorconfig +++ b/.editorconfig @@ -167,7 +167,9 @@ indent_size = 2 # Shell scripts [*.sh] +indent_size = 2 end_of_line = lf -[*.{cmd, bat}] +[*.{bat,cmd,ps1}] +indent_size = 2 end_of_line = crlf diff --git a/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml b/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml index 785453a41a..795f172ed4 100644 --- a/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml @@ -46,12 +46,8 @@ jobs: - ${{ if ne(parameters.prebuildSteps, '') }}: - ${{ parameters.prebuildSteps }} # extra steps to run before the build like downloading sni and the required configuration - # Install whichever .NET SDKs are specified in our global.json. - - task: UseDotNet@2 - displayName: Install .NET SDKs - inputs: - packageType: sdk - useGlobalJson: true + # Install the .NET SDK. + - template: /eng/pipelines/steps/install-dotnet.yml@self - template: ../steps/ci-project-build-step.yml@self parameters: diff --git a/eng/pipelines/common/templates/jobs/ci-code-coverage-job.yml b/eng/pipelines/common/templates/jobs/ci-code-coverage-job.yml index ab8e607809..bad36806ef 100644 --- a/eng/pipelines/common/templates/jobs/ci-code-coverage-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-code-coverage-job.yml @@ -60,12 +60,10 @@ jobs: - pwsh: 'Get-ChildItem env: | Sort-Object Name' displayName: '[Debug] List Environment Variables' - # Install whichever .NET SDKs are specified in our global.json. - - task: UseDotNet@2 - displayName: Install .NET SDKs - inputs: - packageType: sdk - useGlobalJson: true + # Install the .NET SDK. + - template: /eng/pipelines/steps/install-dotnet.yml@self + parameters: + debug: ${{ parameters.debug }} # Install additional dotnet tools. - pwsh: | diff --git a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml index a5e6da7b2d..712e472d6f 100644 --- a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml @@ -108,56 +108,13 @@ jobs: steps: - # Install .NET SDKs and runtimes. These may be needed for the pre-build - # steps. - # - # We can use the standard UseDotNet@2 task for non-ARM64 jobs. - - ${{ if eq(parameters.isArm64, false) }}: - - task: UseDotNet@2 - displayName: Install .NET SDKs - inputs: - packageType: sdk - useGlobalJson: true - - - task: UseDotNet@2 - displayName: Install .NET 9 Runtime - inputs: - packageType: runtime - version: 9.x - - - task: UseDotNet@2 - displayName: Install .NET 8 Runtime - inputs: - packageType: runtime - version: 8.x - - # For ARM64, we need to use our custom step to work around a bug in - # UseDotNet@2: - # - # [BUG]: UseDotNet task installs x86 build - # https://github.com/microsoft/azure-pipelines-tasks/issues/20300 - # - - ${{ else }}: - - template: ../../../steps/install-dotnet-arm64.yml@self - parameters: - debug: ${{ parameters.debug }} - installType: SDK - # GOTCHA: We always use global.json for SDK version except on ARM64, - # where we have to specify it here. This must be kept synchronized with - # the SDK version in global.json. - version: 10.0 - - - template: ../../../steps/install-dotnet-arm64.yml@self - parameters: - debug: ${{ parameters.debug }} - installType: Runtime - version: 9.0 - - - template: ../../../steps/install-dotnet-arm64.yml@self - parameters: - debug: ${{ parameters.debug }} - installType: Runtime - version: 8.0 + # Install the .NET SDK and Runtimes. + - template: /eng/pipelines/steps/install-dotnet.yml@self + parameters: + ${{ if parameters.isArm64 }}: + architecture: arm64 + debug: ${{ parameters.debug }} + runtimes: ['8.0', '9.0'] - ${{ if ne(parameters.prebuildSteps, '') }}: - ${{ parameters.prebuildSteps }} # extra steps to run before the build like downloading sni and the required configuration @@ -317,27 +274,13 @@ jobs: # @TODO: This setup is very confusing. Ideally we should just be utilizing the dotnet installation # earlier in the job. There has to be a cleaner way of doing this. - ${{ if ne(variables['dotnetx86RootPath'], '') }}: - # Install whichever .NET SDKs are specified in our global.json. - - task: UseDotNet@2 - displayName: Install .NET SDKs - inputs: - installationPath: $(dotnetx86RootPath) - packageType: sdk - useGlobalJson: true - env: - # Override the architecture to install for x86. - PROCESSOR_ARCHITECTURE: x86 - - # Install the .NET 8.0 runtime to run tests that target it. - - task: UseDotNet@2 - displayName: Install .NET 8.0 Runtime - inputs: - installationPath: $(dotnetx86RootPath) - packageType: runtime - version: 8.x - env: - # Override the architecture to install for x86. - PROCESSOR_ARCHITECTURE: x86 + # Install the .NET SDK and Runtimes for x86. + - template: /eng/pipelines/steps/install-dotnet.yml@self + parameters: + architecture: x86 + debug: ${{ parameters.debug }} + installDir: $(dotnetx86RootPath) + runtimes: ['8.0', '9.0'] - template: ../steps/run-all-tests-step.yml@self parameters: diff --git a/eng/pipelines/common/templates/steps/build-all-configurations-signed-dlls-step.yml b/eng/pipelines/common/templates/steps/build-all-configurations-signed-dlls-step.yml index 21bb9d35c8..8981f2d392 100644 --- a/eng/pipelines/common/templates/steps/build-all-configurations-signed-dlls-step.yml +++ b/eng/pipelines/common/templates/steps/build-all-configurations-signed-dlls-step.yml @@ -31,12 +31,8 @@ steps: secureFile: netfxKeypair.snk retryCount: 5 - # Install whichever .NET SDKs are specified in our global.json. - - task: UseDotNet@2 - displayName: Install .NET SDKs - inputs: - packageType: sdk - useGlobalJson: true + # Install the .NET SDK. + - template: /eng/pipelines/steps/install-dotnet.yml@self - ${{ if eq(parameters.product, 'MDS') }}: - task: MSBuild@1 diff --git a/eng/pipelines/common/templates/steps/pre-build-step.yml b/eng/pipelines/common/templates/steps/pre-build-step.yml index 5a0d01b30d..675324ee05 100644 --- a/eng/pipelines/common/templates/steps/pre-build-step.yml +++ b/eng/pipelines/common/templates/steps/pre-build-step.yml @@ -4,26 +4,10 @@ # See the LICENSE file in the project root for more information. # ################################################################################# steps: - # Install whichever .NET SDKs are specified in our global.json. - - task: UseDotNet@2 - displayName: Install .NET SDKs - inputs: - packageType: sdk - useGlobalJson: true - - # Install the .NET 9.0 runtime to run tests that target it. - - task: UseDotNet@2 - displayName: Install .NET 9.0 Runtime - inputs: - packageType: runtime - version: 9.x - - # Install the .NET 8.0 runtime to run tests that target it. - - task: UseDotNet@2 - displayName: Install .NET 8.0 Runtime - inputs: - packageType: runtime - version: 8.x + # Install the .NET SDK and Runtimes. + - template: /eng/pipelines/steps/install-dotnet.yml@self + parameters: + runtimes: ['8.0', '9.0'] - script: SET displayName: 'Print Environment Variables' diff --git a/eng/pipelines/jobs/stress-tests-ci-job.yml b/eng/pipelines/jobs/stress-tests-ci-job.yml index 2155e542da..2d319613d7 100644 --- a/eng/pipelines/jobs/stress-tests-ci-job.yml +++ b/eng/pipelines/jobs/stress-tests-ci-job.yml @@ -131,19 +131,10 @@ jobs: steps: - # Install whichever .NET SDKs are specified in our global.json. - - task: UseDotNet@2 - displayName: Install .NET SDKs - inputs: - packageType: sdk - useGlobalJson: true - - # Install the .NET 8.0 runtime to run tests that target it. - - task: UseDotNet@2 - displayName: Install .NET 8.0 Runtime - inputs: - packageType: runtime - version: 8.x + # Install the .NET SDK and Runtimes. + - template: /eng/pipelines/steps/install-dotnet.yml@self + parameters: + runtimes: ['8.0', '9.0'] # Download the pipeline artifact that contains the MDS package to test. - task: DownloadPipelineArtifact@2 diff --git a/eng/pipelines/steps/compound-build-akv-step.yml b/eng/pipelines/steps/compound-build-akv-step.yml index aa9ea67d23..ce8da41d52 100644 --- a/eng/pipelines/steps/compound-build-akv-step.yml +++ b/eng/pipelines/steps/compound-build-akv-step.yml @@ -29,12 +29,8 @@ steps: retryCount: 5 secureFile: 'netfxKeypair.snk' - # Install whichever .NET SDKs are specified in our global.json. - - task: UseDotNet@2 - displayName: Install .NET SDKs - inputs: - packageType: sdk - useGlobalJson: true + # Install the .NET SDK. + - template: /eng/pipelines/steps/install-dotnet.yml@self - task: MSBuild@1 displayName: 'Build.proj - BuildAkv' diff --git a/eng/pipelines/steps/install-dotnet-arm64.ps1 b/eng/pipelines/steps/install-dotnet-arm64.ps1 new file mode 100644 index 0000000000..0d55a92810 --- /dev/null +++ b/eng/pipelines/steps/install-dotnet-arm64.ps1 @@ -0,0 +1,150 @@ +<# +.SYNOPSIS + This script installs dotnet SDKs and Runtimes for ARM64. + +.DESCRIPTION + Special handling is required for ARM64 due to a bug in UseDotNet@2: + + [BUG]: UseDotNet@2 task installs x86 build + https://github.com/microsoft/azure-pipelines-tasks/issues/20300 + + The downloaded dotnet-install.ps1 script is kept in the $InstallDir to avoid + downloading it multiple times during the pipeline job. + + The following environment variables are set for subsequent steps in the pipeline: + + DOTNET_ROOT: Set to $InstallDir. + PATH: $DOTNET_ROOT is prepended to the PATH environment variable. + +.PARAMETER Debug + True to emit debug messages. Default is false. + +.PARAMETER DryRun + True to perform a dry run of the installation. Default is false. + +.PARAMETER GlobalJson + The path to the global.json file that specifies the exact SDK version to + install. Default is 'global.json'. + +.PARAMETER InstallDir + The directory to install the SDKs and Runtimes into, typically the + pipeline's $(Agent.ToolsDirectory)/dotnet directory. + + The dotnet-install.ps1 script is downloaded into this directory if it is not + already present. + + Default is '.'. + +.PARAMETER Runtimes + The versions of the .NET Runtimes to install. These must be in the runtime + channel format of X.Y expected by the dotnet-install.ps1 script. Default is + an empty array. + +.NOTES + Licensed to the .NET Foundation under one or more agreements. + The .NET Foundation licenses this file to you under the MIT license. + See the LICENSE file in the project root for more information. +#> + +param +( + [switch]$Debug, + [switch]$DryRun, + [string]$GlobalJson = "global.json", + [string]$InstallDir = '.', + [string[]]$Runtimes = @() +) + +#------------------------------------------------------------------------------ +# Emit our command-line arguments. + +if ($Debug) +{ + Write-Host "Command-line arguments:" + Write-Host ($PSBoundParameters | ConvertTo-Json -Depth 1) +} + +#------------------------------------------------------------------------------ +# Download the dotnet-install.ps1 script it if isn't already present. + +if (-not (Test-Path -Path "$InstallDir/dotnet-install.ps1" -PathType Leaf)) +{ + Write-Host "Downloading dotnet-install.ps1..." + + Invoke-WebRequest ` + -Uri "https://builds.dotnet.microsoft.com/dotnet/scripts/v1/dotnet-install.ps1" ` + -OutFile "$InstallDir/dotnet-install.ps1" ` + -Verbose:$Debug + + if ($Debug) + { + Write-Host "Emitting dotnet-install.ps1 help:" + Get-Help "$InstallDir/dotnet-install.ps1" + } +} + +#------------------------------------------------------------------------------ +# Read the SDK versions from global.json. + +$globalJsonContent = Get-Content -Raw -Path "$GlobalJson" | ConvertFrom-Json +$sdkVersion = $globalJsonContent.sdk.version + +if ($Debug) +{ + Write-Host "global.json content:" + Write-Host ($globalJsonContent | ConvertTo-Json -Depth 1) + + Write-Host "SDK version: $sdkVersion" +} + +#------------------------------------------------------------------------------ +# Install the SDK. + +Write-Host "Installing .NET SDK version: $sdkVersion" + +$installParams = +@{ + Architecture = "arm64" + Version = "$sdkVersion" + InstallDir = "$InstallDir" +} + +if ($Debug) +{ + Write-Host "dotnet-install.ps1 parameters:" + Write-Host ($installParams | ConvertTo-Json -Depth 1) +} + +& ./dotnet-install.ps1 -Verbose:$Debug -DryRun:$DryRun @installParams +#------------------------------------------------------------------------------ +# Install the Runtimes, if any. + +foreach ($channel in $Runtimes) +{ + Write-Host "Installing .NET Runtime GA channel: $channel" + + $installParams = + @{ + Architecture = "arm64" + Channel = "$channel" + InstallDir = "$InstallDir" + Quality = "GA" + Runtime = "dotnet" + } + + if ($Debug) + { + Write-Host "dotnet-install.ps1 parameters:" + Write-Host ($installParams | ConvertTo-Json -Depth 1) + } + + & ./dotnet-install.ps1 -Verbose:$Debug -DryRun:$DryRun @installParams +} + +#------------------------------------------------------------------------------ +# Set the DOTNET_ROOT environment variable, and add the tools dir to the path. +# These values propagate back out to the pipeline and are used by subsequent +# steps. + +Write-Host "##vso[task.setvariable variable=DOTNET_ROOT]$InstallDir" +Write-Host "##vso[task.prependpath]$InstallDir" diff --git a/eng/pipelines/steps/install-dotnet-arm64.yml b/eng/pipelines/steps/install-dotnet-arm64.yml deleted file mode 100644 index 8bfa1e29e1..0000000000 --- a/eng/pipelines/steps/install-dotnet-arm64.yml +++ /dev/null @@ -1,73 +0,0 @@ -################################################################################ -# Licensed to the .NET Foundation under one or more agreements. # -# The .NET Foundation licenses this file to you under the MIT license. # -# See the LICENSE file in the project root for more information. # -################################################################################ - -# Installs the dotnet SDK or Runtime for ARM64 using the dotnet-install.ps1 -# script. This avoids a bug in UseDotNet@2: -# -# [BUG]: UseDotNet task installs x86 build -# https://github.com/microsoft/azure-pipelines-tasks/issues/20300 - -parameters: - - # True to enable debug logging. - - name: debug - type: boolean - default: false - - # Whether to install the full SDK or the "dotnet" runtime - - name: installType - type: string - values: - - Runtime - - SDK - - # SDK or Runtime version to install. - # - # See dotnet-install.ps1 documentation for version format: - # - # https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script - # - - name: version - type: string - -steps: - - - pwsh: |- - #------------------------------------------------------------------------ - # Download the dotnet-install.ps1 script - - Invoke-WebRequest -Uri "https://builds.dotnet.microsoft.com/dotnet/scripts/v1/dotnet-install.ps1" -OutFile "dotnet-install.ps1" - - #------------------------------------------------------------------------ - # Install dotnet - - $installParams = @{ - Architecture = "arm64" - Channel = "${{ parameters.version }}" - InstallDir = "$(Agent.ToolsDirectory)" - Quality = "GA" - } - - if ('${{ parameters.installType }}' -eq 'Runtime') { - $installParams.add('Runtime', 'dotnet') - } - - & ./dotnet-install.ps1 -Verbose @installParams - - #---------------------------------------------------------------------- - # Remove the install script. - - Remove-Item dotnet-install.ps1 -ErrorAction:Ignore - - #---------------------------------------------------------------------- - # Set the DOTNET_ROOT environment variable, and add the tools dir to the - # path. These values propagate back out to the pipeline and are used by - # subsequent steps. - - Write-Host "##vso[task.setvariable variable=DOTNET_ROOT]$(Agent.ToolsDirectory)" - Write-Host "##vso[task.prependpath]$(Agent.ToolsDirectory)" - - displayName: Install .NET ${{ parameters.version }} ${{ parameters.installType }} for ARM64 diff --git a/eng/pipelines/steps/install-dotnet.yml b/eng/pipelines/steps/install-dotnet.yml new file mode 100644 index 0000000000..70b151c0a2 --- /dev/null +++ b/eng/pipelines/steps/install-dotnet.yml @@ -0,0 +1,110 @@ +################################################################################ +# Licensed to the .NET Foundation under one or more agreements. # +# The .NET Foundation licenses this file to you under the MIT license. # +# See the LICENSE file in the project root for more information. # +################################################################################ + +# This template installs a single .NET SDK and zero or more .NET Runtimes. The +# SDK version is always read from the root global.json file. The Runtimes to +# install, if any, may be provided as an array of version strings. +# +# Special handling is required for ARM64 due to a bug in UseDotNet@2: +# +# [BUG]: UseDotNet@2 task installs x86 build +# https://github.com/microsoft/azure-pipelines-tasks/issues/20300 + +parameters: + + # The architecture to install for. + - name: architecture + type: string + values: + - x64 + - x86 + - arm64 + default: x64 + + # True to enable debug logging. + - name: debug + type: boolean + default: false + + # The directory to install to. + - name: installDir + type: string + default: $(Agent.ToolsDirectory)/dotnet + + # The list of .NET Runtimes to install, if any. + # + # When architecture is arm64, these must adhere to the format expected by the + # dotnet-install.ps1 script: + # + # https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script + # + # Otherwise, these must adhere to the format expected by the UseDotNet@2 task: + # + # https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/reference/use-dotnet-v2 + # + - name: runtimes + type: object + default: [] + +steps: + + # Use the UseDotNet@2 task for all architectures except ARM64. + - ${{ if ne(parameters.architecture, 'arm64') }}: + + # Install the SDK listed in the global.json file. + - task: UseDotNet@2 + displayName: Install .NET SDK (global.json) + inputs: + installationPath: ${{ parameters.installDir }} + packageType: sdk + useGlobalJson: true + ${{ if eq(parameters.architecture, 'x86') }}: + env: + PROCESSOR_ARCHITECTURE: x86 + + # Install the desired Runtimes, if any. + - ${{ each version in parameters.runtimes }}: + - task: UseDotNet@2 + displayName: Install .NET ${{ version }} Runtime + inputs: + installationPath: ${{ parameters.installDir }} + packageType: runtime + version: ${{ version }} + ${{ if eq(parameters.architecture, 'x86') }}: + env: + PROCESSOR_ARCHITECTURE: x86 + + # Special handling for ARM64. + - ${{ else }}: + + # The runtimes array must be formatted as a comma-separated string with each + # runtime enclosed in single-quotes. This prevents PowerShell from + # interpreting each runtime as a decimal number and removing trailing '.0'. + - pwsh: | + $runtimes = ` + @( ${{ join(parameters.runtimes, ', ') }} ) | ` + ForEach-Object { "'$_'" } | ` + Join-String -Separator "," + + Write-Host "install-dotnet Runtimes: $runtimes" + + Write-Host "##vso[task.setvariable variable=installDotnetRuntimesArg]$runtimes" + displayName: Format runtimes for PowerShell parameter + + # Use the install script for ARM64. + - task: PowerShell@2 + displayName: Install .NET SDK and Runtimes for ARM64 + pwsh: true + filePath: install-dotnet-arm64.ps1 + arguments: > + -Debug:${{ parameters.debug }} + -GlobalJson "$(Build.SourcesDirectory)/global.json" + -InstallDir "${{ parameters.installDir }}" + -Runtimes $(installDotnetRuntimesArg) + + # Report what was installed. + - pwsh: dotnet --info + displayName: Report installed .NET SDK and Runtimes From 8960c4d106d918d232c8047077c1a6d67fd7ca97 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Mon, 8 Dec 2025 09:08:17 -0400 Subject: [PATCH 5/7] - Fixed .NET Runtime versions when calling install-dotnet template. --- eng/pipelines/common/templates/jobs/ci-run-tests-job.yml | 4 ++-- eng/pipelines/jobs/stress-tests-ci-job.yml | 2 +- src/Microsoft.Data.SqlClient.sln | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml index 712e472d6f..9aca34573f 100644 --- a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml @@ -114,7 +114,7 @@ jobs: ${{ if parameters.isArm64 }}: architecture: arm64 debug: ${{ parameters.debug }} - runtimes: ['8.0', '9.0'] + runtimes: ['8.x', '9.x'] - ${{ if ne(parameters.prebuildSteps, '') }}: - ${{ parameters.prebuildSteps }} # extra steps to run before the build like downloading sni and the required configuration @@ -280,7 +280,7 @@ jobs: architecture: x86 debug: ${{ parameters.debug }} installDir: $(dotnetx86RootPath) - runtimes: ['8.0', '9.0'] + runtimes: ['8.x', '9.x'] - template: ../steps/run-all-tests-step.yml@self parameters: diff --git a/eng/pipelines/jobs/stress-tests-ci-job.yml b/eng/pipelines/jobs/stress-tests-ci-job.yml index 2d319613d7..756b9b16c2 100644 --- a/eng/pipelines/jobs/stress-tests-ci-job.yml +++ b/eng/pipelines/jobs/stress-tests-ci-job.yml @@ -134,7 +134,7 @@ jobs: # Install the .NET SDK and Runtimes. - template: /eng/pipelines/steps/install-dotnet.yml@self parameters: - runtimes: ['8.0', '9.0'] + runtimes: ['8.x', '9.x'] # Download the pipeline artifact that contains the MDS package to test. - task: DownloadPipelineArtifact@2 diff --git a/src/Microsoft.Data.SqlClient.sln b/src/Microsoft.Data.SqlClient.sln index 2369d884f0..015bc91135 100644 --- a/src/Microsoft.Data.SqlClient.sln +++ b/src/Microsoft.Data.SqlClient.sln @@ -296,7 +296,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "steps", "steps", "{AD738BD4 ..\eng\pipelines\steps\compound-publish-symbols-step.yml = ..\eng\pipelines\steps\compound-publish-symbols-step.yml ..\eng\pipelines\steps\roslyn-analyzers-akv-step.yml = ..\eng\pipelines\steps\roslyn-analyzers-akv-step.yml ..\eng\pipelines\steps\script-output-environment-variables-step.yml = ..\eng\pipelines\steps\script-output-environment-variables-step.yml - ..\eng\pipelines\steps\install-dotnet-arm64.yml = ..\eng\pipelines\steps\install-dotnet-arm64.yml + ..\eng\pipelines\steps\install-dotnet.yml = ..\eng\pipelines\steps\install-dotnet.yml + ..\eng\pipelines\steps\install-dotnet-arm64.ps1 = ..\eng\pipelines\steps\install-dotnet-arm64.ps1 EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Data.SqlClient.UnitTests", "Microsoft.Data.SqlClient\tests\UnitTests\Microsoft.Data.SqlClient.UnitTests.csproj", "{4461063D-2F2B-274C-7E6F-F235119D258E}" From 2ca062ac019b7a3b3c565cebaddc3e966704214c Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Mon, 8 Dec 2025 10:31:38 -0400 Subject: [PATCH 6/7] - Added missing ARM64 flag to test config. - Formatting ARM64 runtimes with quotes. --- eng/pipelines/dotnet-sqlclient-ci-core.yml | 1 + eng/pipelines/steps/install-dotnet.yml | 18 +++--------------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/eng/pipelines/dotnet-sqlclient-ci-core.yml b/eng/pipelines/dotnet-sqlclient-ci-core.yml index 9f796e768d..388b2429fa 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-core.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-core.yml @@ -377,6 +377,7 @@ stages: pool: ADO-CI-PUBLIC-ARM64-1ES-EUS-POOL images: Win11_ARM64_Azure_Sql: ADO-WIN11-ARM64 + isArm64: true, TargetFrameworks: ${{parameters.targetFrameworks }} netcoreVersionTestUtils: ${{parameters.netcoreVersionTestUtils }} buildPlatforms: ${{parameters.buildPlatforms }} diff --git a/eng/pipelines/steps/install-dotnet.yml b/eng/pipelines/steps/install-dotnet.yml index 70b151c0a2..99c0a4faf0 100644 --- a/eng/pipelines/steps/install-dotnet.yml +++ b/eng/pipelines/steps/install-dotnet.yml @@ -80,30 +80,18 @@ steps: # Special handling for ARM64. - ${{ else }}: - # The runtimes array must be formatted as a comma-separated string with each - # runtime enclosed in single-quotes. This prevents PowerShell from - # interpreting each runtime as a decimal number and removing trailing '.0'. - - pwsh: | - $runtimes = ` - @( ${{ join(parameters.runtimes, ', ') }} ) | ` - ForEach-Object { "'$_'" } | ` - Join-String -Separator "," - - Write-Host "install-dotnet Runtimes: $runtimes" - - Write-Host "##vso[task.setvariable variable=installDotnetRuntimesArg]$runtimes" - displayName: Format runtimes for PowerShell parameter - # Use the install script for ARM64. - task: PowerShell@2 displayName: Install .NET SDK and Runtimes for ARM64 pwsh: true filePath: install-dotnet-arm64.ps1 + # Each runtime must be quoted to avoid PowerShell interpreting them as + # decimal numbers and truncating the fractional part. arguments: > -Debug:${{ parameters.debug }} -GlobalJson "$(Build.SourcesDirectory)/global.json" -InstallDir "${{ parameters.installDir }}" - -Runtimes $(installDotnetRuntimesArg) + -Runtimes "${{ join(parameters.runtimes, '", "') }}" # Report what was installed. - pwsh: dotnet --info From 897a15a2a1c7f903cead46e61c0f91b2811593f6 Mon Sep 17 00:00:00 2001 From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com> Date: Mon, 8 Dec 2025 10:59:06 -0400 Subject: [PATCH 7/7] - Using wildcards for .NET runtimes (except ARM64). --- eng/pipelines/common/templates/jobs/ci-run-tests-job.yml | 8 ++++++-- eng/pipelines/common/templates/steps/pre-build-step.yml | 2 +- eng/pipelines/jobs/stress-tests-ci-job.yml | 2 +- eng/pipelines/steps/install-dotnet-arm64.ps1 | 3 ++- eng/pipelines/steps/install-dotnet.yml | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml index 9aca34573f..2227625cad 100644 --- a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml @@ -113,8 +113,12 @@ jobs: parameters: ${{ if parameters.isArm64 }}: architecture: arm64 + # ARM64 needs to specify slightly different runtime version formats. + # See the install-dotnet template docs for more info. + runtimes: ['8.0', '9.0'] + ${{ else }}: + runtimes: [8.x, 9.x] debug: ${{ parameters.debug }} - runtimes: ['8.x', '9.x'] - ${{ if ne(parameters.prebuildSteps, '') }}: - ${{ parameters.prebuildSteps }} # extra steps to run before the build like downloading sni and the required configuration @@ -280,7 +284,7 @@ jobs: architecture: x86 debug: ${{ parameters.debug }} installDir: $(dotnetx86RootPath) - runtimes: ['8.x', '9.x'] + runtimes: [8.x, 9.x] - template: ../steps/run-all-tests-step.yml@self parameters: diff --git a/eng/pipelines/common/templates/steps/pre-build-step.yml b/eng/pipelines/common/templates/steps/pre-build-step.yml index 675324ee05..068223af70 100644 --- a/eng/pipelines/common/templates/steps/pre-build-step.yml +++ b/eng/pipelines/common/templates/steps/pre-build-step.yml @@ -7,7 +7,7 @@ steps: # Install the .NET SDK and Runtimes. - template: /eng/pipelines/steps/install-dotnet.yml@self parameters: - runtimes: ['8.0', '9.0'] + runtimes: [8.x, 9.x] - script: SET displayName: 'Print Environment Variables' diff --git a/eng/pipelines/jobs/stress-tests-ci-job.yml b/eng/pipelines/jobs/stress-tests-ci-job.yml index 756b9b16c2..5683382597 100644 --- a/eng/pipelines/jobs/stress-tests-ci-job.yml +++ b/eng/pipelines/jobs/stress-tests-ci-job.yml @@ -134,7 +134,7 @@ jobs: # Install the .NET SDK and Runtimes. - template: /eng/pipelines/steps/install-dotnet.yml@self parameters: - runtimes: ['8.x', '9.x'] + runtimes: [8.x, 9.x] # Download the pipeline artifact that contains the MDS package to test. - task: DownloadPipelineArtifact@2 diff --git a/eng/pipelines/steps/install-dotnet-arm64.ps1 b/eng/pipelines/steps/install-dotnet-arm64.ps1 index 0d55a92810..f73ade7ac0 100644 --- a/eng/pipelines/steps/install-dotnet-arm64.ps1 +++ b/eng/pipelines/steps/install-dotnet-arm64.ps1 @@ -65,7 +65,7 @@ if ($Debug) } #------------------------------------------------------------------------------ -# Download the dotnet-install.ps1 script it if isn't already present. +# Download the dotnet-install.ps1 script if it isn't already present. if (-not (Test-Path -Path "$InstallDir/dotnet-install.ps1" -PathType Leaf)) { @@ -116,6 +116,7 @@ if ($Debug) } & ./dotnet-install.ps1 -Verbose:$Debug -DryRun:$DryRun @installParams + #------------------------------------------------------------------------------ # Install the Runtimes, if any. diff --git a/eng/pipelines/steps/install-dotnet.yml b/eng/pipelines/steps/install-dotnet.yml index 99c0a4faf0..397ea897a2 100644 --- a/eng/pipelines/steps/install-dotnet.yml +++ b/eng/pipelines/steps/install-dotnet.yml @@ -37,7 +37,7 @@ parameters: # The list of .NET Runtimes to install, if any. # # When architecture is arm64, these must adhere to the format expected by the - # dotnet-install.ps1 script: + # dotnet-install.ps1 script's -Channel option: # # https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-install-script #