Split x64/arm64 builds into parallel pipeline stages (#14497)

* Split x64/arm64 builds into parallel pipeline stages

Restructure the CI/CD pipeline to build x64 and arm64 in parallel
instead of sequentially, reducing end-to-end build time.

Pipeline shapes:
- PR: build_x64 ∥ build_arm64 → test (uses installer.msix directly)
- Nightly: build_x64 ∥ build_arm64 → package → test (dev-cert bundle)
- Release: build_x64 ∥ build_arm64 → package → test (ESRP-signed bundle)

Key changes:
- Extract shared build-job.yml template parameterized by platform
- Add package-stage.yml that creates msixbundle from both platform
  artifacts, ESRP-signs for release, dev-cert signs for nightly
- PR tests run immediately after x64 build using installer.msix
  (no package stage, no bundle needed)
- Release/nightly tests wait for the package stage and test the real
  signed bundle that gets published
- CloudTest configs are parameterized: release tests pull the bundle
  from the [package] artifact, PR tests use installer.msix from [drop]
- arm64 + formatting checks always run in parallel with x64 but don't
  block the PR test gate
- CodeQL runs in the arm64 stage (off the critical path)
- flight-stage and nuget-stage updated for new stage names

* formatting

* Remove redundant runtime conditions on release-only tasks

These tasks are already wrapped in compile-time conditionals which
prevent them from being added to the pipeline definition for
non-release builds. The runtime condition checks can never evaluate
to false at that point, so they are pure noise.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address review feedback from OneBlue

- Remove wslcsdk NuGet staging (wslc is not in master)
- Always include [package] provider in TestMap.xml.in instead of
  conditionally injecting via PACKAGE_PROVIDER_BLOCK cmake variable.
  PR builds simply use [drop] as TEST_PACKAGE_PROVIDER; the [package]
  provider exists but is unused.
- Add BUNDLE_ONLY cmake option so the package pipeline stage reuses
  cmake's existing bundle target instead of forking makeappx logic.
  This locks the SDK version via cmake (CMAKE_SYSTEM_VERSION) and
  keeps bundle creation logic in one place (msixinstaller/CMakeLists.txt).
  The pipeline now copies msix files to expected paths, runs a fast
  cmake configure with -DBUNDLE_ONLY=TRUE, and builds the bundle target.
- Remove dead NuGet binary restore step in package stage.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Address PR review feedback

- Fix PACKAGE_VERSION regex: escape dots so only A.B.C.D is accepted
- Consolidate CMake defaults (build type, config types, output dir)
  before BUNDLE_ONLY block to avoid duplication
- Nightly tests now use the full bundle from the package stage instead
  of installer.msix (new INCLUDE_PACKAGE_STAGE cmake variable)
- Package stage reuses version output from build stage instead of
  recomputing it

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Ben Hillis <benhill@ntdev.microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Ben Hillis
2026-04-09 13:31:55 -07:00
committed by GitHub
parent b7735bba18
commit 6bc39a6bd7
13 changed files with 649 additions and 370 deletions

266
.pipelines/build-job.yml Normal file
View File

@@ -0,0 +1,266 @@
# Shared build job template for x64 and arm64 platforms.
# Parameterized by platform, with optional test artifact and CodeQL support.
parameters:
- name: platform
type: string
- name: isRelease
type: boolean
- name: isNightly
type: boolean
- name: packageVersion
type: string
- name: traceLoggingConfig
type: string
default: ''
- name: targets
type: object
- name: pool
type: string
default: ''
- name: vsoOrg
type: string
- name: vsoProject
type: string
- name: artifactSuffix
type: string
- name: esrp
type: object
# x64-only features
- name: includeTestArtifacts
type: boolean
default: false
- name: includeCodeQL
type: boolean
default: false
- name: dependsOn
type: string
default: ''
jobs:
- job: build_${{ parameters.platform }}
displayName: "Build WSL package (${{ parameters.platform }})"
timeoutInMinutes: 120
${{ if ne(parameters.dependsOn, '') }}:
dependsOn: ${{ parameters.dependsOn }}
${{ 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: '${{ parameters.artifactSuffix }}'
packageStagingDir: '$(Build.SourcesDirectory)\packageStagingDir'
${{ if parameters.includeTestArtifacts }}:
ob_sdl_codeSignValidation_excludes: -|**testbin\**
${{ if parameters.includeCodeQL }}:
Codeql.PublishDatabaseLog: true
Codeql.SourceRoot: src
${{ if eq(parameters.isRelease, true) }}:
packageInputDirArg: '-DPACKAGE_INPUT_DIR=$(packageStagingDir)'
${{ else }}:
packageInputDirArg: ''
steps:
- ${{ if parameters.includeCodeQL }}:
- task: CodeQL3000Init@0
inputs:
Enabled: ${{ and(parameters.isNightly, eq(variables['Build.SourceBranch'], 'refs/heads/main'))}}
- ${{ if eq(parameters.isRelease, true) }}:
- task: UseDotNet@2
displayName: Install .NET Core SDK (required by EsrpCodeSigning)
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 }}'))"
- task: CMake@1
displayName: "CMake ${{ parameters.platform }}"
inputs:
workingDirectory: "."
cmakeArgs: . --fresh -A ${{ parameters.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 }} -DINCLUDE_PACKAGE_STAGE=${{ or(parameters.isRelease, parameters.isNightly) }} -DPIPELINE_BUILD_ID=$(Build.BuildId) -DVSO_ORG=${{ parameters.vsoOrg }} -DVSO_PROJECT=${{ parameters.vsoProject }} -DWSL_BUILD_WSL_SETTINGS=true $(packageInputDirArg)\${{ parameters.platform }}
# Workaround for WSL Settings NuGet restore authentication issue
- script: _deps\nuget.exe restore -NonInteractive
- ${{ each target in parameters.targets }}:
- script: cmake --build . --config Release --target ${{ target.target }} -- -m
displayName: "Build ${{ target.target }} (${{ parameters.platform }})"
- ${{ if eq(parameters.isRelease, true) }}:
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5
displayName: "Sign ${{ target.target }} (${{ parameters.platform }})"
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\\${{ parameters.platform }}\\Release"
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"
}
]
- task: PowerShell@2
displayName: "Copy signed ${{ target.target }} to staging (${{ parameters.platform }})"
inputs:
targetType: inline
script: |
$arch = '${{ parameters.platform }}'
$pattern = '${{ target.pattern }}'
$inputDir = "bin\$arch\Release"
$outputDir = "$(packageStagingDir)\$arch"
New-Item -ItemType Directory -Path "$outputDir\wslsettings" -Force
foreach ($file in $pattern.Split(',')) {
$sourcePath = Join-Path $inputDir $file
if (Test-Path $sourcePath) {
$destPath = Join-Path $outputDir $file
Write-Host "Copying signed file: $sourcePath -> $destPath"
Copy-Item -Path $sourcePath -Destination $destPath -Force
} else {
Write-Warning "File not found: $sourcePath"
}
}
- script: cmake --build . --config Release -- -m
displayName: "Build remaining targets (${{ parameters.platform }})"
- task: PowerShell@2
displayName: "Stage MSI and installer msix (${{ parameters.platform }})"
inputs:
targetType: inline
script: |
New-Item -ItemType Directory -Path "$(ob_outputDirectory)\bundle" -Force
New-Item -ItemType Directory -Path "$(ob_outputDirectory)\installer" -Force
Copy-Item -Path "bin\${{ parameters.platform }}\release\wsl.msi" -Destination "$(ob_outputDirectory)\bundle\wsl.$(version.WSL_PACKAGE_VERSION).${{ parameters.platform }}.msi"
Copy-Item -Path "bin\${{ parameters.platform }}\release\installer.msix" -Destination "$(ob_outputDirectory)\installer\installer.${{ parameters.platform }}.msix"
if (Test-Path "generated\dev-cert.pfx") { Copy-Item "generated\dev-cert.pfx" "$(ob_outputDirectory)\installer\dev-cert.pfx" }
- powershell: |
$binFolder = ".\bin\${{ parameters.platform }}\Release"
$pdbFolder = Join-Path $(ob_outputDirectory) "pdb\${{ parameters.platform }}\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 (${{ parameters.platform }})
# Test artifacts (x64 only)
- ${{ if parameters.includeTestArtifacts }}:
- 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
mkdir $(ob_outputDirectory)\testbin\x64\release
Move-Item -Path "bin\x64\release\wsltests.dll" -Destination "$(ob_outputDirectory)\testbin\x64\release\wsltests.dll"
Move-Item -Path "bin\x64\release\testplugin.dll" -Destination "$(ob_outputDirectory)\testbin\x64\release\testplugin.dll"
Copy-Item -Path "bin\x64\release\installer.msix" -Destination "$(ob_outputDirectory)\testbin\x64\release\installer.msix"
Move-Item -Path "packages\Microsoft.Taef.$taefVersion\build\Binaries\x64" -Destination "$(ob_outputDirectory)\testbin\x64\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 "diagnostics\wsl.wprp" -Destination "$(ob_outputDirectory)\testbin\wsl.wprp"
Move-Item -Path "test\linux\unit_tests" -Destination "$(ob_outputDirectory)\testbin\unit_tests"
$TestDistroVersion = (Select-Xml -Path packages.config -XPath '/packages/package[@id=''Microsoft.WSL.TestDistro'']/@version').Node.Value
Copy-Item "packages\Microsoft.WSL.TestDistro.$TestDistroVersion\x64\test_distro.tar.xz" "$(ob_outputDirectory)\testbin\x64"
displayName: Stage test artifacts
- task: PublishSymbols@2
displayName: Publish symbols (${{ parameters.platform }})
inputs:
SymbolServerType: "TeamServices"
TreatNotIndexedAsWarning: true
SymbolsProduct: WSL
SymbolsVersion: $(version.WSL_PACKAGE_VERSION)
SearchPattern: |
$(ob_outputDirectory)/pdb/**/*.pdb
- ${{ if ne(parameters.pool, '') }}:
- task: PublishPipelineArtifact@1
inputs:
targetPath: $(ob_outputDirectory)
artifactName: $(ob_artifactBaseName)$(ob_artifactSuffix)
- ${{ if parameters.includeCodeQL }}:
- task: CodeQL3000Finalize@0
condition: ${{ and(parameters.isNightly, eq(variables['Build.SourceBranch'], 'refs/heads/main'))}}

View File

@@ -11,14 +11,18 @@ parameters:
type: boolean
default: false
- name: traceLoggingConfig
type: string
default: ''
- name: nugetPackages
type: object
default:
- Microsoft.WSL.PluginApi.nuspec
- name: traceLoggingConfig
type: string
default: ''
- name: includePackageStage
type: boolean
default: true
- name: targets
type: object
@@ -30,12 +34,6 @@ parameters:
- target: "msipackage"
pattern: "wsl.msi"
- name: platforms
type: object
default:
- x64
- arm64
- name: pool
type: string
default: ''
@@ -62,10 +60,32 @@ parameters:
EsrpClientId: $(EsrpClientId)
stages:
- stage: build
# ── x64 build stage ──────────────────────────────────────────────────
# Runs in parallel with build_arm64. Tests depend on this stage.
- stage: build_x64
dependsOn: []
jobs:
- job:
- template: build-job.yml
parameters:
platform: x64
artifactSuffix: '_build'
isRelease: ${{ parameters.isRelease }}
isNightly: ${{ parameters.isNightly }}
packageVersion: ${{ parameters.packageVersion }}
traceLoggingConfig: ${{ parameters.traceLoggingConfig }}
targets: ${{ parameters.targets }}
pool: ${{ parameters.pool }}
vsoOrg: ${{ parameters.vsoOrg }}
vsoProject: ${{ parameters.vsoProject }}
esrp: ${{ parameters.esrp }}
includeTestArtifacts: true
# ── arm64 build stage (runs in parallel with build_x64) ──────────────
# Includes formatting/localization checks as a first job, then arm64 build.
- stage: build_arm64
dependsOn: []
jobs:
- job: checks
displayName: "Formatting & localization checks"
timeoutInMinutes: 30
@@ -101,328 +121,28 @@ stages:
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 }}:
- template: build-job.yml
parameters:
platform: arm64
artifactSuffix: '_build_arm64'
dependsOn: checks
isRelease: ${{ parameters.isRelease }}
isNightly: ${{ parameters.isNightly }}
packageVersion: ${{ parameters.packageVersion }}
traceLoggingConfig: ${{ parameters.traceLoggingConfig }}
targets: ${{ parameters.targets }}
pool: ${{ parameters.pool }}
vsoOrg: ${{ parameters.vsoOrg }}
vsoProject: ${{ parameters.vsoProject }}
esrp: ${{ parameters.esrp }}
includeCodeQL: true
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
packageStagingDir: '$(Build.SourcesDirectory)\packageStagingDir'
${{ if eq(parameters.isRelease, 'true') }}:
packageInputDirArg: '-DPACKAGE_INPUT_DIR=$(packageStagingDir)'
${{ else }}:
packageInputDirArg: ''
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 $(packageInputDirArg)\${{ platform }}
# 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 }}\\Release"
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"
}
]
- task: PowerShell@2
displayName: "Copy signed ${{ target.target }} to staging (${{ platform }})"
condition: and(succeeded(), eq('${{ parameters.isRelease }}', true))
inputs:
targetType: inline
script: |
$arch = '${{ platform }}'
$pattern = '${{ target.pattern }}'
$inputDir = "bin\$arch\Release"
$outputDir = "$(packageStagingDir)\$arch"
New-Item -ItemType Directory -Path "$outputDir\wslsettings" -Force
foreach ($file in $pattern.Split(',')) {
$sourcePath = Join-Path $inputDir $file
if (Test-Path $sourcePath) {
$destPath = Join-Path $outputDir $file
Write-Host "Copying signed file: $sourcePath -> $destPath"
Copy-Item -Path $sourcePath -Destination $destPath -Force
} else {
Write-Warning "File not found: $sourcePath"
}
}
- 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
# TODO: Add "ARM64" to this list once arm64 testing is supported
foreach ($arch in @("x64"))
{
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\$arch\cloudtest" -Destination "$(ob_outputDirectory)\testbin\$arch\cloudtest"
$TestDistroVersion = (Select-Xml -Path packages.config -XPath '/packages/package[@id=''Microsoft.WSL.TestDistro'']/@version').Node.Value
Copy-Item "packages\Microsoft.WSL.TestDistro.$TestDistroVersion\$arch\test_distro.tar.xz" "$(ob_outputDirectory)\testbin\$arch"
}
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 "diagnostics\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
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'))}}
# ── package stage (release and nightly only) ─────────────────────────
# Creates msixbundle, appxupload, and NuGet packages from both platform artifacts.
- ${{ if parameters.includePackageStage }}:
- template: package-stage.yml
parameters:
isRelease: ${{ parameters.isRelease }}
pool: ${{ parameters.pool }}
esrp: ${{ parameters.esrp }}
nugetPackages: ${{ parameters.nugetPackages }}

View File

@@ -14,9 +14,9 @@ parameters:
stages:
- stage: flight
${{ if eq(parameters.bypassTests, true) }}:
dependsOn: [build]
dependsOn: [package]
${{ else }}:
dependsOn: [test]
dependsOn: [test, package]
jobs:
- job: flight
@@ -30,7 +30,6 @@ stages:
FlightId: $(StoreBrokerFlightId)
StoreBrokerPath: $(Build.SourcesDirectory)\storebroker # location of StoreBroker information in the repo
StoreBrokerPayloadPath: $(Build.ArtifactStagingDirectory)\StoreBrokerPayload # location of package created for flight
WSL_PACKAGE_VERSION: $[ dependencies.build.outputs['version.WSL_PACKAGE_VERSION'] ]
ob_outputDirectory: '$(Build.SourcesDirectory)\out'
ob_artifactBaseName: 'drop_wsl'
ob_artifactSuffix: '_flight'
@@ -55,9 +54,9 @@ stages:
# Download the build drop
- task: DownloadPipelineArtifact@2
displayName: Download Bundle artifact
displayName: Download package artifact
inputs:
artifact: "drop_wsl_build"
artifact: "drop_wsl_package"
path: drop
# copy the appxupload folder to the storebroker folder

View File

@@ -10,7 +10,7 @@ parameters:
stages:
- stage: nuget
dependsOn: [build, test]
dependsOn: [package, test]
jobs:
- job: nuget
displayName: 'Publish nuget packages'
@@ -21,7 +21,7 @@ stages:
type: windows
variables:
WSL_NUGET_PACKAGE_VERSION: $[ dependencies.build.outputs['version.WSL_NUGET_PACKAGE_VERSION'] ]
WSL_NUGET_PACKAGE_VERSION: $[ stageDependencies.package.package.outputs['version.WSL_NUGET_PACKAGE_VERSION'] ]
NUGET_PLUGIN_HANDSHAKE_TIMEOUT_IN_SECONDS: 60
NUGET_PLUGIN_REQUEST_TIMEOUT_IN_SECONDS: 60
ob_outputDirectory: '$(Build.SourcesDirectory)\out'
@@ -32,8 +32,8 @@ stages:
- task: DownloadPipelineArtifact@2
displayName: Download nuget artifacts
inputs:
artifact: "drop_wsl_build"
inputs:
artifact: "drop_wsl_package"
path: drop
# Note: this task might fail if there's been no commits between two nightly pipelines, which is fine.

View File

@@ -0,0 +1,239 @@
parameters:
- name: isRelease
type: boolean
default: true
- name: nugetPackages
type: object
default:
- Microsoft.WSL.PluginApi.nuspec
- name: pool
type: string
default: ''
- 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: package
dependsOn: [build_x64, build_arm64]
jobs:
- job: package
displayName: "Create msixbundle & appxupload"
timeoutInMinutes: 60
${{ if eq(parameters.pool, '') }}:
pool: {'type': 'windows'}
${{ else }}:
pool: ${{ parameters.pool }}
variables:
ob_outputDirectory: '$(Build.SourcesDirectory)\out'
ob_artifactBaseName: 'drop_wsl'
ob_artifactSuffix: '_package'
buildStagePackageVersion: $[ stageDependencies.build_x64.build_x64.outputs['version.WSL_PACKAGE_VERSION'] ]
buildStageNugetVersion: $[ stageDependencies.build_x64.build_x64.outputs['version.WSL_NUGET_PACKAGE_VERSION'] ]
steps:
- task: PowerShell@2
displayName: "Set package version from build stage"
name: version
inputs:
targetType: inline
script: |
Write-Host "##vso[task.setvariable variable=WSL_PACKAGE_VERSION;isOutput=true]$(buildStagePackageVersion)"
Write-Host "##vso[task.setvariable variable=WSL_NUGET_PACKAGE_VERSION;isOutput=true]$(buildStageNugetVersion)"
- task: DownloadPipelineArtifact@2
displayName: Download x64 build artifact
inputs:
artifact: "drop_wsl_build"
path: $(Pipeline.Workspace)\drop_x64
- task: DownloadPipelineArtifact@2
displayName: Download arm64 build artifact
inputs:
artifact: "drop_wsl_build_arm64"
path: $(Pipeline.Workspace)\drop_arm64
- powershell: |
$version = "$(version.WSL_PACKAGE_VERSION)"
# Place per-platform msix files where cmake's bundle target expects them
foreach ($arch in @(
@{platform="x64"; dir="X64"},
@{platform="arm64"; dir="arm64"}
)) {
$dest = "bin\$($arch.dir)\Release"
New-Item -ItemType Directory -Path $dest -Force
Copy-Item "$(Pipeline.Workspace)\drop_$($arch.platform)\installer\installer.$($arch.platform).msix" "$dest\installer.msix"
}
# Copy MSIs to the output bundle directory
$bundleDir = "$(ob_outputDirectory)\bundle"
New-Item -ItemType Directory -Path $bundleDir -Force
Copy-Item "$(Pipeline.Workspace)\drop_x64\bundle\wsl.${version}.x64.msi" "$bundleDir\"
Copy-Item "$(Pipeline.Workspace)\drop_arm64\bundle\wsl.${version}.arm64.msi" "$bundleDir\"
displayName: Stage build artifacts
- task: CMake@1
displayName: "CMake configure (bundle-only)"
inputs:
workingDirectory: "."
cmakeArgs: . -DBUNDLE_ONLY=TRUE -DCMAKE_BUILD_TYPE=Release -DPACKAGE_VERSION=$(version.WSL_PACKAGE_VERSION) -DWSL_NUGET_PACKAGE_VERSION=$(version.WSL_NUGET_PACKAGE_VERSION)
- script: cmake --build . --config Release --target bundle -- -m
displayName: Create msixbundle
- powershell: |
Copy-Item "bundle\Release\*.msixbundle" "$(ob_outputDirectory)\bundle\"
displayName: Copy bundle to output
- ${{ if eq(parameters.isRelease, true) }}:
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5
displayName: "Sign the bundle"
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)\\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"
}
]
- ${{ if not(eq(parameters.isRelease, true)) }}:
- powershell: |
# Sign the bundle with the dev cert from the x64 build
$cert = "$(Pipeline.Workspace)\drop_x64\installer\dev-cert.pfx"
if (-not (Test-Path $cert)) { throw "Dev cert not found at $cert" }
$bundle = Get-ChildItem "$(ob_outputDirectory)\bundle\*.msixbundle" | Select-Object -First 1
$signtool = Get-ChildItem "${env:ProgramFiles(x86)}\Windows Kits\10\bin\*\x64\signtool.exe" -ErrorAction Stop | Sort-Object FullName -Descending | Select-Object -First 1 -ExpandProperty FullName
& $signtool sign /a /v /fd SHA256 /f $cert $bundle.FullName
displayName: Sign bundle with dev cert
- powershell: |
$version = "$(version.WSL_PACKAGE_VERSION)"
# Collect PDBs from both platforms
foreach ($source in @(
@{arch="x64"; drop="$(Pipeline.Workspace)\drop_x64\pdb\x64\Release"},
@{arch="ARM64"; drop="$(Pipeline.Workspace)\drop_arm64\pdb\arm64\Release"}
))
{
$pdbFolder = Join-Path $(ob_outputDirectory) "pdb\$($source.arch)\Release"
New-Item -ItemType Directory -Path $pdbFolder -Force
if (Test-Path $source.drop) {
Copy-Item -Path "$($source.drop)\*" -Destination $pdbFolder -Recurse
}
}
displayName: Collect symbols from both platforms
- powershell: |
$version = "$(version.WSL_PACKAGE_VERSION)"
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}_$arch.zip
Copy-Item -Path appxsym/Microsoft.WSL_${version}_$arch.zip -Destination appxsym/Microsoft.WSL_${version}_$arch.appxsym
}
mkdir $(ob_outputDirectory)/appxupload
Get-ChildItem -Path appxsym/*.appxsym,$(ob_outputDirectory)/bundle/Microsoft.WSL_${version}_x64_ARM64.msixbundle | Compress-Archive -DestinationPath $(ob_outputDirectory)/appxupload/Microsoft.WSL_${version}_x64_ARM64.zip
Move-Item -Path $(ob_outputDirectory)/appxupload/Microsoft.WSL_${version}_x64_ARM64.zip -Destination $(ob_outputDirectory)/appxupload/Microsoft.WSL_${version}_x64_ARM64.appxupload
rm appxsym/*.appxsym
displayName: Create appxupload
condition: and(succeeded(), eq('${{ parameters.isRelease }}', true))
- script: md.exe $(ob_outputDirectory)\nuget
displayName: "Create the nuget directory"
- ${{ each package in parameters.nugetPackages }}:
- script: nuget.exe pack ${{ package }} -OutputDirectory $(ob_outputDirectory)\nuget -NonInteractive
displayName: Build ${{ package }}
- ${{ if eq(parameters.isRelease, true) }}:
- task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5
displayName: "Sign nuget packages"
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)\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"
}
]
- ${{ if ne(parameters.pool, '') }}:
- task: PublishPipelineArtifact@1
inputs:
targetPath: $(ob_outputDirectory)
artifactName: $(ob_artifactBaseName)$(ob_artifactSuffix)

View File

@@ -3,6 +3,10 @@ parameters:
type: boolean
default: false
- name: includePackageStage
type: boolean
default: true
- name: pool
type: string
default: ''
@@ -29,7 +33,10 @@ parameters:
stages:
- stage: test
dependsOn: [build]
${{ if parameters.includePackageStage }}:
dependsOn: [build_x64, package]
${{ else }}:
dependsOn: [build_x64]
jobs:
- ${{ each version in parameters.versions }}:
- ${{ each image in parameters.test_images }}:

View File

@@ -46,7 +46,9 @@ extends:
- template: build-stage.yml@self
parameters:
isRelease: false
includePackageStage: false
- template: test-stage.yml@self
parameters:
includePackageStage: false
rs_prerelease_only: true

View File

@@ -8,11 +8,13 @@ stages:
- template: build-stage.yml@self
parameters:
isRelease: false
includePackageStage: false
pool: 'wsl-build'
vsoOrg: shine-oss
vsoProject: wsl
- template: test-stage.yml@self
parameters:
includePackageStage: false
rs_prerelease_only: true
pool: server

View File

@@ -27,6 +27,36 @@ if (NOT ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION} STREQUAL ${CMAKE_SYSTEM_VERS
message(FATAL_ERROR "Incorrect Windows SDK version: ${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}, requires ${CMAKE_SYSTEM_VERSION}")
endif()
# Default to debug build if unspecified (pipeline always passes -DCMAKE_BUILD_TYPE=Release)
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug")
endif()
# Only generate the build configuration that CMake is configured for
set(CMAKE_CONFIGURATION_TYPES "${CMAKE_BUILD_TYPE}" CACHE STRING "" FORCE)
# Configure output directories
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/${TARGET_PLATFORM})
# BUNDLE_ONLY mode: skip all source builds; only configure the msixbundle target and nuspec files.
# Used by the package pipeline stage to create the bundle from pre-built per-platform msix files.
option(BUNDLE_ONLY "Only configure the msixbundle target, skip all source builds" OFF)
if (BUNDLE_ONLY)
if (NOT PACKAGE_VERSION)
message(FATAL_ERROR "PACKAGE_VERSION is required for BUNDLE_ONLY mode")
endif()
if (NOT PACKAGE_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.([0-9]+)$")
message(FATAL_ERROR "PACKAGE_VERSION is invalid: '${PACKAGE_VERSION}'")
endif()
set(PACKAGE_SIGN_COMMAND echo Skipped package signing for:)
add_subdirectory(nuget)
add_subdirectory(msixinstaller)
return()
endif()
include(FetchContent)
# Import GSL and nlohmannjson
@@ -103,11 +133,6 @@ find_nuget_package(WinUIEx WINUIEX /)
set(WSLG_TS_PLUGIN_DLL "WSLDVCPlugin.dll")
# Default to debug build if unspecified
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Debug")
endif()
set(SUPPORTED_LANGS cs-CZ;da-DK;de-DE;en-GB;en-US;es-ES;fi-FI;fr-FR;hu-HU;it-IT;ja-JP;ko-KR;nb-NO;nl-NL;pl-PL;pt-BR;pt-PT;ru-RU;sv-SE;tr-TR;zh-CN;zh-TW)
if (EXISTS "${CMAKE_CURRENT_LIST_DIR}/UserConfig.cmake")
@@ -120,17 +145,14 @@ if (NOT DEFINED WSL_BUILD_WSL_SETTINGS)
set(WSL_BUILD_WSL_SETTINGS false)
endif ()
# Only generate the build configuration that CMake is configured for
set(CMAKE_CONFIGURATION_TYPES "${CMAKE_BUILD_TYPE}" CACHE STRING "" FORCE)
find_commit_hash(COMMIT_HASH)
if (NOT PACKAGE_VERSION)
find_version(PACKAGE_VERSION WSL_NUGET_PACKAGE_VERSION) # Fetch the package version from git if not specified
endif ()
if (NOT PACKAGE_VERSION MATCHES "^([0-9]+).([0-9]+).([0-9]+).([0-9]+)$")
message(FATAL_ERROR "PACKAGE_VERSION is invalid: '${PACKAGE_VERSION}'. Needs to match '([0-9]+).([0-9]+).([0-9]+).([0-9]+)'")
if (NOT PACKAGE_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.([0-9]+)$")
message(FATAL_ERROR "PACKAGE_VERSION must be four dot-separated numeric components (e.g., '1.2.3.4'): got '${PACKAGE_VERSION}'")
endif()
set(PACKAGE_VERSION_MAJOR ${CMAKE_MATCH_1})
@@ -138,12 +160,11 @@ set(PACKAGE_VERSION_MINOR ${CMAKE_MATCH_2})
set(PACKAGE_VERSION_REVISION ${CMAKE_MATCH_3})
# The store requires the revision number to be 0, so enforce this on official builds
if (OFFICIAL_BUILD AND NOT PACKAGE_VERSION MATCHES "^([0-9]+).([0-9]+).([0-9]+).0$")
if (OFFICIAL_BUILD AND NOT PACKAGE_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.0$")
message(FATAL_ERROR "PACKAGE_VERSION is invalid: '${PACKAGE_VERSION}'. Needs to match '([0-9]+).([0-9]+).([0-9]+).0' for official builds")
endif()
# Configure output directories
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin/${TARGET_PLATFORM})
# Configure per-config output directories
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Debug)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/Release)

View File

@@ -24,6 +24,18 @@ else()
set(ALLOW_UNSIGNED_PACKAGE "1")
endif()
# When the package stage is included (release + nightly), test the real bundle from that stage.
# PR builds test the installer.msix directly from the build artifact (no bundle needed).
if (INCLUDE_PACKAGE_STAGE)
set(TEST_PACKAGE_PROVIDER "[package]")
set(TEST_PACKAGE_PATH "bundle\\Microsoft.WSL_${PACKAGE_VERSION}_x64_ARM64.msixbundle")
set(TEST_PACKAGE_FILE "Microsoft.WSL_${PACKAGE_VERSION}_x64_ARM64.msixbundle")
else()
set(TEST_PACKAGE_PROVIDER "[drop]")
set(TEST_PACKAGE_PATH "testbin\\x64\\release\\installer.msix")
set(TEST_PACKAGE_FILE "installer.msix")
endif()
function(add_test_group image version)
set(DIR ${OUT}/${image}-wsl${version})

View File

@@ -5,7 +5,7 @@
</ResourceSpec>
<Setup TimeoutMins="30">
<BuildFiles>
<Copy Src="[drop]\bundle\Microsoft.WSL_${PACKAGE_VERSION}_x64_ARM64.msixbundle" Dest="[WorkingDirectory]" IsRecursive="false"/>
<Copy Src="${TEST_PACKAGE_PROVIDER}\${TEST_PACKAGE_PATH}" Dest="[WorkingDirectory]" IsRecursive="false"/>
<Copy Src="[drop]\testbin\${TARGET_PLATFORM}\release\*" Dest="[WorkingDirectory]\" IsRecursive="true" Writable="true"/>
<Copy Src="[drop]\testbin\${TARGET_PLATFORM}\test_distro.tar.xz" Dest="[WorkingDirectory]" IsRecursive="false" Writable="true"/>
<Copy Src="[drop]\testbin\test-setup.ps1" Dest="[WorkingDirectory]\" IsRecursive="false" />
@@ -21,6 +21,6 @@
</Setup>
<TestJob Name="CloudTest.Taef" TimeoutMins="240">
<Execution Type="TAEF" Path="[WorkingDirectory]\wsltests.dll" Args="/p:bugReportDirectory=[LoggingDirectory]\BugReportOutput /errorOnCrash /testmode:etwlogger /EtwLogger:WPRProfileFile=[WorkingDirectory]\wsl.wprp /EtwLogger:WPRProfile=WSL /EtwLogger:SavePoint=ExecutionComplete /EtwLogger:RecordingScope=Execution /p:SetupScript=.\test-setup.ps1 /p:Package=[WorkingDirectory]\Microsoft.WSL_${PACKAGE_VERSION}_x64_ARM64.msixbundle /p:Version=${version} /p:AllowUnsigned=${ALLOW_UNSIGNED_PACKAGE} /p:UnitTestsPath=[WorkingDirectory]\unit_tests /p:DistroPath=[WorkingDirectory]\test_distro.tar.xz /p:DistroName=test_distro /logOutput:High /p:RedirectStdout=[LoggingDirectory]\stdout.txt /p:RedirectStderr=[LoggingDirectory]\stderr.txt /p:KernelLogs=[LoggingDirectory]\dmesg.txt /p:DumpFolder=[LoggingDirectory] /p:WerReport /p:LogDmesg /p:PipelineBuildId=${PIPELINE_BUILD_ID} /p:DumpTool=DumpTool.exe" />
<Execution Type="TAEF" Path="[WorkingDirectory]\wsltests.dll" Args="/p:bugReportDirectory=[LoggingDirectory]\BugReportOutput /errorOnCrash /testmode:etwlogger /EtwLogger:WPRProfileFile=[WorkingDirectory]\wsl.wprp /EtwLogger:WPRProfile=WSL /EtwLogger:SavePoint=ExecutionComplete /EtwLogger:RecordingScope=Execution /p:SetupScript=.\test-setup.ps1 /p:Package=[WorkingDirectory]\${TEST_PACKAGE_FILE} /p:Version=${version} /p:AllowUnsigned=${ALLOW_UNSIGNED_PACKAGE} /p:UnitTestsPath=[WorkingDirectory]\unit_tests /p:DistroPath=[WorkingDirectory]\test_distro.tar.xz /p:DistroName=test_distro /logOutput:High /p:RedirectStdout=[LoggingDirectory]\stdout.txt /p:RedirectStderr=[LoggingDirectory]\stderr.txt /p:KernelLogs=[LoggingDirectory]\dmesg.txt /p:DumpFolder=[LoggingDirectory] /p:WerReport /p:LogDmesg /p:PipelineBuildId=${PIPELINE_BUILD_ID} /p:DumpTool=DumpTool.exe" />
</TestJob>
</TestJobGroup>

View File

@@ -9,6 +9,13 @@
<Add Name="PipelineArtifactName" Value="drop_wsl_build"/>
</Properties>
</Provider>
<Provider Type="PipelineArtifacts">
<Properties>
<Add Name="CloudTest.ProviderCustomName" Value="[package]" />
<Add Name="PipelineArtifactBuildUrl" Value="https://${VSO_ORG}.visualstudio.com/${VSO_PROJECT}/_build/results?buildId=${PIPELINE_BUILD_ID}"/>
<Add Name="PipelineArtifactName" Value="drop_wsl_package"/>
</Properties>
</Provider>
<Provider Type="VSODrop">
<Properties>
<Add Name="CloudTest.ProviderCustomName" Value="[test_distro]" />

View File

@@ -1,16 +1,18 @@
set(DEPENDENCIES "wsl.exe;wslinstaller.exe;wslinstallerproxystub.dll")
if (NOT BUNDLE_ONLY)
set(DEPENDENCIES "wsl.exe;wslinstaller.exe;wslinstallerproxystub.dll")
# Don't include the MSI if building a thin package.
if (NOT "${WSL_BUILD_THIN_PACKAGE}")
list(APPEND DEPENDENCIES "wsl.msi")
# Don't include the MSI if building a thin package.
if (NOT "${WSL_BUILD_THIN_PACKAGE}")
list(APPEND DEPENDENCIES "wsl.msi")
endif()
add_appx_target(msixinstallerpackage
"${DEPENDENCIES}"
"${CMAKE_CURRENT_LIST_DIR}/AppxManifest.in"
"${BIN}/installer.msix"
"wsl;wslinstaller;msipackage;wslinstallerproxystub")
endif()
add_appx_target(msixinstallerpackage
"${DEPENDENCIES}"
"${CMAKE_CURRENT_LIST_DIR}/AppxManifest.in"
"${BIN}/installer.msix"
"wsl;wslinstaller;msipackage;wslinstallerproxystub")
set(ARM64_BUNDLE_PATH ${CMAKE_SOURCE_DIR}/bin/arm64/${CMAKE_BUILD_TYPE}/installer.msix)
set(X64_BUNDLE_PATH ${CMAKE_SOURCE_DIR}/bin/X64/${CMAKE_BUILD_TYPE}/installer.msix)
@@ -38,6 +40,8 @@ if ((TARGET_PLATFORM STREQUAL "arm64" AND EXISTS ${X64_BUNDLE_PATH}) OR (TARGET_
set_source_files_properties(${OUTPUT_BUNDLE} PROPERTIES GENERATED TRUE)
add_custom_target(bundle DEPENDS ${OUTPUT_BUNDLE})
add_dependencies(bundle msixinstallerpackage)
if (NOT BUNDLE_ONLY)
add_dependencies(bundle msixinstallerpackage)
endif()
set_target_properties(bundle PROPERTIES EXCLUDE_FROM_ALL FALSE)
endif()