Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 7 additions & 3 deletions .github/instructions/onebranch-pipeline-design.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ When `isPreview` is true, pipeline resolves `effective*Version` variables to pre

- Variable chain: pipeline YAML → `variables/onebranch-variables.yml` → `variables/common-variables.yml`
- All package versions (GA, preview, assembly file) centralized in `variables/common-variables.yml`
- `effective*Version` pipeline variables map to selected version set based on `isPreview`
- The `compute_versions` stage reads canonical versions from MSBuild and publishes effective package,
file-build, and APIScan registration versions for downstream stages
- Artifact name variables defined in `variables/onebranch-variables.yml` following `drop_<stageName>_<jobName>` pattern
- `assemblyBuildNumber` derived from first segment of `Build.BuildNumber` only (16-bit limit)
- When adding a new package, add GA version, preview version, and assembly file version entries
Expand All @@ -128,8 +129,11 @@ Variable groups:
## SDL and Compliance

- TSA: enabled only in official pipeline; disabled in non-official to avoid spurious alerts
- ApiScan: enabled in both; currently `break: false` pending package registration
- Each build job sets `ob_sdl_apiscan_softwareFolder` to `$(JOB_OUTPUT)/assemblies` and `ob_sdl_apiscan_symbolsFolder` to `$(JOB_OUTPUT)/symbols`
- ApiScan: enabled in both; `break` follows the `breakOnSdlError` parameter
- Each package is registered with APIScan under its own name/version pair, so the `globalSdl.apiscan` blocks deliberately omit `softwareName`/`versionNumber`. `build-buildproj-job.yml` is the single place they are set, via `ob_sdl_apiscan_softwareName` (the package's `packageFullName`) and `ob_sdl_apiscan_versionNumber` (the `apiScanSoftwareVersion` parameter)
- `compute-versions.ps1` derives APIScan registration versions as major.minor from the effective canonical package versions and publishes them as stage outputs. A package name/version pair must still be registered with APIScan before releasing a new major.minor. Consume these as runtime `$(...)` references so values such as `1.0` remain strings rather than being coerced to numbers by template expressions
- Jobs that produce no assemblies (symbol publishing, signed-package validation, version computation) set `ob_sdl_apiscan_enabled: false` rather than reporting a name/version
- Each build job also sets `ob_sdl_apiscan_softwareFolder` and `ob_sdl_apiscan_symbolsFolder` to its per-package `apiScan/<package>/dlls` and `apiScan/<package>/pdbs` paths
- CodeQL, SBOM, Policheck (`break: true`): enabled in both pipelines
- asyncSdl `enabled: false` in both; individual sub-tools (CredScan, BinSkim, Armory, Roslyn) configured underneath
- Policheck exclusions: `$(REPO_ROOT)\.config\PolicheckExclusions.xml`
Expand Down
12 changes: 11 additions & 1 deletion eng/pipelines/onebranch/jobs/build-buildproj-job.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ parameters:
- name: apiScanPdbPath
type: string

# The APIScan registration version for the package being built. This is the major.minor value
# derived from the canonical package version by the compute_versions stage. The package's
# name/version pair must already be registered with APIScan before the build runs.
- name: apiScanSoftwareVersion
type: string

# True to enable ESRP malware scanning and code signing steps, which should not be run on
# non-official pipelines as they access production resources. If true, Signing* parameters must
# be provided.
Expand Down Expand Up @@ -112,9 +118,13 @@ jobs:

ob_outputDirectory: '$(JOB_OUTPUT)'

# APIScan per-job configuration for the DLL and PDB folders.
# APIScan per-job configuration. This job template is the single place where the APIScan
# software name and version are set; the pipelines' globalSdl blocks deliberately leave them
# unset so that every scan is attributed to the package it actually covers.
ob_sdl_apiscan_softwareFolder: ${{ parameters.apiScanDllPath }}
ob_sdl_apiscan_symbolsFolder: ${{ parameters.apiScanPdbPath }}
ob_sdl_apiscan_softwareName: ${{ parameters.packageFullName }}
ob_sdl_apiscan_versionNumber: ${{ parameters.apiScanSoftwareVersion }}

steps:
- template: /eng/pipelines/onebranch/steps/script-output-environment-variables-step.yml@self
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ jobs:

variables: # More settings at https://aka.ms/obpipelines/yaml/jobs

# This job installs and inspects an already-built package rather than producing assemblies,
# so it has no APIScan software name/version to report. The build jobs scan those assemblies.
- name: ob_sdl_apiscan_enabled
value: false

# Path within the downloaded artifact where NuGet packages are located.
- name: artifactPath
value: '$(Pipeline.Workspace)\${{ parameters.artifactName }}'
Expand Down
26 changes: 26 additions & 0 deletions eng/pipelines/onebranch/scripts/compute-versions.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@
- VersionRevision
- SqlClientPackageVersion
- SqlServerPackageVersion
- SqlClientApiScanVersion
- SqlServerApiScanVersion

.PARAMETER ProjectPath
Absolute or relative path to the repository build.proj file.
Expand Down Expand Up @@ -273,6 +275,28 @@ function Add-VersionBuildNumber {
return $Version
}

<#
.SYNOPSIS
Extracts the major.minor components from a package version.

.PARAMETER Version
Package version beginning with a numeric major.minor pair.

.OUTPUTS
The major.minor version pair.
#>
function Get-MajorMinorVersion {
param(
[string]$Version
)

if ($Version -notmatch "^(\d+)\.(\d+)(?:\.|-|$)") {
throw "Unable to derive a major.minor version from package version '$Version'."
}

return "$($Matches[1]).$($Matches[2])"
}

<#
.SYNOPSIS
Emits an Azure DevOps job output variable for consumption by downstream stages.
Expand Down Expand Up @@ -351,4 +375,6 @@ Write-Host " SqlServer: $sqlServerPackageVersion"

Set-PipelineOutputVariable -Name "SqlClientPackageVersion" -Value $sqlClientPackageVersion
Set-PipelineOutputVariable -Name "SqlServerPackageVersion" -Value $sqlServerPackageVersion
Set-PipelineOutputVariable -Name "SqlClientApiScanVersion" -Value (Get-MajorMinorVersion -Version $sqlClientPackageVersion)
Set-PipelineOutputVariable -Name "SqlServerApiScanVersion" -Value (Get-MajorMinorVersion -Version $sqlServerPackageVersion)
Comment thread
paulmedynski marked this conversation as resolved.
Set-PipelineOutputVariable -Name "VersionRevision" -Value $fileVersionBuildNumber
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ Describe 'compute-versions.ps1 Effective Versions' {

$output | Should -Match "SqlClientPackageVersion;isOutput=true]7\.1\.0-preview3\.$script:testBuildNumberPattern"
$output | Should -Match "SqlServerPackageVersion;isOutput=true]1\.1\.0-preview1\.$script:testBuildNumberPattern"
$output | Should -Match 'SqlClientApiScanVersion;isOutput=true]7\.1'
$output | Should -Match 'SqlServerApiScanVersion;isOutput=true]1\.1'
$output | Should -Match "VersionRevision;isOutput=true]$script:testFileVersionBuildNumber"
}

Expand All @@ -93,6 +95,7 @@ Describe 'compute-versions.ps1 Effective Versions' {

$output | Should -Match 'SqlClientPackageVersion;isOutput=true]7\.1\.0\.42-preview3'
$output | Should -Match 'SqlServerPackageVersion;isOutput=true]1\.0\.0'
$output | Should -Match 'SqlServerApiScanVersion;isOutput=true]1\.0'
$output | Should -Not -Match 'SqlServerPackageVersion;isOutput=true]1\.0\.0\.42'
}

Expand Down
14 changes: 4 additions & 10 deletions eng/pipelines/onebranch/sqlclient-non-official.yml
Original file line number Diff line number Diff line change
Expand Up @@ -144,16 +144,10 @@ extends:
# Use pre-release mode for non-official pipelines.
modeType: prerelease

# We have a single "name" registered with APIScan for all of our packages.
#
# https://eng.ms/docs/products/apiscan/onboard/requirements/registersoftware
#
softwareName: Microsoft.Data.SqlClient

# Similar to the software name, we have a single version registered as well. This has
# nothing to do with the NuGet package version. It is purely an APIScan registration
# value that points to our backend configuration.
versionNumber: $(ApiScanSoftwareVersion)
# The APIScan software name and version are NOT set here. Each package is registered with
# APIScan under its own name/version pair, so every build job sets ob_sdl_apiscan_softwareName
# and ob_sdl_apiscan_versionNumber for the package it builds (see build-buildproj-job.yml).
# Jobs that produce no assemblies disable APIScan instead, via ob_sdl_apiscan_enabled.

# We want the standard level of logging.
verbosityLevel: standard
Expand Down
14 changes: 4 additions & 10 deletions eng/pipelines/onebranch/sqlclient-official.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,10 @@ extends:
# Use release mode for official pipelines.
modeType: release

# We have a single "name" registered with APIScan for all of our packages.
#
# https://eng.ms/docs/products/apiscan/onboard/requirements/registersoftware
#
softwareName: Microsoft.Data.SqlClient

# Similar to the software name, we have a single version registered as well. This has
# nothing to do with the NuGet package version. It is purely an APIScan registration
# value that points to our backend configuration.
versionNumber: $(ApiScanSoftwareVersion)
# The APIScan software name and version are NOT set here. Each package is registered with
# APIScan under its own name/version pair, so every build job sets ob_sdl_apiscan_softwareName
# and ob_sdl_apiscan_versionNumber for the package it builds (see build-buildproj-job.yml).
# Jobs that produce no assemblies disable APIScan instead, via ob_sdl_apiscan_enabled.

# We want the standard level of logging.
verbosityLevel: standard
Expand Down
16 changes: 16 additions & 0 deletions eng/pipelines/onebranch/stages/build-stages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,18 @@ stages:
value: $[ stageDependencies.compute_versions.compute_versions_job.outputs['versions.SqlClientPackageVersion'] ]
- name: sqlServerPackageVersion
value: $[ stageDependencies.compute_versions.compute_versions_job.outputs['versions.SqlServerPackageVersion'] ]
- name: sqlClientApiScanVersion
value: $[ stageDependencies.compute_versions.compute_versions_job.outputs['versions.SqlClientApiScanVersion'] ]
- name: sqlServerApiScanVersion
value: $[ stageDependencies.compute_versions.compute_versions_job.outputs['versions.SqlServerApiScanVersion'] ]

jobs:
# Build Microsoft.Data.SqlClient.Internal.Logging
- template: /eng/pipelines/onebranch/jobs/build-buildproj-job.yml@self
parameters:
apiScanDllPath: '$(REPO_ROOT)/apiScan/Microsoft.Data.SqlClient.Internal.Logging/dlls'
apiScanPdbPath: '$(REPO_ROOT)/apiScan/Microsoft.Data.SqlClient.Internal.Logging/pdbs'
apiScanSoftwareVersion: '$(sqlClientApiScanVersion)'
shouldSignPackage: ${{ parameters.isOfficial }}
signingAppRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
signingAppRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
Expand All @@ -115,6 +120,7 @@ stages:
parameters:
apiScanDllPath: '$(REPO_ROOT)/apiScan/Microsoft.SqlServer.Server/dlls'
apiScanPdbPath: '$(REPO_ROOT)/apiScan/Microsoft.SqlServer.Server/pdbs'
apiScanSoftwareVersion: '$(sqlServerApiScanVersion)'
shouldSignPackage: ${{ parameters.isOfficial }}
signingAppRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
signingAppRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
Expand Down Expand Up @@ -146,13 +152,16 @@ stages:
value: $[ stageDependencies.compute_versions.compute_versions_job.outputs['versions.VersionRevision'] ]
- name: sqlClientPackageVersion
value: $[ stageDependencies.compute_versions.compute_versions_job.outputs['versions.SqlClientPackageVersion'] ]
- name: sqlClientApiScanVersion
value: $[ stageDependencies.compute_versions.compute_versions_job.outputs['versions.SqlClientApiScanVersion'] ]

jobs:
# Build Microsoft.Data.SqlClient.Extensions.Abstractions
- template: /eng/pipelines/onebranch/jobs/build-buildproj-job.yml@self
parameters:
apiScanDllPath: '$(REPO_ROOT)/apiScan/Microsoft.Data.SqlClient.Extensions.Abstractions/dlls'
apiScanPdbPath: '$(REPO_ROOT)/apiScan/Microsoft.Data.SqlClient.Extensions.Abstractions/pdbs'
apiScanSoftwareVersion: '$(sqlClientApiScanVersion)'
shouldSignPackage: ${{ parameters.isOfficial }}
signingAppRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
signingAppRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
Expand Down Expand Up @@ -189,13 +198,16 @@ stages:
value: $[ stageDependencies.compute_versions.compute_versions_job.outputs['versions.SqlClientPackageVersion'] ]
- name: sqlServerPackageVersion
value: $[ stageDependencies.compute_versions.compute_versions_job.outputs['versions.SqlServerPackageVersion'] ]
- name: sqlClientApiScanVersion
value: $[ stageDependencies.compute_versions.compute_versions_job.outputs['versions.SqlClientApiScanVersion'] ]

jobs:
# Build Microsoft.Data.SqlClient
- template: /eng/pipelines/onebranch/jobs/build-buildproj-job.yml@self
parameters:
apiScanDllPath: '$(REPO_ROOT)/apiScan/Microsoft.Data.SqlClient/dlls'
apiScanPdbPath: '$(REPO_ROOT)/apiScan/Microsoft.Data.SqlClient/pdbs'
apiScanSoftwareVersion: '$(sqlClientApiScanVersion)'
shouldSignPackage: ${{ parameters.isOfficial }}
signingAppRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
signingAppRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
Expand Down Expand Up @@ -233,6 +245,7 @@ stages:
parameters:
apiScanDllPath: '$(REPO_ROOT)/apiScan/Microsoft.Data.SqlClient.Extensions.Azure/dlls'
apiScanPdbPath: '$(REPO_ROOT)/apiScan/Microsoft.Data.SqlClient.Extensions.Azure/pdbs'
apiScanSoftwareVersion: '$(sqlClientApiScanVersion)'
shouldSignPackage: ${{ parameters.isOfficial }}
signingAppRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
signingAppRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
Expand Down Expand Up @@ -271,12 +284,15 @@ stages:
value: $[ stageDependencies.compute_versions.compute_versions_job.outputs['versions.SqlClientPackageVersion'] ]
- name: sqlServerPackageVersion
value: $[ stageDependencies.compute_versions.compute_versions_job.outputs['versions.SqlServerPackageVersion'] ]
- name: sqlClientApiScanVersion
value: $[ stageDependencies.compute_versions.compute_versions_job.outputs['versions.SqlClientApiScanVersion'] ]

jobs:
- template: /eng/pipelines/onebranch/jobs/build-buildproj-job.yml@self
parameters:
apiScanDllPath: '$(REPO_ROOT)/apiScan/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider/dlls'
apiScanPdbPath: '$(REPO_ROOT)/apiScan/Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider/pdbs'
apiScanSoftwareVersion: '$(sqlClientApiScanVersion)'
shouldSignPackage: ${{ parameters.isOfficial }}
signingAppRegistrationClientId: '${{ parameters.signingAppRegistrationClientId }}'
signingAppRegistrationTenantId: '${{ parameters.signingAppRegistrationTenantId }}'
Expand Down
5 changes: 0 additions & 5 deletions eng/pipelines/onebranch/variables/onebranch-variables.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,6 @@ variables:
- name: Packaging.EnableSBOMSigning
value: true

# Keep this as a runtime variable reference in globalSdl.apiscan.versionNumber. Passing the
# quoted value directly through an Azure template expression perturbs '6.10' to the number 6.1.
- name: ApiScanSoftwareVersion
value: '6.10'

# OneBranch supplies a variety of container images we must use for our jobs.

# Windows jobs use this image.
Expand Down
Loading