diff --git a/build.proj b/build.proj index 4ff29a08df..91c8729f23 100644 --- a/build.proj +++ b/build.proj @@ -247,8 +247,8 @@ $(TestFilters)&category!=signed @@ -394,7 +394,7 @@ environments. Please consider running project specific test targets or specific test sets within the project. --> - + @@ -452,6 +452,8 @@ "$(DotnetPath)dotnet" build "$(SqlClientNotSupportedProjectPath)" + + -p:Configuration=$(Configuration) -p:GenApiPath="@(GenApiArtifactPath->'%(FullPath)')" $(SigningKeyPathArgument) @@ -483,6 +485,8 @@ "$(DotnetPath)dotnet" build $(SqlClientRefProjectPath) + + -p:Configuration=$(Configuration) $(SigningKeyPathArgument) @@ -491,7 +495,7 @@ $(BuildSuffixArgument) $(PackageVersionSqlClientArgument) - + $(ReferenceTypeArgument) $(PackageVersionAbstractionsArgument) $(PackageVersionSqlServerArgument) @@ -512,6 +516,8 @@ "$(DotnetPath)dotnet" build $(SqlClientProjectPath) + + -p:Configuration=$(Configuration) -p:TargetOs=Unix $(SigningKeyPathArgument) @@ -543,11 +549,13 @@ "$(DotnetPath)dotnet" build $(SqlClientProjectPath) + + -p:Configuration=$(Configuration) -p:TargetOs=Windows_NT $(SigningKeyPathArgument) - + $(BuildNumberArgument) $(BuildSuffixArgument) $(PackageVersionSqlClientArgument) @@ -586,6 +594,8 @@ "$(DotnetPath)dotnet" pack "$(SqlClientProjectPath)" + + -p:Configuration=$(Configuration) $(PackBuildArgument) $(SigningKeyPathArgument) @@ -601,7 +611,7 @@ $(PackageVersionLoggingArgument) $(PackageVersionSqlServerArgument) - + -p:PackageOutputPath="$(SqlClientPackageArtifactRoot)" @@ -635,7 +645,12 @@ "$(DotnetPath)dotnet" test "$(SqlClientFunctionalTestProjectPath)" + + -p:Configuration=$(Configuration) + $(SigningKeyPathArgument) + + $(TestBlameArgument) $(TestCodeCoverageArgument) $(TestFiltersArgument) @@ -680,7 +695,12 @@ "$(DotnetPath)dotnet" test "$(SqlClientManualTestProjectPath)" + + -p:Configuration=$(Configuration) + $(SigningKeyPathArgument) + + $(TestBlameArgument) $(TestCodeCoverageArgument) $(ManualTestFiltersArgument) @@ -710,17 +730,24 @@ "$(DotnetPath)dotnet" test "$(SqlClientUnitTestProjectPath)" + + -p:Configuration=$(Configuration) + $(SigningKeyPathArgument) + $(TestSigningKeyPathArgument) + + $(TestBlameArgument) $(TestCodeCoverageArgument) $(TestFiltersArgument) $(TestFrameworkArgument) + --results-directory "$(TestResultsFolderPath)" + --logger:"trx;LogFilePrefix=$(LogFilePrefix)" + + $(ReferenceTypeArgument) - $(TestSigningKeyPathArgument) $(PackageVersionSqlClientArgument) $(PackageVersionSqlServerArgument) - --results-directory "$(TestResultsFolderPath)" - --logger:"trx;LogFilePrefix=$(LogFilePrefix)" @@ -746,15 +773,17 @@ "$(DotnetPath)dotnet" build "$(AkvProviderProjectPath)" + + -p:Configuration=$(Configuration) $(SigningKeyPathArgument) - + $(BuildNumberArgument) $(BuildSuffixArgument) $(PackageVersionAkvProviderArgument) - + $(ReferenceTypeArgument) $(PackageVersionAbstractionsArgument) $(PackageVersionLoggingArgument) @@ -774,6 +803,8 @@ "$(DotnetPath)dotnet" pack "$(AkvProviderProjectPath)" + + -p:Configuration=$(Configuration) $(PackBuildArgument) $(SigningKeyPathArgument) @@ -827,6 +858,8 @@ "$(DotnetPath)dotnet" build "$(AbstractionsProjectPath)" + + -p:Configuration=$(Configuration) $(SigningKeyPathArgument) @@ -852,6 +885,8 @@ "$(DotnetPath)dotnet" pack "$(AbstractionsProjectPath)" + + -p:Configuration=$(Configuration) $(PackBuildArgument) $(SigningKeyPathArgument) @@ -887,22 +922,28 @@ - AbstractionsTests-$(OS) $(LogFilePrefix)-$(TestFramework) "$(DotnetPath)dotnet" test "$(AbstractionsTestProjectPath)" + + -p:Configuration=$(Configuration) + $(SigningKeyPathArgument) + $(TestSigningKeyPathArgument) + + $(TestBlameArgument) $(TestCodeCoverageArgument) $(TestFiltersArgument) $(TestFrameworkArgument) --results-directory "$(TestResultsFolderPath)" --logger:"trx;LogFilePrefix=$(LogFilePrefix)" + + + $(ReferenceTypeArgument) + $(PackageVersionLoggingArgument) $([System.Text.RegularExpressions.Regex]::Replace($(DotnetCommand), "\s+", " ")) @@ -929,6 +970,8 @@ "$(DotnetPath)dotnet" build "$(AzureProjectPath)" + + -p:Configuration=$(Configuration) $(SigningKeyPathArgument) @@ -937,7 +980,7 @@ $(BuildSuffixArgument) $(PackageVersionAzureArgument) - + $(ReferenceTypeArgument) $(PackageVersionLoggingArgument) @@ -954,6 +997,8 @@ "$(DotnetPath)dotnet" pack "$(AzureProjectPath)" + + -p:Configuration=$(Configuration) $(PackBuildArgument) $(SigningKeyPathArgument) @@ -994,7 +1039,13 @@ "$(DotnetPath)dotnet" test "$(AzureTestProjectPath)" + + -p:Configuration=$(Configuration) + $(SigningKeyPathArgument) + $(TestSigningKeyPathArgument) + + $(TestBlameArgument) $(TestCodeCoverageArgument) $(TestFiltersArgument) @@ -1002,7 +1053,7 @@ --results-directory "$(TestResultsFolderPath)" --logger:"trx;LogFilePrefix=$(LogFilePrefix)" - + $(ReferenceTypeArgument) $(PackageVersionAbstractionsArgument) $(PackageVersionLoggingArgument) @@ -1022,6 +1073,7 @@ $(RepoRoot)src/Microsoft.Data.SqlClient.Internal/Logging/src/ $(LoggingSrcRoot)Logging.csproj + $(RepoRoot)src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj $(RepoRoot)artifacts/Microsoft.Data.SqlClient.Internal.Logging/$(Configuration)/ @@ -1030,6 +1082,8 @@ "$(DotnetPath)dotnet" build $(LoggingProjectPath) + + -p:Configuration=$(Configuration) $(SigningKeyPathArgument) @@ -1051,6 +1105,8 @@ "$(DotnetPath)dotnet" pack $(LoggingProjectPath) + + -p:Configuration=$(Configuration) $(PackBuildArgument) $(SigningKeyPathArgument) @@ -1079,6 +1135,39 @@ SkipUnchangedFiles="true" /> + + + + LoggingTests-$(OS) + $(LogFilePrefix)-$(TestFramework) + + + "$(DotnetPath)dotnet" test "$(LoggingTestProjectPath)" + + + -p:Configuration=$(Configuration) + $(SigningKeyPathArgument) + $(TestSigningKeyPathArgument) + + + $(TestBlameArgument) + $(TestCodeCoverageArgument) + $(TestFiltersArgument) + $(TestFrameworkArgument) + --results-directory "$(TestResultsFolderPath)" + --logger:"trx;LogFilePrefix=$(LogFilePrefix)" + + + $(ReferenceTypeArgument) + + + $([System.Text.RegularExpressions.Regex]::Replace($(DotnetCommand), "\s+", " ")) + + + + + + @@ -1092,10 +1181,12 @@ "$(DotnetPath)dotnet" build $(SqlServerProjectPath) + + -p:Configuration=$(Configuration) $(SigningKeyPathArgument) - + $(BuildNumberArgument) $(BuildSuffixArgument) $(PackageVersionSqlServerArgument) @@ -1113,6 +1204,8 @@ "$(DotnetPath)dotnet" pack $(SqlServerProjectPath) + + -p:Configuration=$(Configuration) $(PackBuildArgument) $(SigningKeyPathArgument) diff --git a/eng/pipelines/ci/package/sqlclient-package.yml b/eng/pipelines/ci/package/sqlclient-package.yml index e194e2abef..244993c23d 100644 --- a/eng/pipelines/ci/package/sqlclient-package.yml +++ b/eng/pipelines/ci/package/sqlclient-package.yml @@ -11,7 +11,7 @@ # - On pushes to GitHub main and ADO internal/main (batched) # - Nightly at 00:00 UTC on both branches # -# On internal/main the strong-name signing key is downloaded and used to sign assemblies during the +# On internal/main the assembly signing key is downloaded and used to sign assemblies during the # build. # # GOTCHA: This pipeline definition is triggered by GitHub _and_ ADO CI. We distinguish the two via @@ -89,10 +89,10 @@ variables: value: ${{ eq(variables['System.TeamProject'], 'ADO.Net') }} # Signing key argument passed to build.proj. On internal builds this references the secure file - # downloaded by DownloadSecureFile@1; on public builds it expands to empty. + # downloaded by download-assembly-signing-key.yml; on public builds it expands to empty. - name: signingKeyArg ${{ if eq(variables.isInternalBuild, true) }}: - value: '-p:SigningKeyPath="$(keyFile.secureFilePath)"' + value: '-p:SigningKeyPath="$(driverKeyFile.secureFilePath)"' ${{ else }}: value: '' @@ -133,13 +133,9 @@ jobs: Write-Host 'Done.' displayName: Clean packages/ directory - # On internal builds, download the strong-name signing key. + # On internal builds, download the assembly signing key. - ${{ if eq(variables.isInternalBuild, true) }}: - - task: DownloadSecureFile@1 - displayName: Download Signing Key - inputs: - secureFile: netfxKeypair.snk - name: keyFile + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self # Run the Pack target via build.proj. - task: DotNetCoreCLI@2 diff --git a/eng/pipelines/common/steps/download-assembly-signing-key.yml b/eng/pipelines/common/steps/download-assembly-signing-key.yml new file mode 100644 index 0000000000..b7c415f74d --- /dev/null +++ b/eng/pipelines/common/steps/download-assembly-signing-key.yml @@ -0,0 +1,39 @@ +################################################################################ +# 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. +################################################################################ + +# Downloads a signing key from ADO secure files. +# +# When isTest is false, downloads the driver signing key and exports it as 'driverKeyFile'. When +# isTest is true, downloads the test signing key and exports it as 'testKeyFile'. +# +# Downstream steps reference the path via: +# +# $(driverKeyFile.secureFilePath) or +# $(testKeyFile.secureFilePath) + +parameters: + + # When false, download the driver signing key. + # When true, download the test signing key. + - name: isTest + type: boolean + default: false + +steps: + + - ${{ if eq(parameters.isTest, false) }}: + - task: DownloadSecureFile@1 + displayName: Download Driver Signing Key + inputs: + secureFile: netfxKeypair.snk + name: driverKeyFile + + - ${{ if eq(parameters.isTest, true) }}: + - task: DownloadSecureFile@1 + displayName: Download Test Signing Key + inputs: + secureFile: sqlclient-test-key.snk + name: testKeyFile 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 aa6a1c50c5..50d017f459 100644 --- a/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-build-nugets-job.yml @@ -87,6 +87,11 @@ parameters: type: string default: SqlServer.Artifacts + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + jobs: - job: build_mds_akv_packages_job displayName: Build MDS & AKV Packages @@ -137,6 +142,10 @@ jobs: # Restore dotnet CLI tools (e.g. pwsh, apicompat) before building. - template: /eng/pipelines/common/steps/restore-dotnet-tools.yml@self + # Download the assembly signing key for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + # When we're performing a Debug build, we still want to try _compiling_ the # code in Release mode to ensure downstream pipelines don't encounter # compilation errors. We won't use the Release artifacts for anything else @@ -159,6 +168,8 @@ jobs: abstractionsPackageVersion: ${{parameters.abstractionsPackageVersion}} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} + ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + signingKeyPath: $(driverKeyFile.secureFilePath) - task: DotNetCoreCLI@2 displayName: 'Create MDS NuGet Package' @@ -206,6 +217,8 @@ jobs: mdsPackageVersion: ${{ parameters.mdsPackageVersion }} akvPackageVersion: ${{ parameters.akvPackageVersion }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} + ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + signingKeyPath: $(driverKeyFile.secureFilePath) - task: DotNetCoreCLI@2 displayName: 'Create AKV Provider NuGet Package' 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 1b1ea7a2e7..1bbaef213a 100644 --- a/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml +++ b/eng/pipelines/common/templates/jobs/ci-run-tests-job.yml @@ -160,6 +160,11 @@ parameters: - name: saPassword type: string + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + jobs: - job: ${{ format('{0}', coalesce(parameters.jobDisplayName, parameters.image, 'unknown_image')) }} @@ -223,6 +228,13 @@ jobs: # Restore dotnet CLI tools (e.g. pwsh, apicompat) before building. - template: /eng/pipelines/common/steps/restore-dotnet-tools.yml@self + # Download the assembly signing keys for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + parameters: + isTest: true + - ${{ if ne(parameters.prebuildSteps, '') }}: - ${{ parameters.prebuildSteps }} # extra steps to run before the build like downloading sni and the required configuration @@ -378,6 +390,9 @@ jobs: loggingPackageVersion: ${{ parameters.loggingPackageVersion }} mdsPackageVersion: ${{ parameters.mdsPackageVersion }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} + ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + signingKeyPath: $(driverKeyFile.secureFilePath) + testSigningKeyPath: $(testKeyFile.secureFilePath) - ${{ if and(eq(parameters.enableX86Test, true), eq(parameters.operatingSystem, 'Windows')) }}: - template: /eng/pipelines/common/templates/steps/run-all-tests-step.yml@self @@ -394,6 +409,9 @@ jobs: loggingPackageVersion: ${{ parameters.loggingPackageVersion }} mdsPackageVersion: ${{ parameters.mdsPackageVersion }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} + ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + signingKeyPath: $(driverKeyFile.secureFilePath) + testSigningKeyPath: $(testKeyFile.secureFilePath) - template: /eng/pipelines/common/templates/steps/publish-test-results-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 86ddc0ca45..86c86f7aec 100644 --- a/eng/pipelines/common/templates/stages/ci-run-tests-stage.yml +++ b/eng/pipelines/common/templates/stages/ci-run-tests-stage.yml @@ -88,6 +88,11 @@ parameters: - name: testJobTimeout type: number + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + stages: - ${{ each config in parameters.testConfigurations }}: - ${{ each image in config.value.images }}: @@ -124,6 +129,7 @@ stages: loggingPackageVersion: ${{ parameters.loggingPackageVersion }} mdsArtifactsName: ${{ parameters.mdsArtifactsName }} mdsPackageVersion: ${{ parameters.mdsPackageVersion }} + isInternalBuild: ${{ parameters.isInternalBuild }} sqlServerArtifactsName: ${{ parameters.sqlServerArtifactsName }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} prebuildSteps: ${{ parameters.prebuildSteps }} @@ -162,6 +168,7 @@ stages: loggingPackageVersion: ${{ parameters.loggingPackageVersion }} mdsArtifactsName: ${{ parameters.mdsArtifactsName }} mdsPackageVersion: ${{ parameters.mdsPackageVersion }} + isInternalBuild: ${{ parameters.isInternalBuild }} sqlServerArtifactsName: ${{ parameters.sqlServerArtifactsName }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} prebuildSteps: ${{ parameters.prebuildSteps }} 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 e5fa6d4424..a4b980f46e 100644 --- a/eng/pipelines/common/templates/steps/ci-project-build-step.yml +++ b/eng/pipelines/common/templates/steps/ci-project-build-step.yml @@ -73,6 +73,13 @@ parameters: type: string default: $(sqlServerPackageVersion) + # Path to the assembly signing key file. When non-empty, passed as -p:SigningKeyPath="" to the + # build. The calling job is responsible for downloading the key (via + # download-assembly-signing-key.yml). + - name: signingKeyPath + type: string + default: '' + steps: # Build MDS - ${{ if or(eq(parameters.build, 'MDS'), eq(parameters.build, 'all'), eq(parameters.build, 'allNoDocs')) }}: @@ -91,6 +98,7 @@ steps: -p:PackageVersionLogging=${{ parameters.loggingPackageVersion }} -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" # Build AKV Provider - ${{ if or(eq(parameters.build, 'AkvProvider'), eq(parameters.build, 'all'), eq(parameters.build, 'allNoDocs')) }}: @@ -110,3 +118,4 @@ steps: -p:PackageVersionLogging=${{ parameters.loggingPackageVersion }} -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" diff --git a/eng/pipelines/common/templates/steps/run-all-tests-step.yml b/eng/pipelines/common/templates/steps/run-all-tests-step.yml index e41c7d22b2..02c22087b4 100644 --- a/eng/pipelines/common/templates/steps/run-all-tests-step.yml +++ b/eng/pipelines/common/templates/steps/run-all-tests-step.yml @@ -72,6 +72,18 @@ parameters: type: number default: 2 + # Path to the assembly signing key file. When non-empty, passed to build.proj so that the + # test-filter logic can include category=signed tests. + - name: signingKeyPath + type: string + default: '' + + # Path to the test assembly signing key file. When non-empty, passed to build.proj so that test + # assemblies are signed and can satisfy InternalsVisibleTo grants from signed source assemblies. + - name: testSigningKeyPath + type: string + default: '' + steps: - ${{ if parameters.debug }}: - powershell: 'dotnet sdk check' @@ -94,6 +106,8 @@ steps: -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" ${{ else }}: # x86 arguments: >- -t:TestSqlClientUnit @@ -104,6 +118,8 @@ steps: -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:DotnetPath=${{ parameters.dotnetx86RootPath }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" - task: DotNetCoreCLI@2 displayName: 'Run Flaky Unit Tests ${{parameters.msbuildArchitecture }}' @@ -122,6 +138,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" ${{ else }}: # x86 arguments: >- -t:TestSqlClientUnit @@ -134,6 +152,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" continueOnError: true - task: DotNetCoreCLI@2 @@ -153,6 +173,8 @@ steps: -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" ${{ else }}: # x86 arguments: >- -t:TestSqlClientFunctional @@ -165,6 +187,8 @@ steps: -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:DotnetPath=${{ parameters.dotnetx86RootPath }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" - task: DotNetCoreCLI@2 displayName: 'Run Flaky Functional Tests ${{parameters.msbuildArchitecture }}' @@ -185,6 +209,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" ${{ else }}: # x86 arguments: >- -t:TestSqlClientFunctional @@ -199,6 +225,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" continueOnError: true - task: DotNetCoreCLI@2 @@ -219,6 +247,8 @@ steps: -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" ${{ else }}: # x86 arguments: >- -t:TestSqlClientManual @@ -232,6 +262,8 @@ steps: -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:DotnetPath=${{ parameters.dotnetx86RootPath }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" retryCountOnTaskFailure: ${{parameters.retryCountOnManualTests }} - task: DotNetCoreCLI@2 @@ -254,6 +286,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" ${{ else }}: # x86 arguments: >- -t:TestSqlClientManual @@ -269,6 +303,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" continueOnError: true - ${{ else }}: # Linux or macOS @@ -286,6 +322,8 @@ steps: -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" - task: DotNetCoreCLI@2 displayName: 'Run Flaky Unit Tests' @@ -303,6 +341,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" continueOnError: true - task: DotNetCoreCLI@2 @@ -321,6 +361,8 @@ steps: -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" - task: DotNetCoreCLI@2 displayName: 'Run Flaky Functional Tests' @@ -340,6 +382,8 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" continueOnError: true - task: DotNetCoreCLI@2 displayName: 'Run Manual Tests' @@ -358,6 +402,8 @@ steps: -p:PackageVersionSqlClient=${{ parameters.mdsPackageVersion }} -p:PackageVersionSqlServer=${{ parameters.sqlServerPackageVersion }} -p:TestResultsFolderPath=TestResults + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" retryCountOnTaskFailure: ${{parameters.retryCountOnManualTests }} - task: DotNetCoreCLI@2 @@ -379,4 +425,6 @@ steps: -p:TestFilters="category=flaky" -p:TestResultsFolderPath=TestResults -p:TestCodeCoverage=false + -p:SigningKeyPath="${{ parameters.signingKeyPath }}" + -p:TestSigningKeyPath="${{ parameters.testSigningKeyPath }}" continueOnError: true diff --git a/eng/pipelines/dotnet-sqlclient-ci-core.yml b/eng/pipelines/dotnet-sqlclient-ci-core.yml index 9ee7c7132d..2df5d62e1e 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-core.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-core.yml @@ -104,6 +104,12 @@ parameters: - detailed - diagnostic + # True when building on the internal ADO.Net project. Internal builds may perform additional or + # different steps, such as assembly signing. + - name: isInternalBuild + type: boolean + default: false + variables: - template: /eng/pipelines/libraries/ci-build-variables.yml@self @@ -138,6 +144,8 @@ stages: buildConfiguration: ${{ parameters.buildConfiguration }} debug: ${{ parameters.debug }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} + referenceType: ${{ parameters.referenceType }} # Build the Logging package, and publish it to the pipeline artifacts # under the given artifact name. This runs in parallel with the Secrets @@ -150,6 +158,8 @@ stages: buildConfiguration: ${{ parameters.buildConfiguration }} debug: ${{ parameters.debug }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} + referenceType: ${{ parameters.referenceType }} # Build the Abstractions package, and publish it to the pipeline artifacts # under the given artifact name. @@ -167,6 +177,7 @@ stages: loggingArtifactsName: $(loggingArtifactsName) loggingPackageVersion: $(loggingPackageVersion) referenceType: ${{ parameters.referenceType }} + isInternalBuild: ${{ parameters.isInternalBuild }} # When building Abstractions via packages, we must depend on the Logging # package. ${{ if eq(parameters.referenceType, 'Package') }}: @@ -188,6 +199,7 @@ stages: mdsPackageVersion: $(mdsPackageVersion) akvPackageVersion: $(akvPackageVersion) referenceType: ${{ parameters.referenceType }} + isInternalBuild: ${{ parameters.isInternalBuild }} sqlServerArtifactsName: $(sqlServerArtifactsName) sqlServerPackageVersion: $(sqlServerPackageVersion) SNIVersion: ${{ parameters.SNIVersion }} @@ -220,6 +232,7 @@ stages: - build_sqlserver_package_stage - build_sqlclient_package_stage dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} loggingArtifactsName: $(loggingArtifactsName) loggingPackageVersion: $(loggingPackageVersion) mdsArtifactsName: $(mdsArtifactsName) @@ -251,6 +264,7 @@ stages: loggingPackageVersion: $(loggingPackageVersion) mdsArtifactsName: $(mdsArtifactsName) mdsPackageVersion: $(mdsPackageVersion) + isInternalBuild: ${{ parameters.isInternalBuild }} sqlServerArtifactsName: $(sqlServerArtifactsName) sqlServerPackageVersion: $(sqlServerPackageVersion) testJobTimeout: ${{ parameters.testJobTimeout }} diff --git a/eng/pipelines/dotnet-sqlclient-ci-package-reference-pipeline.yml b/eng/pipelines/dotnet-sqlclient-ci-package-reference-pipeline.yml index 98cac1bcdd..c510dc2c6b 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-package-reference-pipeline.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-package-reference-pipeline.yml @@ -174,3 +174,4 @@ extends: testJobTimeout: ${{ parameters.testJobTimeout }} testSets: ${{ parameters.testSets }} useManagedSNI: ${{ parameters.useManagedSNI }} + isInternalBuild: ${{ eq(variables['System.TeamProject'], 'ADO.Net') }} diff --git a/eng/pipelines/dotnet-sqlclient-ci-project-reference-pipeline.yml b/eng/pipelines/dotnet-sqlclient-ci-project-reference-pipeline.yml index 7068c9693c..29f2660f0f 100644 --- a/eng/pipelines/dotnet-sqlclient-ci-project-reference-pipeline.yml +++ b/eng/pipelines/dotnet-sqlclient-ci-project-reference-pipeline.yml @@ -174,3 +174,4 @@ extends: testJobTimeout: ${{ parameters.testJobTimeout }} testSets: ${{ parameters.testSets }} useManagedSNI: ${{ parameters.useManagedSNI }} + isInternalBuild: ${{ eq(variables['System.TeamProject'], 'ADO.Net') }} diff --git a/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml b/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml index d077aa2115..37b16769b4 100644 --- a/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml @@ -77,6 +77,11 @@ parameters: # Reference sibling packages as C# projects. - Project + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + jobs: - job: pack_abstractions_package_job @@ -119,6 +124,23 @@ jobs: - name: Configuration value: '' + # Build properties passed to dotnet pack. Composed from a base set plus + # optional suffixes for Package-mode dependencies and assembly signing. + - name: baseBuildProperties + value: AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};AbstractionsAssemblyFileVersion=${{ parameters.abstractionsAssemblyFileVersion }} + + # NOTE: We use compile-time ${{ if }} branches rather than concatenating + # separate variables (e.g. "$(base);$(optional);$(signing)") because + # when the optional variables are empty the semicolons remain, producing + # a trailing ";;" that MSBuild rejects with MSB1005. + - name: buildProperties + ${{ if and(eq(parameters.referenceType, 'Package'), eq(parameters.isInternalBuild, true)) }}: + value: $(baseBuildProperties);ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }};SigningKeyPath=$(driverKeyFile.secureFilePath) + ${{ elseif eq(parameters.referenceType, 'Package') }}: + value: $(baseBuildProperties);ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }} + ${{ else }}: + value: $(baseBuildProperties) + steps: # Emit environment variables if debug is enabled. @@ -140,32 +162,20 @@ jobs: parameters: debug: ${{ parameters.debug }} + # Download the assembly signing key for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + # Create the NuGet packages. - # - # When referenceType is Package, we must pass ReferenceType and the - # dependency version so that Directory.Packages.props applies version - # ranges to sibling package dependencies. - - ${{ if eq(parameters.referenceType, 'Package') }}: - - task: DotNetCoreCLI@2 - displayName: Create NuGet Package - inputs: - command: pack - packagesToPack: $(project) - configurationToPack: ${{ parameters.buildConfiguration }} - packDirectory: $(dotnetPackagesDir) - verbosityToPack: ${{ parameters.dotnetVerbosity }} - buildProperties: AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};AbstractionsAssemblyFileVersion=${{ parameters.abstractionsAssemblyFileVersion }};ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }} - - - ${{ else }}: - - task: DotNetCoreCLI@2 - displayName: Create NuGet Package - inputs: - command: pack - packagesToPack: $(project) - configurationToPack: ${{ parameters.buildConfiguration }} - packDirectory: $(dotnetPackagesDir) - verbosityToPack: ${{ parameters.dotnetVerbosity }} - buildProperties: AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};AbstractionsAssemblyFileVersion=${{ parameters.abstractionsAssemblyFileVersion }} + - task: DotNetCoreCLI@2 + displayName: Create NuGet Package + inputs: + command: pack + packagesToPack: $(project) + configurationToPack: ${{ parameters.buildConfiguration }} + packDirectory: $(dotnetPackagesDir) + verbosityToPack: ${{ parameters.dotnetVerbosity }} + buildProperties: $(buildProperties) # Publish the NuGet packages as a named pipeline artifact. - task: PublishPipelineArtifact@1 diff --git a/eng/pipelines/jobs/pack-azure-package-ci-job.yml b/eng/pipelines/jobs/pack-azure-package-ci-job.yml index 12567fec14..e1ddd7da76 100644 --- a/eng/pipelines/jobs/pack-azure-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-azure-package-ci-job.yml @@ -89,6 +89,11 @@ parameters: # Reference sibling packages as C# projects. - Project + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + jobs: - job: pack_azure_package_job @@ -131,6 +136,23 @@ jobs: - name: Configuration value: '' + # Build properties passed to dotnet pack. Composed from a base set plus + # optional suffixes for Package-mode dependencies and assembly signing. + - name: baseBuildProperties + value: AzurePackageVersion=${{ parameters.azurePackageVersion }};AzureAssemblyFileVersion=${{ parameters.azureAssemblyFileVersion }} + + # NOTE: We use compile-time ${{ if }} branches rather than concatenating + # separate variables (e.g. "$(base);$(optional);$(signing)") because + # when the optional variables are empty the semicolons remain, producing + # a trailing ";;" that MSBuild rejects with MSB1005. + - name: buildProperties + ${{ if and(eq(parameters.referenceType, 'Package'), eq(parameters.isInternalBuild, true)) }}: + value: $(baseBuildProperties);ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }};AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};SigningKeyPath=$(driverKeyFile.secureFilePath) + ${{ elseif eq(parameters.referenceType, 'Package') }}: + value: $(baseBuildProperties);ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }};AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }} + ${{ else }}: + value: $(baseBuildProperties) + steps: # Emit environment variables if debug is enabled. @@ -157,32 +179,20 @@ jobs: parameters: debug: ${{ parameters.debug }} + # Download the assembly signing key for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + # Create the NuGet packages. - # - # When referenceType is Package, we must pass ReferenceType and the - # dependency versions so that Directory.Packages.props applies version - # ranges to sibling package dependencies. - - ${{ if eq(parameters.referenceType, 'Package') }}: - - task: DotNetCoreCLI@2 - displayName: Create NuGet Package - inputs: - command: pack - packagesToPack: $(project) - configurationToPack: ${{ parameters.buildConfiguration }} - packDirectory: $(dotnetPackagesDir) - verbosityToPack: ${{ parameters.dotnetVerbosity }} - buildProperties: AzurePackageVersion=${{ parameters.azurePackageVersion }};AzureAssemblyFileVersion=${{ parameters.azureAssemblyFileVersion }};ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }};AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }} - - - ${{ else }}: - - task: DotNetCoreCLI@2 - displayName: Create NuGet Package - inputs: - command: pack - packagesToPack: $(project) - configurationToPack: ${{ parameters.buildConfiguration }} - packDirectory: $(dotnetPackagesDir) - verbosityToPack: ${{ parameters.dotnetVerbosity }} - buildProperties: AzurePackageVersion=${{ parameters.azurePackageVersion }};AzureAssemblyFileVersion=${{ parameters.azureAssemblyFileVersion }} + - task: DotNetCoreCLI@2 + displayName: Create NuGet Package + inputs: + command: pack + packagesToPack: $(project) + configurationToPack: ${{ parameters.buildConfiguration }} + packDirectory: $(dotnetPackagesDir) + verbosityToPack: ${{ parameters.dotnetVerbosity }} + buildProperties: $(buildProperties) # Publish the NuGet packages as a named pipeline artifact. - task: PublishPipelineArtifact@1 diff --git a/eng/pipelines/jobs/pack-logging-package-ci-job.yml b/eng/pipelines/jobs/pack-logging-package-ci-job.yml index f2a42699e0..5248bf0853 100644 --- a/eng/pipelines/jobs/pack-logging-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-logging-package-ci-job.yml @@ -53,6 +53,19 @@ parameters: - detailed - diagnostic + # The C# project reference type to use when building and packing the packages. + - name: referenceType + type: string + default: Project + values: + - Package + - Project + + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + jobs: - job: pack_logging_package_job @@ -86,6 +99,20 @@ jobs: - name: Configuration value: '' + # Build properties passed to dotnet pack. + - name: baseBuildProperties + value: LoggingPackageVersion=${{ parameters.loggingPackageVersion }};LoggingAssemblyFileVersion=${{ parameters.loggingAssemblyFileVersion }} + + # NOTE: We use compile-time ${{ if }} branches rather than concatenating + # separate variables (e.g. "$(base);$(signing)") because when the + # optional variable is empty the semicolons remain, producing a trailing + # ";;" that MSBuild rejects with MSB1005. + - name: buildProperties + ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + value: $(baseBuildProperties);SigningKeyPath=$(driverKeyFile.secureFilePath) + ${{ else }}: + value: $(baseBuildProperties) + steps: # Emit environment variables if debug is enabled. @@ -98,6 +125,10 @@ jobs: parameters: debug: ${{ parameters.debug }} + # Download the assembly signing key for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + # Create the NuGet packages. - task: DotNetCoreCLI@2 displayName: Create NuGet Package @@ -107,7 +138,7 @@ jobs: configurationToPack: ${{ parameters.buildConfiguration }} packDirectory: $(dotnetPackagesDir) verbosityToPack: ${{ parameters.dotnetVerbosity }} - buildProperties: LoggingPackageVersion=${{ parameters.loggingPackageVersion }};LoggingAssemblyFileVersion=${{ parameters.loggingAssemblyFileVersion }} + buildProperties: $(buildProperties) # Publish the NuGet packages as a named pipeline artifact. - task: PublishPipelineArtifact@1 diff --git a/eng/pipelines/jobs/pack-sqlserver-package-ci-job.yml b/eng/pipelines/jobs/pack-sqlserver-package-ci-job.yml index 6b19e8c154..8684d474ac 100644 --- a/eng/pipelines/jobs/pack-sqlserver-package-ci-job.yml +++ b/eng/pipelines/jobs/pack-sqlserver-package-ci-job.yml @@ -49,6 +49,19 @@ parameters: - detailed - diagnostic + # The C# project reference type to use when building and packing the packages. + - name: referenceType + type: string + default: Project + values: + - Package + - Project + + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + jobs: - job: pack_sqlserver_package_job @@ -82,6 +95,14 @@ jobs: - name: Configuration value: '' + # Build properties passed to dotnet pack. Composed from a base set plus + # optional signing key path for internal Package-mode builds. + - name: buildProperties + ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + value: SqlServerPackageVersion=${{ parameters.sqlServerPackageVersion }};SigningKeyPath=$(driverKeyFile.secureFilePath) + ${{ else }}: + value: SqlServerPackageVersion=${{ parameters.sqlServerPackageVersion }} + steps: # Emit environment variables if debug is enabled. @@ -94,6 +115,10 @@ jobs: parameters: debug: ${{ parameters.debug }} + # Download the assembly signing key for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + # Create the NuGet packages. - task: DotNetCoreCLI@2 displayName: Create NuGet Package @@ -103,7 +128,7 @@ jobs: configurationToPack: ${{ parameters.buildConfiguration }} packDirectory: $(dotnetPackagesDir) verbosityToPack: ${{ parameters.dotnetVerbosity }} - buildProperties: SqlServerPackageVersion=${{ parameters.sqlServerPackageVersion }} + buildProperties: $(buildProperties) - task: PublishPipelineArtifact@1 displayName: Publish Pipeline Artifact diff --git a/eng/pipelines/jobs/test-abstractions-package-ci-job.yml b/eng/pipelines/jobs/test-abstractions-package-ci-job.yml index 83366b52a9..ceb176274a 100644 --- a/eng/pipelines/jobs/test-abstractions-package-ci-job.yml +++ b/eng/pipelines/jobs/test-abstractions-package-ci-job.yml @@ -61,6 +61,20 @@ parameters: - name: poolName type: string + # True when building on the internal ADO.Net project. When set, assemblies + # are signed with the driver key and tests are signed with the test key. + - name: isInternalBuild + type: boolean + default: false + + # The C# project reference type to use when building. + - name: referenceType + type: string + default: Project + values: + - Package + - Project + # The pool VM image to use. - name: vmImage type: string @@ -89,11 +103,21 @@ jobs: value: src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj # dotnet CLI arguments for build/test/pack commands - - name: buildArguments + - name: dotnetBuildOpts value: >- -p:Configuration=${{ parameters.buildConfiguration }} --verbosity ${{ parameters.dotnetVerbosity }} + # Signing arguments — only set for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - name: signingArguments + value: >- + -p:SigningKeyPath=$(driverKeyFile.secureFilePath) + -p:TestSigningKeyPath=$(testKeyFile.secureFilePath) + - ${{ else }}: + - name: signingArguments + value: '' + # Explicitly unset the $PLATFORM environment variable that is set by the # 'ADO Build properties' Library in the ADO SqlClientDrivers public project. # This is defined with a non-standard Platform of 'AnyCPU', and will fail @@ -121,6 +145,13 @@ jobs: - pwsh: 'Get-ChildItem Env: | Sort-Object Name' displayName: '[Debug] Print Environment Variables' + # Download the assembly signing keys for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + parameters: + isTest: true + # Install the .NET SDK and Runtimes. - template: /eng/pipelines/common/steps/install-dotnet.yml@self parameters: @@ -136,7 +167,7 @@ jobs: inputs: command: build projects: $(project) - arguments: $(buildArguments) + arguments: $(dotnetBuildOpts) $(signingArguments) # Run the tests for each .NET runtime. - ${{ each runtime in parameters.netRuntimes }}: @@ -146,7 +177,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category != failing & category != flaky & category != interactive" @@ -157,7 +188,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category = flaky" @@ -170,7 +201,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category != failing & category != flaky & category != interactive" @@ -181,7 +212,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category = flaky" diff --git a/eng/pipelines/jobs/test-azure-package-ci-job.yml b/eng/pipelines/jobs/test-azure-package-ci-job.yml index eb9e36152a..3570d72114 100644 --- a/eng/pipelines/jobs/test-azure-package-ci-job.yml +++ b/eng/pipelines/jobs/test-azure-package-ci-job.yml @@ -69,6 +69,12 @@ parameters: - detailed - diagnostic + # True when building on the internal ADO.Net project. When set, assemblies + # are signed with the driver key and tests are signed with the test key. + - name: isInternalBuild + type: boolean + default: false + # The suffix to append to the job name. - name: jobNameSuffix type: string @@ -169,7 +175,7 @@ jobs: value: src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj # dotnet CLI arguments for build/test/pack commands. - - name: buildArguments + - name: dotnetBuildOpts value: >- -p:Configuration=${{ parameters.buildConfiguration }} --verbosity ${{ parameters.dotnetVerbosity }} @@ -179,6 +185,16 @@ jobs: -p:SqlClientPackageVersion=${{ parameters.mdsPackageVersion }} -p:SqlServerPackageVersion=${{ parameters.sqlServerPackageVersion }} + # Signing arguments — only set for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - name: signingArguments + value: >- + -p:SigningKeyPath=$(driverKeyFile.secureFilePath) + -p:TestSigningKeyPath=$(testKeyFile.secureFilePath) + - ${{ else }}: + - name: signingArguments + value: '' + # Explicitly unset the $PLATFORM environment variable that is set by the # 'ADO Build properties' Library in the ADO SqlClientDrivers public # project. This is defined with a non-standard Platform of 'AnyCPU', and @@ -206,6 +222,13 @@ jobs: - pwsh: 'Get-ChildItem Env: | Sort-Object Name' displayName: '[Debug] Print Environment Variables' + # Download the assembly signing keys for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + parameters: + isTest: true + # We have a few extra steps for Package reference builds. - ${{ if eq(parameters.referenceType, 'Package') }}: @@ -289,7 +312,7 @@ jobs: inputs: command: build projects: $(project) - arguments: $(buildArguments) + arguments: $(dotnetBuildOpts) $(signingArguments) # List the DLLs in the output directory for debugging purposes. - ${{ if eq(parameters.debug, true) }}: @@ -324,7 +347,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category != failing & category != flaky & category != interactive" @@ -342,7 +365,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category = flaky" @@ -362,7 +385,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category != failing & category != flaky & category != interactive" @@ -380,7 +403,7 @@ jobs: command: test projects: $(project) arguments: >- - $(buildArguments) + $(dotnetBuildOpts) --no-build -f ${{ runtime }} --filter "category = flaky" diff --git a/eng/pipelines/jobs/test-logging-package-ci-job.yml b/eng/pipelines/jobs/test-logging-package-ci-job.yml new file mode 100644 index 0000000000..fde3e44c7e --- /dev/null +++ b/eng/pipelines/jobs/test-logging-package-ci-job.yml @@ -0,0 +1,218 @@ +################################################################################ +# 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 job builds the Logging package and runs its tests for a set of .NET +# runtimes. +# +# This template defines a job named +# 'test_logging_package_job_' that can be depended on by +# downstream jobs. + +parameters: + + # The type of build to test (Release or Debug) + - name: buildConfiguration + type: string + values: + - Release + - Debug + + # True to emit debug information and steps. + - name: debug + type: boolean + default: false + + # The prefix to prepend to the job's display name: + # + # [] Test Logging Package + # + - name: displayNamePrefix + type: string + + # The verbosity level for the dotnet CLI commands. + - name: dotnetVerbosity + type: string + default: normal + values: + - quiet + - minimal + - normal + - detailed + - diagnostic + + # True when building on the internal ADO.Net project. When set, assemblies + # are signed with the driver key and tests are signed with the test key. + - name: isInternalBuild + type: boolean + default: false + + # The suffix to append to the job name. + - name: jobNameSuffix + type: string + + # The list of .NET Framework runtimes to test against. + - name: netFrameworkRuntimes + type: object + default: [] + + # The list of .NET runtimes to test against. + - name: netRuntimes + type: object + default: [] + + # The name of the Azure Pipelines pool to use. + - name: poolName + type: string + + # The pool VM image to use. + - name: vmImage + type: string + + # The C# project reference type to use when building. + - name: referenceType + type: string + default: Project + values: + - Package + - Project + +jobs: + + - job: test_logging_package_job_${{ parameters.jobNameSuffix }} + displayName: '[${{ parameters.displayNamePrefix }}] Test Logging Package' + pool: + name: ${{ parameters.poolName }} + + # Images provided by Azure Pipelines must be selected using 'vmImage'. + ${{ if eq(parameters.poolName, 'Azure Pipelines') }}: + vmImage: ${{ parameters.vmImage }} + # Images provided by 1ES must be selected using a demand. + ${{ else }}: + demands: + - imageOverride -equals ${{ parameters.vmImage }} + + variables: + + # The Logging test project file to use for all dotnet CLI commands. + # + # Building this project implicitly builds the Logging project. + - name: project + value: src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj + + # dotnet CLI arguments for build/test/pack commands + - name: dotnetBuildOpts + value: >- + -p:Configuration=${{ parameters.buildConfiguration }} + --verbosity ${{ parameters.dotnetVerbosity }} + + # Signing arguments — only set for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - name: signingArguments + value: >- + -p:SigningKeyPath=$(driverKeyFile.secureFilePath) + -p:TestSigningKeyPath=$(testKeyFile.secureFilePath) + - ${{ else }}: + - name: signingArguments + value: '' + + # Explicitly unset the $PLATFORM environment variable that is set by the + # 'ADO Build properties' Library in the ADO SqlClientDrivers public project. + # This is defined with a non-standard Platform of 'AnyCPU', and will fail + # the builds if left defined. + # + # Note that Azure Pipelines will inject this variable as PLATFORM into the + # environment of all tasks in this job. + # + # See: + # https://learn.microsoft.com/en-us/azure/devops/pipelines/process/variables?view=azure-devops&tabs=yaml%2Cbatch + # + - name: Platform + value: '' + + # Do the same for $CONFIGURATION since we explicitly set it using our + # 'buildConfiguration' parameter, and we don't want the environment to + # override us. + - name: Configuration + value: '' + + steps: + + # Emit environment variables if debug is enabled. + - ${{ if eq(parameters.debug, true) }}: + - pwsh: 'Get-ChildItem Env: | Sort-Object Name' + displayName: '[Debug] Print Environment Variables' + + # Download the assembly signing keys for internal Package-mode builds. + - ${{ if and(eq(parameters.isInternalBuild, true), ne(parameters.referenceType, 'Project')) }}: + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self + parameters: + isTest: true + + # Install the .NET SDK and Runtimes. + - template: /eng/pipelines/common/steps/install-dotnet.yml@self + parameters: + debug: ${{ parameters.debug }} + runtimes: [8.x, 9.x] + + # The Windows agent images include a suitable .NET Framework runtime, so + # we don't have to install one explicitly. + + # Build the project. + - task: DotNetCoreCLI@2 + displayName: Build Project + inputs: + command: build + projects: $(project) + arguments: $(dotnetBuildOpts) $(signingArguments) + + # Run the tests for each .NET runtime. + - ${{ each runtime in parameters.netRuntimes }}: + - task: DotNetCoreCLI@2 + displayName: Test [${{ runtime }}] + inputs: + command: test + projects: $(project) + arguments: >- + $(dotnetBuildOpts) + --no-build + -f ${{ runtime }} + --filter "category != failing & category != flaky & category != interactive" + + - task: DotNetCoreCLI@2 + displayName: Test Flaky [${{ runtime }}] + inputs: + command: test + projects: $(project) + arguments: >- + $(dotnetBuildOpts) + --no-build + -f ${{ runtime }} + --filter "category = flaky" + + # Run the tests for each .NET Framework runtime. + - ${{ each runtime in parameters.netFrameworkRuntimes }}: + - task: DotNetCoreCLI@2 + displayName: Test [${{ runtime }}] + inputs: + command: test + projects: $(project) + arguments: >- + $(dotnetBuildOpts) + --no-build + -f ${{ runtime }} + --filter "category != failing & category != flaky & category != interactive" + + - task: DotNetCoreCLI@2 + displayName: Test Flaky [${{ runtime }}] + inputs: + command: test + projects: $(project) + arguments: >- + $(dotnetBuildOpts) + --no-build + -f ${{ runtime }} + --filter "category = flaky" diff --git a/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml b/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml index afa5aa5918..0769e2093c 100644 --- a/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml +++ b/eng/pipelines/onebranch/jobs/validate-signed-package-job.yml @@ -157,8 +157,8 @@ jobs: $nugetPackageInstallPath = "${{ variables.nugetPackageInstallPath }}" echo "nugetPackageInstallPath= $nugetPackageInstallPath" - # Verify strong name signing ##################################### - echo "> 1. Verifying strong name signing of DLLs ..." + # Verify strong-name signing ################################### + echo "> 1. Verifying strong-name signing of DLLs ..." # @TODO: This path seems brittle to VS upgrades, can we make it more flexible? $snPath = "C:\Program Files (x86)\Microsoft SDKs\Windows\*\bin\NETFX 4.8.1 Tools\sn.exe" diff --git a/eng/pipelines/onebranch/steps/build-buildproj-step.yml b/eng/pipelines/onebranch/steps/build-buildproj-step.yml index 2a5730c848..dcb66f6f15 100644 --- a/eng/pipelines/onebranch/steps/build-buildproj-step.yml +++ b/eng/pipelines/onebranch/steps/build-buildproj-step.yml @@ -7,7 +7,7 @@ # This collection of steps to build a project via the build.proj. This will execute the "Build*" # target in build.proj, where * is the packageShortName provided in the parameters. # -# Note: This differs from the pr/ci build-buildproj-step.yml in that it always strong-name signs +# Note: This differs from the pr/ci build-buildproj-step.yml in that it always signs # the assemblies, it only builds in package reference mode, and as such allows for version # parameters to be provided. @@ -44,12 +44,8 @@ parameters: type: string steps: - # Download the strong name signing key from secure file storage - - task: DownloadSecureFile@1 - displayName: 'Download Signing Key' - inputs: - secureFile: 'netfxKeypair.snk' - name: keyFile + # Download the assembly signing key from secure file storage. + - template: /eng/pipelines/common/steps/download-assembly-signing-key.yml@self - task: DotNetCoreCLI@2 displayName: 'build.proj - Build${{ parameters.packageShortName }}' @@ -61,7 +57,7 @@ steps: -p:Configuration=${{ parameters.buildConfiguration }} -p:ReferenceType=Package -p:SkipDependencyPack=true - -p:SigningKeyPath="$(keyFile.secureFilePath)" + -p:SigningKeyPath="$(driverKeyFile.secureFilePath)" -p:BuildNumber="$(Build.BuildNumber)" -p:PackageVersion${{ parameters.packageShortName }}="${{ parameters.packageVersion }}" ${{ parameters.dependencyArguments }} diff --git a/eng/pipelines/stages/build-abstractions-package-ci-stage.yml b/eng/pipelines/stages/build-abstractions-package-ci-stage.yml index 8579b79caf..82a4efd6a4 100644 --- a/eng/pipelines/stages/build-abstractions-package-ci-stage.yml +++ b/eng/pipelines/stages/build-abstractions-package-ci-stage.yml @@ -91,6 +91,11 @@ parameters: # Reference sibling packages as C# projects. - Project + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + stages: - stage: build_abstractions_package_stage @@ -112,10 +117,12 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: Linux dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: linux netFrameworkRuntimes: [] netRuntimes: [net8.0, net9.0, net10.0] poolName: Azure Pipelines + referenceType: ${{ parameters.referenceType }} vmImage: ubuntu-latest # ------------------------------------------------------------------------ @@ -127,10 +134,12 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: Win dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: windows netFrameworkRuntimes: [net462] netRuntimes: [net8.0, net9.0, net10.0] poolName: Azure Pipelines + referenceType: ${{ parameters.referenceType }} vmImage: windows-latest # ------------------------------------------------------------------------ @@ -142,10 +151,12 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: macOS dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: macos netFrameworkRuntimes: [] netRuntimes: [net8.0, net9.0, net10.0] poolName: Azure Pipelines + referenceType: ${{ parameters.referenceType }} vmImage: macos-latest # ------------------------------------------------------------------------ @@ -168,3 +179,4 @@ stages: loggingArtifactsName: ${{ parameters.loggingArtifactsName }} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} referenceType: ${{ parameters.referenceType }} + isInternalBuild: ${{ parameters.isInternalBuild }} diff --git a/eng/pipelines/stages/build-azure-package-ci-stage.yml b/eng/pipelines/stages/build-azure-package-ci-stage.yml index b3cf9073d5..396314125c 100644 --- a/eng/pipelines/stages/build-azure-package-ci-stage.yml +++ b/eng/pipelines/stages/build-azure-package-ci-stage.yml @@ -152,6 +152,11 @@ parameters: # Reference sibling packages as C# projects. - Project + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + stages: - stage: build_azure_package_stage @@ -180,6 +185,7 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: Linux dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: linux loggingArtifactsName: ${{ parameters.loggingArtifactsName }} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} @@ -202,6 +208,7 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: Linux Integration dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: linux_integration loggingArtifactsName: ${{ parameters.loggingArtifactsName }} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} @@ -233,6 +240,7 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: Win dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: windows loggingArtifactsName: ${{ parameters.loggingArtifactsName }} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} @@ -255,6 +263,7 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: Win Integration dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: windows_integration loggingArtifactsName: ${{ parameters.loggingArtifactsName }} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} @@ -295,6 +304,7 @@ stages: debug: ${{ parameters.debug }} displayNamePrefix: macOS dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} jobNameSuffix: macos loggingArtifactsName: ${{ parameters.loggingArtifactsName }} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} @@ -331,6 +341,7 @@ stages: - test_azure_package_job_windows_integration - test_azure_package_job_macos dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} loggingArtifactsName: ${{ parameters.loggingArtifactsName }} loggingPackageVersion: ${{ parameters.loggingPackageVersion }} referenceType: ${{ parameters.referenceType }} diff --git a/eng/pipelines/stages/build-logging-package-ci-stage.yml b/eng/pipelines/stages/build-logging-package-ci-stage.yml index 6b5f22feeb..4a0ee11a8f 100644 --- a/eng/pipelines/stages/build-logging-package-ci-stage.yml +++ b/eng/pipelines/stages/build-logging-package-ci-stage.yml @@ -67,6 +67,19 @@ parameters: - detailed - diagnostic + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + + # The C# project reference type to use when building and packing the packages. + - name: referenceType + type: string + default: Project + values: + - Package + - Project + stages: - stage: build_logging_package_stage @@ -79,11 +92,59 @@ stages: jobs: + # ------------------------------------------------------------------------ + # Build and test on Linux. + + - template: /eng/pipelines/jobs/test-logging-package-ci-job.yml@self + parameters: + buildConfiguration: ${{ parameters.buildConfiguration }} + debug: ${{ parameters.debug }} + displayNamePrefix: Linux + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} + jobNameSuffix: linux + netFrameworkRuntimes: [] + netRuntimes: [net8.0, net9.0, net10.0] + poolName: Azure Pipelines + referenceType: ${{ parameters.referenceType }} + vmImage: ubuntu-latest + + # ------------------------------------------------------------------------ + # Build and test on Windows. + + - template: /eng/pipelines/jobs/test-logging-package-ci-job.yml@self + parameters: + buildConfiguration: ${{ parameters.buildConfiguration }} + debug: ${{ parameters.debug }} + displayNamePrefix: Win + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} + jobNameSuffix: windows + netFrameworkRuntimes: [net462] + netRuntimes: [net8.0, net9.0, net10.0] + poolName: Azure Pipelines + referenceType: ${{ parameters.referenceType }} + vmImage: windows-latest + + # ------------------------------------------------------------------------ + # Build and test on macOS. + + - template: /eng/pipelines/jobs/test-logging-package-ci-job.yml@self + parameters: + buildConfiguration: ${{ parameters.buildConfiguration }} + debug: ${{ parameters.debug }} + displayNamePrefix: macOS + dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} + jobNameSuffix: macos + netFrameworkRuntimes: [] + netRuntimes: [net8.0, net9.0, net10.0] + poolName: Azure Pipelines + referenceType: ${{ parameters.referenceType }} + vmImage: macos-latest + + # ------------------------------------------------------------------------ # Create and publish the NuGet package. - # Note: No test jobs because the Logging project does not have a test - # project yet. When a test project is added, test jobs should be added - # here (mirroring the Abstractions stage pattern) and the pack job should - # depend on them. - template: /eng/pipelines/jobs/pack-logging-package-ci-job.yml@self parameters: @@ -93,3 +154,5 @@ stages: buildConfiguration: ${{ parameters.buildConfiguration }} debug: ${{ parameters.debug }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} + referenceType: ${{ parameters.referenceType }} diff --git a/eng/pipelines/stages/build-sqlclient-package-ci-stage.yml b/eng/pipelines/stages/build-sqlclient-package-ci-stage.yml index 858f1c8500..aa62f2122e 100644 --- a/eng/pipelines/stages/build-sqlclient-package-ci-stage.yml +++ b/eng/pipelines/stages/build-sqlclient-package-ci-stage.yml @@ -85,6 +85,11 @@ parameters: type: string default: '' + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + stages: - stage: build_sqlclient_package_stage @@ -109,6 +114,7 @@ stages: akvPackageVersion: ${{ parameters.akvPackageVersion }} sqlServerArtifactsName: ${{ parameters.sqlServerArtifactsName }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} + isInternalBuild: ${{ parameters.isInternalBuild }} ${{ if ne(parameters.SNIVersion, '') }}: prebuildSteps: - template: /eng/pipelines/common/templates/steps/override-sni-version.yml@self diff --git a/eng/pipelines/stages/build-sqlserver-package-ci-stage.yml b/eng/pipelines/stages/build-sqlserver-package-ci-stage.yml index 1711725373..e08fbba531 100644 --- a/eng/pipelines/stages/build-sqlserver-package-ci-stage.yml +++ b/eng/pipelines/stages/build-sqlserver-package-ci-stage.yml @@ -63,6 +63,19 @@ parameters: - detailed - diagnostic + # True when building on the internal ADO.Net project. + - name: isInternalBuild + type: boolean + default: false + + # The C# project reference type to use when building and packing the packages. + - name: referenceType + type: string + default: Project + values: + - Package + - Project + stages: - stage: build_sqlserver_package_stage @@ -81,3 +94,5 @@ stages: sqlServerArtifactsName: ${{ parameters.sqlServerArtifactsName }} sqlServerPackageVersion: ${{ parameters.sqlServerPackageVersion }} dotnetVerbosity: ${{ parameters.dotnetVerbosity }} + isInternalBuild: ${{ parameters.isInternalBuild }} + referenceType: ${{ parameters.referenceType }} diff --git a/src/Directory.Build.props b/src/Directory.Build.props index b3e0663fd3..7982e8f785 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -106,15 +106,15 @@ low - + - + true $(SigningKeyPath) - $(DefineConstants);STRONG_NAME_SIGNING + $(DefineConstants);ASSEMBLY_SIGNING diff --git a/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj b/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj index 203aabd1f5..9604565837 100644 --- a/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj +++ b/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider/src/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.csproj @@ -22,7 +22,7 @@ $(AkvProviderPackageVersion) - + diff --git a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj index 0a9d29aa1e..9eac7f6ecf 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/Abstractions.csproj @@ -32,12 +32,24 @@ $(AbstractionsPackageVersion) - + + + + + + + + $(RepoRoot)artifacts/ @@ -79,6 +91,11 @@ Condition="'$(ReferenceType)' == 'Package'" /> + + + + + diff --git a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs index e0adf34e49..dd7cc33e6e 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs +++ b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/src/SqlAuthenticationProvider.Internal.cs @@ -40,30 +40,75 @@ static Internal() { const string assemblyName = "Microsoft.Data.SqlClient"; - // If the MDS package is present, load its + // If the SqlClient assembly is present, load its // SqlAuthenticationProviderManager class and get/set methods. try { - // Try to load the MDS assembly. + // Try to load the SqlClient assembly. + + #if ASSEMBLY_SIGNING + + // The expected public key token of the SqlClient assembly, used to avoid invoking + // APIs from imposter assemblies. This is the public key token of the assembly + // signing key used for all of our driver assemblies. + byte[] expectedPublicKeyToken = + [ 0x23, 0xec, 0x7f, 0xc2, 0xd6, 0xea, 0xa4, 0xa5 ]; + + // When assembly signing is enabled, build a fully-qualified AssemblyName that + // includes the expected public key token. + Log($"Attempting to load SqlClient assembly={assemblyName} with " + + "expected public key token=" + + BitConverter.ToString(expectedPublicKeyToken).Replace("-", "")); + + var qualifiedName = new AssemblyName(assemblyName); + qualifiedName.SetPublicKeyToken(expectedPublicKeyToken); + + // The .NET Framework runtime enforces the token during binding, causing Load() to + // throw if it doesn't match. The .NET (Core) runtime ignores the token, so we + // verify it ourselves below. + var assembly = Assembly.Load(qualifiedName); + + // Defense-in-depth: verify the public key token after loading. This is necessary + // on .NET Core where the runtime does not enforce the token. It is harmless on .NET + // Framework. + if (assembly is not null) + { + byte[]? actualToken = assembly.GetName().GetPublicKeyToken(); + + if (actualToken is null || + !actualToken.AsSpan().SequenceEqual(expectedPublicKeyToken)) + { + Log($"SqlClient assembly={assembly.GetName()} has an " + + "unexpected public key token; " + + "Get/SetProvider() will not function"); + return; + } + } + + #else + + // Assembly signing is disabled, so we cannot verify the public key token. + Log($"Loading SqlClient assembly={assemblyName} without strong-name identity " + + "verification; ensure this assembly is from a trusted source"); + var assembly = Assembly.Load(assemblyName); + #endif + if (assembly is null) { - Log($"MDS assembly={assemblyName} not found; " + + Log($"SqlClient assembly={assemblyName} not found; " + "Get/SetProvider() will not function"); return; } - // TODO(https://sqlclientdrivers.visualstudio.com/ADO.Net/_workitems/edit/39845): - // Verify the assembly is signed by us? - // Look for the manager class. const string className = "Microsoft.Data.SqlClient.SqlAuthenticationProviderManager"; var manager = assembly.GetType(className); if (manager is null) { - Log($"MDS auth manager manager class={className} not found; " + + Log($"SqlClient auth manager class={className} not found; " + "Get/SetProvider() will not function"); return; } @@ -75,7 +120,7 @@ static Internal() if (_getProvider is null) { - Log($"MDS GetProvider() method not found; " + + Log($"SqlClient GetProvider() method not found; " + "GetProvider() will not function"); } @@ -85,7 +130,7 @@ static Internal() if (_setProvider is null) { - Log($"MDS SetProvider() method not found; " + + Log($"SqlClient SetProvider() method not found; " + "SetProvider() will not function"); } } @@ -97,7 +142,7 @@ or BadImageFormatException or FileLoadException or FileNotFoundException) { - Log($"MDS assembly={assemblyName} not found or not usable; " + + Log($"SqlClient assembly={assemblyName} not found or not usable; " + $"Get/SetProvider() will not function: {ex} "); } // Any other exceptions are fatal. diff --git a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj index 427a7aaf9f..7ab085560e 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Abstractions/test/Abstractions.Test.csproj @@ -2,12 +2,26 @@ Microsoft.Data.SqlClient.Extensions.Abstractions.Test - net462;net8.0;net9.0;net10.0 + net8.0;net9.0;net10.0 + + + $(TargetFrameworks);net462 false true + + + + true + $(TestSigningKeyPath) + + enable diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj index dddf5673f9..02d3733ffb 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/src/Azure.csproj @@ -32,12 +32,24 @@ $(AzurePackageVersion) - + + + + + + + + $(RepoRoot)artifacts/ diff --git a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj index 1c020c2ae4..818a223f21 100644 --- a/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj +++ b/src/Microsoft.Data.SqlClient.Extensions/Azure/test/Azure.Test.csproj @@ -8,6 +8,13 @@ true + + + + true + $(TestSigningKeyPath) + + net8.0;net9.0;net10.0 diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj b/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj index d1c3e0fc5c..bc7502d517 100644 --- a/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/src/Logging.csproj @@ -34,12 +34,24 @@ $(LoggingPackageVersion) - + + + + + + + + $(RepoRoot)artifacts/ diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/test/Directory.Packages.props b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Directory.Packages.props new file mode 100644 index 0000000000..f3593ec1ba --- /dev/null +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Directory.Packages.props @@ -0,0 +1,10 @@ + + + + diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj new file mode 100644 index 0000000000..be3ca85785 --- /dev/null +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/test/Logging.Test.csproj @@ -0,0 +1,57 @@ + + + + Microsoft.Data.SqlClient.Internal.Logging.Test + net8.0;net9.0;net10.0 + + + $(TargetFrameworks);net462 + + false + true + + + + + + true + $(TestSigningKeyPath) + + + + + enable + enable + + + + + + + + + + + PreserveNewest + xunit.runner.json + + + + + + + + + + + + + + + + + + diff --git a/src/Microsoft.Data.SqlClient.Internal/Logging/test/SqlClientEventSourceTest.cs b/src/Microsoft.Data.SqlClient.Internal/Logging/test/SqlClientEventSourceTest.cs new file mode 100644 index 0000000000..d46896672f --- /dev/null +++ b/src/Microsoft.Data.SqlClient.Internal/Logging/test/SqlClientEventSourceTest.cs @@ -0,0 +1,20 @@ +// 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. + +namespace Microsoft.Data.SqlClient.Internal.Logging.Test; + +public class SqlClientEventSourceTest +{ + [Fact] + public void SqlClientEventSource_Log_IsNotNull() + { + Assert.NotNull(SqlClientEventSource.Log); + } + + [Fact] + public void SqlClientEventSource_Log_IsSingleton() + { + Assert.Same(SqlClientEventSource.Log, SqlClientEventSource.Log); + } +} diff --git a/src/Microsoft.Data.SqlClient.slnx b/src/Microsoft.Data.SqlClient.slnx index a578a82db6..d6a615e39f 100644 --- a/src/Microsoft.Data.SqlClient.slnx +++ b/src/Microsoft.Data.SqlClient.slnx @@ -146,6 +146,7 @@ + diff --git a/src/Microsoft.Data.SqlClient/notsupported/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/notsupported/Microsoft.Data.SqlClient.csproj index a9474613e6..d1c65d6add 100644 --- a/src/Microsoft.Data.SqlClient/notsupported/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/notsupported/Microsoft.Data.SqlClient.csproj @@ -83,7 +83,7 @@ $(SqlClientPackageVersion) - + diff --git a/src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.csproj index 43aca3f1c1..7976d967fb 100644 --- a/src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/ref/Microsoft.Data.SqlClient.csproj @@ -28,7 +28,7 @@ - + diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj index 06eaf9e914..71e9c80215 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj +++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj @@ -60,7 +60,7 @@ $(SqlClientPackageVersion) - + diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs index 653063b68e..e73a533245 100644 --- a/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs +++ b/src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlAuthenticationProviderManager.cs @@ -61,9 +61,9 @@ static SqlAuthenticationProviderManager() try { // Try to load our Azure extension. - #if STRONG_NAME_SIGNING + #if ASSEMBLY_SIGNING - // When strong-name signing is enabled, build a fully-qualified AssemblyName + // When assembly signing is enabled, build a fully-qualified AssemblyName // that includes the expected public key token. SqlClientEventSource.Log.TryTraceEvent( @@ -109,7 +109,7 @@ static SqlAuthenticationProviderManager() SqlClientEventSource.Log.TryTraceEvent( nameof(SqlAuthenticationProviderManager) + $": Attempting to load Azure extension assembly={azureAssemblyName} without " + - "strong name verification; ensure this assembly is from a trusted source"); + "strong-name identity verification; ensure this assembly is from a trusted source"); var assembly = Assembly.Load(azureAssemblyName); diff --git a/src/Microsoft.Data.SqlClient/tests/Common/Microsoft.Data.SqlClient.TestCommon.csproj b/src/Microsoft.Data.SqlClient/tests/Common/Microsoft.Data.SqlClient.TestCommon.csproj index 67c5250748..aac951b190 100644 --- a/src/Microsoft.Data.SqlClient/tests/Common/Microsoft.Data.SqlClient.TestCommon.csproj +++ b/src/Microsoft.Data.SqlClient/tests/Common/Microsoft.Data.SqlClient.TestCommon.csproj @@ -14,7 +14,7 @@ false - + true diff --git a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs index b051f2cc26..6c31e23bd3 100644 --- a/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/FunctionalTests/SqlDataRecordTest.cs @@ -334,7 +334,7 @@ public void GetChar_ThrowsNotSupported() [Theory] #if NETFRAMEWORK - [Trait("Category", "signed")] // Requires strong-name signed Microsoft.SqlServer.Server + [Trait("Category", "signed")] // Requires a signed Microsoft.SqlServer.Server assembly #endif [MemberData( nameof(GetUdtTypeTestData.Get), diff --git a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs index 712d1ec2c6..911f2fbc58 100644 --- a/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs +++ b/src/Microsoft.Data.SqlClient/tests/ManualTests/SQL/UdtTest/SqlServerTypesTest.cs @@ -37,7 +37,7 @@ public static class SqlServerTypesTest // Synapse: Parse error at line: 1, column: 48: Incorrect syntax near 'hierarchyid'. [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] #if NETFRAMEWORK - [Trait("Category", "signed")] // Requires strong-name signed Microsoft.SqlServer.Server + [Trait("Category", "signed")] // Requires a signed Microsoft.SqlServer.Server assembly #endif public static void GetSchemaTableTest() { @@ -66,7 +66,7 @@ public static void GetSchemaTableTest() // Synapse: Parse error at line: 1, column: 48: Incorrect syntax near 'hierarchyid'. [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] #if NETFRAMEWORK - [Trait("Category", "signed")] // Requires strong-name signed Microsoft.SqlServer.Server + [Trait("Category", "signed")] // Requires a signed Microsoft.SqlServer.Server assembly #endif public static void GetValueTest() { @@ -227,7 +227,7 @@ void ActAndAssert(int index, string expectedHexString) // Synapse: Parse error at line: 1, column: 41: Incorrect syntax near 'hierarchyid'. [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] #if NETFRAMEWORK - [Trait("Category", "signed")] // Requires strong-name signed Microsoft.SqlServer.Server + [Trait("Category", "signed")] // Requires a signed Microsoft.SqlServer.Server assembly #endif public static void TestUdtSchemaMetadata() { @@ -384,7 +384,7 @@ private static string GetUdtName(Type udtClrType) // Synapse: Parse error at line: 1, column: 8: Incorrect syntax near 'geometry'. [ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.AreConnStringsSetup), nameof(DataTestUtility.IsNotAzureSynapse))] #if NETFRAMEWORK - [Trait("Category", "signed")] // Requires strong-name signed Microsoft.SqlServer.Server + [Trait("Category", "signed")] // Requires a signed Microsoft.SqlServer.Server assembly #endif public static void TestSqlServerTypesInsertAndRead() { diff --git a/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft.Data.SqlClient.UnitTests.csproj b/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft.Data.SqlClient.UnitTests.csproj index e09e49c967..cd95155822 100644 --- a/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft.Data.SqlClient.UnitTests.csproj +++ b/src/Microsoft.Data.SqlClient/tests/UnitTests/Microsoft.Data.SqlClient.UnitTests.csproj @@ -36,7 +36,7 @@ - + true diff --git a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj index 05444fd022..3d4f6c41d7 100644 --- a/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj +++ b/src/Microsoft.Data.SqlClient/tests/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj @@ -3,7 +3,7 @@ netstandard2.0 - + true diff --git a/src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj b/src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj index a995fa13b9..6769c42328 100644 --- a/src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj +++ b/src/Microsoft.SqlServer.Server/Microsoft.SqlServer.Server.csproj @@ -16,7 +16,7 @@ $(SqlServerPackageVersion) - +