WSL/.pipelines/build-stage.yml
2025-12-02 20:05:14 -08:00

414 lines
21 KiB
YAML

parameters:
- name: isRelease
type: boolean
default: true
- name: packageVersion
type: string
default: ""
- name: isNightly
type: boolean
default: false
- name: nugetPackages
type: object
default:
- Microsoft.WSL.PluginApi.nuspec
- name: traceLoggingConfig
type: string
default: ''
- name: targets
type: object
default:
- target: "wsl;libwsl;wslg;wslservice;wslhost;wslrelay;wslinstaller;wslinstall;initramfs;wslserviceproxystub;wslsettings;wslinstallerproxystub;testplugin"
pattern: "wsl.exe,libwsl.dll,wslg.exe,wslservice.exe,wslhost.exe,wslrelay.exe,wslinstaller.exe,wslinstall.dll,wslserviceproxystub.dll,wslsettings.dll,wslsettings.exe,wslinstallerproxystub.dll,wsldevicehost.dll,WSLDVCPlugin.dll,testplugin.dll,wsldeps.dll"
- target: "msixgluepackage"
pattern: "gluepackage.msix"
- target: "msipackage"
pattern: "wsl.msi"
- name: platforms
type: object
default:
- x64
- arm64
- name: pool
type: string
default: ''
- name: vsoOrg
type: string
- name: vsoProject
type: string
- name: esrp
type: object
default:
ConnectedServiceName: "AzureConnection-AME"
signConfigType: "inlineSignParams"
SessionTimeout: 60
MaxConcurrency: 50
MaxRetryAttempts: 5
ServiceEndpointUrl: $(EsrpServiceEndpointUrl)
AuthAKVName: $(EsrpAuthAKVName)
AuthSignCertName: $(EsrpAuthSignCertName)
AppRegistrationClientId: $(EsrpAppRegistrationClientId)
AppRegistrationTenantId: $(EsrpAppRegistrationTenantId)
EsrpClientId: $(EsrpClientId)
stages:
- stage: build
jobs:
- job:
displayName: "Formatting & localization checks"
timeoutInMinutes: 30
variables:
ob_outputDirectory: '$(Build.SourcesDirectory)\out'
${{ if eq(parameters.pool, '') }}:
pool: {'type': 'windows'}
${{ else }}:
pool: ${{ parameters.pool }}
steps:
- script: python tools/devops/validate-localization.py localization/strings en-US
displayName: Validate localization resources
- script: python tools\devops\validate-copyright-headers.py src
displayName: Validate copyright headers (src/)
- script: python tools\devops\validate-copyright-headers.py test
displayName: Validate copyright headers (test/)
- task: CMake@1
displayName: "CMake ."
inputs:
workingDirectory: "."
cmakeArgs: .
- task: PowerShell@2
inputs:
targetType: "filePath"
filePath: FormatSource.ps1
arguments: "-ModifiedOnly $false -Verify $true"
displayName: "Clang-format check"
- job: build
displayName: "Build WSL package"
timeoutInMinutes: 120
${{ if eq(parameters.pool, '') }}:
pool: {'type': 'windows'}
${{ else }}:
pool: ${{ parameters.pool }}
variables:
NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS: 60
NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS: 60
ob_outputDirectory: '$(Build.SourcesDirectory)\out'
ob_artifactBaseName: 'drop_wsl'
ob_artifactSuffix: '_build'
ob_sdl_codeSignValidation_excludes: -|**testbin\**
Codeql.PublishDatabaseLog: true
Codeql.SourceRoot: src
steps:
- task: CodeQL3000Init@0
inputs:
Enabled: ${{ and(parameters.isNightly, eq(variables['Build.SourceBranch'], 'refs/heads/main'))}}
- task: UseDotNet@2
displayName: Install .NET Core SDK (required by EsrpCodeSigning)
condition: and(succeeded(), eq('${{ parameters.isRelease }}', true))
inputs:
packageType: "sdk"
- task: PowerShell@2
displayName: Set trace logging configuration
condition: ne('${{ parameters.traceLoggingConfig }}', '')
inputs:
targetType: 'inline'
script: 'Set-Content -Path src/windows/inc/traceloggingconfig.h -Value $env:config.replace("\n", "`n")'
env:
config: '${{ parameters.traceLoggingConfig }}'
- task: PowerShell@2
displayName: "Compute package version"
name: version
inputs:
targetType: inline
${{ if eq(parameters.packageVersion, '') }}:
script: |
$gitversion_version = (Select-Xml -Path packages.config -XPath '/packages/package[@id=''GitVersion.CommandLine'']/@version').Node.Value
$env:path = "packages/GitVersion.CommandLine.$gitversion_version/tools;$env:path"
. .\tools\devops\version_functions.ps1
$version = Get-VersionInfo -Nightly $${{ parameters.isNightly }}
Write-Host "##vso[task.setvariable variable=WSL_PACKAGE_VERSION;isOutput=true]$($version.MsixVersion)"
Write-Host "##vso[task.setvariable variable=WSL_NUGET_PACKAGE_VERSION;isOutput=true]$($version.NugetVersion)"
${{ else }}:
script: |
Write-Host "##vso[task.setvariable variable=WSL_PACKAGE_VERSION;isOutput=true]$([string]('${{ parameters.packageVersion }}' + '.0'))"
Write-Host "##vso[task.setvariable variable=WSL_NUGET_PACKAGE_VERSION;isOutput=true]$([string]('${{ parameters.packageVersion }}'))"
- ${{ each platform in parameters.platforms }}:
- task: CMake@1
displayName: "CMake ${{ platform }}"
inputs:
workingDirectory: "."
cmakeArgs: . --fresh -A ${{ platform }} -DCMAKE_BUILD_TYPE=Release -DCMAKE_SYSTEM_VERSION=10.0.26100.0 -DPACKAGE_VERSION=$(version.WSL_PACKAGE_VERSION) -DWSL_NUGET_PACKAGE_VERSION=$(version.WSL_NUGET_PACKAGE_VERSION) -DSKIP_PACKAGE_SIGNING=${{ parameters.isRelease }} -DOFFICIAL_BUILD=${{ parameters.isRelease }} -DPIPELINE_BUILD_ID=$(Build.BuildId) -DVSO_ORG=${{ parameters.vsoOrg }} -DVSO_PROJECT=${{ parameters.vsoProject }} -DWSL_BUILD_WSL_SETTINGS=true
# This additional Restore NuGet package task is added as a workaround for WSL Settings to have its packages restored properly.
# Without this, building wsl settings may encounter the following error:
#
# The plugin credential provider could not acquire credentials. Authentication may require manual action.
# Consider re-running the command with --interactive for `dotnet`, /p:NuGetInteractive="true" for MSBuild or removing the -NonInteractive switch for `NuGet`
# Response status code does not indicate success: 401 (Unauthorized)
- script: _deps\nuget.exe restore -NonInteractive
- ${{ each target in parameters.targets }}:
- script: cmake --build . --config Release --target ${{ target.target }} -- -m
condition: and(succeeded(), eq('${{ parameters.isRelease }}', true))
displayName: "Build ${{ target.target }} (${{ platform }})"
- ${{ if eq(parameters.isRelease, 'true') }}:
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5
displayName: "Sign ${{ target.target }} (${{ platform }})"
condition: and(succeeded(), eq('${{ parameters.isRelease }}', true))
inputs:
ConnectedServiceName: ${{ parameters.esrp.ConnectedServiceName}}
signConfigType: ${{ parameters.esrp.signConfigType }}
SessionTimeout: ${{ parameters.esrp.SessionTimeout }}
MaxConcurrency: ${{ parameters.esrp.MaxConcurrency }}
MaxRetryAttempts: ${{ parameters.esrp.MaxRetryAttempts }}
ServiceEndpointUrl: ${{ parameters.esrp.ServiceEndpointUrl }}
AuthAKVName: ${{ parameters.esrp.AuthAKVName }}
AuthSignCertName: ${{ parameters.esrp.AuthSignCertName }}
AppRegistrationClientId: ${{ parameters.esrp.AppRegistrationClientId }}
AppRegistrationTenantId: ${{ parameters.esrp.AppRegistrationTenantId }}
FolderPath: "bin\\${{ platform }}"
Pattern: "${{ target.pattern }}"
UseMSIAuthentication: true
EsrpClientId: ${{ parameters.esrp.EsrpClientId }}
inlineOperation: |
[
{
"KeyCode": "CP-230012",
"OperationCode": "SigntoolSign",
"Parameters" : {
"OpusName" : "Microsoft",
"OpusInfo" : "http://www.microsoft.com",
"FileDigest" : "/fd \"SHA256\"",
"PageHash" : "/NPH",
"TimeStamp" : "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
},
"ToolName" : "sign",
"ToolVersion" : "1.0"
},
{
"KeyCode" : "CP-230012",
"OperationCode" : "SigntoolVerify",
"Parameters" : {},
"ToolName" : "sign",
"ToolVersion" : "1.0"
}
]
# Replace the intermediate wslsettings binaries file with the signed versions so that any future steps building wslsettings will use the signed versions
- task: PowerShell@2
displayName: 'Replace wslsettings binaries in intermediate folder with signed versions'
condition: and(succeeded(), eq('${{ parameters.isRelease }}', true))
inputs:
targetType: inline
script: |
$arch = '${{ platform }}'
$wslsettingsbinpath = "bin\$arch\release\wslsettings"
$wslsettingsobjpath = "src\windows\wslsettings\obj\$arch\release"
# Update the timestamp of wslsettings.exe so that it doesn't get rebuilt
(Get-Item $wslsettingsbinpath\wslsettings.exe).LastWriteTime = Get-Date
Copy-Item $wslsettingsbinpath\wslsettings.dll $wslsettingsobjpath\wslsettings.dll -Force
Copy-Item $wslsettingsbinpath\wslsettings.exe $wslsettingsobjpath\apphost.exe -Force
- script: cmake --build . --config Release -- -m
displayName: "Build installer msix and tests (${{ platform }})"
- task: PowerShell@2
displayName: "Move ${{ platform }} installer msi to output directory"
inputs:
targetType: inline
script: |
New-Item -ItemType Directory -Path "$(ob_outputDirectory)\bundle" -Force
$arch = '${{ platform }}'
Copy-Item -Path "bin\$arch\release\wsl.msi" -Destination "$(ob_outputDirectory)\bundle\wsl.$(version.WSL_PACKAGE_VERSION).$arch.msi"
- ${{ if eq(parameters.isRelease, 'true') }}:
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5
displayName: "Sign the bundle"
condition: and(succeeded(), eq('${{ parameters.isRelease }}', true))
inputs:
ConnectedServiceName: ${{ parameters.esrp.ConnectedServiceName}}
signConfigType: ${{ parameters.esrp.signConfigType }}
SessionTimeout: ${{ parameters.esrp.SessionTimeout }}
MaxConcurrency: ${{ parameters.esrp.MaxConcurrency }}
MaxRetryAttempts: ${{ parameters.esrp.MaxRetryAttempts }}
ServiceEndpointUrl: ${{ parameters.esrp.ServiceEndpointUrl }}
AuthAKVName: ${{ parameters.esrp.AuthAKVName }}
AuthSignCertName: ${{ parameters.esrp.AuthSignCertName }}
AppRegistrationClientId: ${{ parameters.esrp.AppRegistrationClientId }}
AppRegistrationTenantId: ${{ parameters.esrp.AppRegistrationTenantId }}
FolderPath: "bundle"
Pattern: "*.msixbundle"
UseMSIAuthentication: true
EsrpClientId: ${{ parameters.esrp.EsrpClientId }}
inlineOperation: |
[
{
"KeyCode": "CP-230012",
"OperationCode": "SigntoolSign",
"Parameters" : {
"OpusName" : "Microsoft",
"OpusInfo" : "http://www.microsoft.com",
"FileDigest" : "/fd \"SHA256\"",
"PageHash" : "/NPH",
"TimeStamp" : "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256"
},
"ToolName" : "sign",
"ToolVersion" : "1.0"
},
{
"KeyCode" : "CP-230012",
"OperationCode" : "SigntoolVerify",
"Parameters" : {},
"ToolName" : "sign",
"ToolVersion" : "1.0"
}
]
- script: md.exe $(ob_outputDirectory)\bin\nuget
displayName: "Create the nuget directory"
- ${{ each package in parameters.nugetPackages }}:
- script: nuget.exe pack ${{ package }} -OutputDirectory $(ob_outputDirectory)\bin\nuget -NonInteractive
displayName: Build ${{ package }}
- ${{ if eq(parameters.isRelease, 'true') }}:
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5
displayName: "Sign nuget packages"
condition: and(succeeded(), eq('${{ parameters.isRelease }}', true))
inputs:
ConnectedServiceName: ${{ parameters.esrp.ConnectedServiceName}}
signConfigType: ${{ parameters.esrp.signConfigType }}
SessionTimeout: ${{ parameters.esrp.SessionTimeout }}
MaxConcurrency: ${{ parameters.esrp.MaxConcurrency }}
MaxRetryAttempts: ${{ parameters.esrp.MaxRetryAttempts }}
ServiceEndpointUrl: ${{ parameters.esrp.ServiceEndpointUrl }}
AuthAKVName: ${{ parameters.esrp.AuthAKVName }}
AuthSignCertName: ${{ parameters.esrp.AuthSignCertName }}
AppRegistrationClientId: ${{ parameters.esrp.AppRegistrationClientId }}
AppRegistrationTenantId: ${{ parameters.esrp.AppRegistrationTenantId }}
FolderPath: '$(ob_outputDirectory)\bin\nuget'
Pattern: "*.nupkg"
UseMSIAuthentication: true
EsrpClientId: ${{ parameters.esrp.EsrpClientId }}
inlineOperation: |
[
{
"KeyCode": "CP-401405",
"OperationCode": "NuGetSign",
"Parameters" : {},
"ToolName" : "sign",
"ToolVersion" : "1.0"
},
{
"KeyCode" : "CP-401405",
"OperationCode" : "NuGetVerify",
"Parameters" : {},
"ToolName" : "sign",
"ToolVersion" : "1.0"
}
]
- powershell: |
foreach ($arch in @("x64", "ARM64"))
{
$binFolder = ".\bin\$arch\Release"
$pdbFolder = Join-Path $(ob_outputDirectory) "pdb\$arch\Release"
mkdir $pdbFolder
foreach ($filter in @("*.pdb", "*.debug"))
{
foreach ($e in (Get-ChildItem -Recurse -Path $binFolder -Filter $filter)) {Move-Item -Path $e.fullname -Destination (Join-Path $pdbFolder $e.name)}
}
}
displayName: Collect symbols
- powershell: |
mkdir appxsym
foreach ($arch in @("x64", "ARM64"))
{
Get-ChildItem -Path $(ob_outputDirectory)\pdb\$arch\release\*.pdb -Exclude wsltests.pdb | Compress-Archive -DestinationPath appxsym/Microsoft.WSL_$(version.WSL_PACKAGE_VERSION)_$arch.zip
Copy-Item -Path appxsym/Microsoft.WSL_$(version.WSL_PACKAGE_VERSION)_$arch.zip -Destination appxsym/Microsoft.WSL_$(version.WSL_PACKAGE_VERSION)_$arch.appxsym
}
mkdir $(ob_outputDirectory)/appxupload
Get-ChildItem -Path appxsym/*.appxsym,bundle/release/Microsoft.WSL_$(version.WSL_PACKAGE_VERSION)_x64_ARM64.msixbundle | Compress-Archive -DestinationPath $(ob_outputDirectory)/appxupload/Microsoft.WSL_$(version.WSL_PACKAGE_VERSION)_x64_ARM64.zip
Move-Item -Path $(ob_outputDirectory)/appxupload/Microsoft.WSL_$(version.WSL_PACKAGE_VERSION)_x64_ARM64.zip -Destination $(ob_outputDirectory)/appxupload/Microsoft.WSL_$(version.WSL_PACKAGE_VERSION)_x64_ARM64.appxupload
rm appxsym/*.appxsym
displayName: Create appxupload
condition: and(succeeded(), eq('${{ parameters.isRelease }}', true))
- powershell: |
$taefVersion = (Select-Xml -Path packages.config -XPath '/packages/package[@id=''Microsoft.Taef'']/@version').Node.Value
New-Item -ItemType Directory -Path "$(ob_outputDirectory)\bundle" -Force
foreach ($arch in @("x64", "ARM64"))
{
mkdir $(ob_outputDirectory)\testbin\$arch\release
Move-Item -Path "bin\$arch\release\wsltests.dll" -Destination "$(ob_outputDirectory)\testbin\$arch\release\wsltests.dll"
Move-Item -Path "bin\$arch\release\testplugin.dll" -Destination "$(ob_outputDirectory)\testbin\$arch\release\testplugin.dll"
Move-Item -Path "packages\Microsoft.Taef.$taefVersion\build\Binaries\$arch" -Destination "$(ob_outputDirectory)\testbin\$arch\release\taef"
}
Move-Item -Path "bin\x64\cloudtest" -Destination "$(ob_outputDirectory)\testbin\x64\cloudtest"
Move-Item -Path "tools\test\test-setup.ps1" -Destination "$(ob_outputDirectory)\testbin\test-setup.ps1"
Move-Item -Path "tools\test\CloudTest-Setup.bat" -Destination "$(ob_outputDirectory)\testbin\CloudTest-Setup.bat"
Move-Item -Path "tools\wsl.wprp" -Destination "$(ob_outputDirectory)\testbin\wsl.wprp"
Move-Item -Path "test\linux\unit_tests" -Destination "$(ob_outputDirectory)\testbin\unit_tests"
Move-Item -Path bundle\release\* -Destination $(ob_outputDirectory)\bundle
$TestDistroVersion = (Select-Xml -Path packages.config -XPath '/packages/package[@id=''Microsoft.WSL.TestDistro'']/@version').Node.Value
Copy-Item "packages\Microsoft.WSL.TestDistro.$TestDistroVersion\test_distro.tar.xz" "$(ob_outputDirectory)\testbin\x64"
displayName: Move artifacts to drop directory
- task: PublishSymbols@2
displayName: Publish symbols
inputs:
SymbolServerType: "TeamServices"
TreatNotIndexedAsWarning: true
SymbolsProduct: WSL
SymbolsVersion: $(version.WSL_PACKAGE_VERSION)
SearchPattern: |
$(ob_outputDirectory)/pdb/**/*.pdb
$(ob_outputDirectory)/bin/**/*.exe
$(ob_outputDirectory)/bin/**/*.dll
- ${{ if ne(parameters.pool, '') }}:
- task: PublishPipelineArtifact@1
inputs:
targetPath: $(ob_outputDirectory)
artifactName: $(ob_artifactBaseName)$(ob_artifactSuffix)
- task: CodeQL3000Finalize@0
condition: ${{ and(parameters.isNightly, eq(variables['Build.SourceBranch'], 'refs/heads/main'))}}